This commit is contained in:
beard%netscape.com 1998-12-03 22:36:55 +00:00
Родитель 5819efc4cc
Коммит a697e8380d
33 изменённых файлов: 6250 добавлений и 0 удалений

Просмотреть файл

@ -0,0 +1,39 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
AsyncMessage.h
Base class for messages that are executed asynchronously, during MRJSession idle time.
by Patrick C. Beard.
*/
#pragma once
#include "MRJSession.h"
class AsyncMessage : public NativeMessage {
public:
AsyncMessage(MRJSession* session) : mSession(session) {}
virtual ~AsyncMessage() {}
void send();
protected:
MRJSession* mSession;
};

Просмотреть файл

@ -0,0 +1,40 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
JNIThread.java
Provides a communication channel between native threads and Java threads.
by Patrick C. Beard.
*/
package netscape.oji;
public class JNIThread extends Thread {
private int fSecureEnv;
public JNIThread(int secureEnv) {
super("JNIThread->0x" + Integer.toHexString(secureEnv));
fSecureEnv = secureEnv;
setPriority(NORM_PRIORITY);
// setPriority(MAX_PRIORITY);
start();
}
public native void run();
}

Просмотреть файл

@ -0,0 +1,38 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
JNIUtils.java
*/
package netscape.oji;
public class JNIUtils {
/**
* Returns a local reference for a passed-in global reference.
*/
public static Object NewLocalRef(Object object) {
return object;
}
/**
* Returns the currently running thread.
*/
public static Object GetCurrentThread() {
return Thread.currentThread();
}
}

Просмотреть файл

@ -0,0 +1,63 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
JavaMessageQueue.h
*/
#pragma once
#ifndef JNI_H
#include "jni.h"
#endif
class Monitor;
class JavaMessage {
public:
JavaMessage() : mNext(NULL) {}
virtual ~JavaMessage() {}
void setNext(JavaMessage* next) { mNext = next; }
JavaMessage* getNext() { return mNext; }
virtual void execute(JNIEnv* env) = 0;
private:
JavaMessage* mNext;
};
class JavaMessageQueue {
public:
JavaMessageQueue(Monitor* monitor);
void putMessage(JavaMessage* msg);
JavaMessage* getMessage();
void enter();
void exit();
void wait();
void wait(long long millis);
void notify();
private:
// Message queue.
JavaMessage* mFirst;
JavaMessage* mLast;
Monitor* mMonitor;
};

Просмотреть файл

@ -0,0 +1,541 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
LiveConnectNativeMethods.cpp
*/
#include "LiveConnectNativeMethods.h"
#include "nsIPluginManager.h"
#include "nsIJVMManager.h"
#include "nsILiveconnect.h"
#include "MRJPlugin.h"
#include "MRJContext.h"
#include "MRJSession.h"
#include "CSecureJNI2.h"
#include "JavaMessageQueue.h"
#include "MRJMonitor.h"
#include "NativeMonitor.h"
#include "netscape_javascript_JSObject.h" /* javah-generated headers */
extern nsIPluginManager* thePluginManager;
static MRJPlugin* theJVMPlugin = NULL;
static nsILiveconnect* theLiveConnectManager = NULL;
static jclass netscape_javascript_JSObject = NULL;
static jmethodID netscape_javascript_JSObject_JSObject;
static jfieldID netscape_javascript_JSObject_internal;
static jclass netscape_oji_JNIUtils = NULL;
static jmethodID netscape_oji_JNIUtils_NewLocalRef = NULL;
static jmethodID netscape_oji_JNIUtils_GetCurrentThread = NULL;
nsresult InitLiveConnectSupport(MRJPlugin* jvmPlugin)
{
theJVMPlugin = jvmPlugin;
NS_DEFINE_IID(kILiveconnectIID, NS_ILIVECONNECT_IID);
// QI the LiveConnect interface.
nsresult result = thePluginManager->QueryInterface(kILiveconnectIID, &theLiveConnectManager);
if (result != NS_OK)
return result;
// Manually load the required native methods.
static JNINativeMethod nativeMethods[] = {
"getMember", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getMember,
"getSlot", "(I)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_getSlot,
"setMember", "(Ljava/lang/String;Ljava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setMember,
"setSlot", "(ILjava/lang/Object;)V", (void*)&Java_netscape_javascript_JSObject_setSlot,
"removeMember", "(Ljava/lang/String;)V", (void*)&Java_netscape_javascript_JSObject_removeMember,
"call", "(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_call,
"eval", "(Ljava/lang/String;)Ljava/lang/Object;", (void*)&Java_netscape_javascript_JSObject_eval,
"toString", "()Ljava/lang/String;", (void*)&Java_netscape_javascript_JSObject_toString,
"getWindow", "(Ljava/applet/Applet;)Lnetscape/javascript/JSObject;", (void*)&Java_netscape_javascript_JSObject_getWindow,
"finalize", "()V", (void*)&Java_netscape_javascript_JSObject_finalize,
};
JNIEnv* env = NULL;
nsrefcnt count = jvmPlugin->GetJNIEnv(&env);
if (count > 0 && env != NULL) {
jclass classJSObject = env->FindClass("netscape/javascript/JSObject");
if (classJSObject != NULL) {
// register LiveConnect native methods.
netscape_javascript_JSObject = (jclass) env->NewGlobalRef(classJSObject);
env->DeleteLocalRef(classJSObject);
netscape_javascript_JSObject_JSObject = env->GetMethodID(netscape_javascript_JSObject, "<init>", "(I)V");
netscape_javascript_JSObject_internal = env->GetFieldID(netscape_javascript_JSObject, "internal", "I");
env->RegisterNatives(netscape_javascript_JSObject, nativeMethods, sizeof(nativeMethods) / sizeof(JNINativeMethod));
if (env->ExceptionOccurred()) {
env->ExceptionClear();
result = NS_ERROR_FAILURE;
}
}
// load netscape.oji.JNIUtils class.
jclass classJNIUtils = env->FindClass("netscape/oji/JNIUtils");
if (classJNIUtils != NULL) {
netscape_oji_JNIUtils = (jclass) env->NewGlobalRef(classJNIUtils);
env->DeleteLocalRef(classJNIUtils);
netscape_oji_JNIUtils_NewLocalRef = env->GetStaticMethodID(netscape_oji_JNIUtils, "NewLocalRef", "(Ljava/lang/Object;)Ljava/lang/Object;");
netscape_oji_JNIUtils_GetCurrentThread = env->GetStaticMethodID(netscape_oji_JNIUtils, "GetCurrentThread", "()Ljava/lang/Object;");
}
jvmPlugin->ReleaseJNIEnv(env);
}
return result;
}
nsresult ShutdownLiveConnectSupport()
{
if (theLiveConnectManager != NULL) {
theLiveConnectManager->Release();
theLiveConnectManager = NULL;
}
if (theJVMPlugin != NULL) {
theJVMPlugin = NULL;
}
return NS_OK;
}
jobject Wrap_JSObject(JNIEnv* env, jsobject js_obj)
{
jmethodID constructorID = env->GetMethodID(netscape_javascript_JSObject, "<init>", "(I)V");
return env->NewObject(netscape_javascript_JSObject, constructorID, js_obj);
}
jsobject Unwrap_JSObject(JNIEnv* env, jobject java_wrapper_obj)
{
return env->GetIntField(java_wrapper_obj, netscape_javascript_JSObject_internal);
}
static jobject NewLocalRef(JNIEnv* env, jobject global_ref)
{
return env->CallStaticObjectMethod(netscape_oji_JNIUtils, netscape_oji_JNIUtils_NewLocalRef, global_ref);
}
static jobject GetCurrentThread(JNIEnv* env)
{
return env->CallStaticObjectMethod(netscape_oji_JNIUtils, netscape_oji_JNIUtils_GetCurrentThread);
}
/**
* Sends a message by rendezvousing with an existing JavaScript thread, or creates a new one
* if none exists for this thread already.
*/
static void sendMessage(JNIEnv* env, JavaMessage* msg)
{
// the main thread gets its own secure env, so it won't contend with other threads. this
// is needed to handle finalization, which seems to get called from the main thread sometimes.
if (env == theJVMPlugin->getSession()->getMainEnv()) {
static CSecureJNI2* mainEnv = NULL;
if (mainEnv == NULL) {
mainEnv = new CSecureJNI2(NULL, theJVMPlugin, NULL, env);
mainEnv->AddRef();
}
mainEnv->setJavaEnv(env);
mainEnv->sendMessageFromJava(env, msg, true);
return;
}
// If this is a call back into JavaScript from Java, there will be a secureEnv associated with this thread.
jobject thread = GetCurrentThread(env);
CSecureJNI2* secureEnv = GetSecureJNI(env, thread);
env->DeleteLocalRef(thread);
if (secureEnv != NULL) {
secureEnv->sendMessageFromJava(env, msg);
} else {
// spontaneous call in from Java. this communicates with a shared server thread. this is *VERY* slow right now.
static MRJMonitor sharedMonitor(theJVMPlugin->getSession());
// only 1 Java thread can use this at a time.
sharedMonitor.enter();
{
static CSecureJNI2* sharedEnv = NULL;
if (sharedEnv == NULL) {
sharedEnv = new CSecureJNI2(NULL, theJVMPlugin, NULL, env);
sharedEnv->AddRef();
}
sharedEnv->setJavaEnv(env);
sharedEnv->sendMessageFromJava(env, msg);
}
sharedMonitor.exit();
}
}
/****************** Implementation of methods of JSObject *******************/
/*
* Class: netscape_javascript_JSObject
* Method: getMember
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
Java_netscape_javascript_JSObject_getMember(JNIEnv* env,
jobject java_wrapper_obj,
jstring property_name_jstr)
{
if (property_name_jstr == NULL) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "illegal null member name");
return NULL;
}
/* Get the Unicode string for the JS property name */
jboolean is_copy;
const jchar* property_name_ucs2 = env->GetStringChars(property_name_jstr, &is_copy);
jsize property_name_len = env->GetStringLength(property_name_jstr);
jobject member = NULL;
nsresult result = theLiveConnectManager->GetMember(env, Unwrap_JSObject(env, java_wrapper_obj), property_name_ucs2, property_name_len,
NULL, 0, NULL, &member);
if (result != NS_OK) member = NULL;
env->ReleaseStringChars(property_name_jstr, property_name_ucs2);
return member;
}
/*
* Class: netscape_javascript_JSObject
* Method: getSlot
* Signature: (I)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
Java_netscape_javascript_JSObject_getSlot(JNIEnv* env,
jobject java_wrapper_obj,
jint slot)
{
jobject member = NULL;
nsresult result = theLiveConnectManager->GetSlot(env, Unwrap_JSObject(env, java_wrapper_obj), slot, NULL, 0, NULL, &member);
return member;
}
/*
* Class: netscape_javascript_JSObject
* Method: setMember
* Signature: (Ljava/lang/String;Ljava/lang/Object;)V
*/
JNIEXPORT void JNICALL
Java_netscape_javascript_JSObject_setMember(JNIEnv* env,
jobject java_wrapper_obj,
jstring property_name_jstr,
jobject java_obj)
{
if (property_name_jstr == NULL) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "illegal null member name");
return;
}
/* Get the Unicode string for the JS property name */
jboolean is_copy;
const jchar* property_name_ucs2 = env->GetStringChars(property_name_jstr, &is_copy);
jsize property_name_len = env->GetStringLength(property_name_jstr);
jobject member = NULL;
nsresult result = theLiveConnectManager->SetMember(env, Unwrap_JSObject(env, java_wrapper_obj), property_name_ucs2, property_name_len, NULL, 0, NULL, java_obj);
if (result != NS_OK) member = NULL;
env->ReleaseStringChars(property_name_jstr, property_name_ucs2);
}
/*
* Class: netscape_javascript_JSObject
* Method: setSlot
* Signature: (ILjava/lang/Object;)V
*/
JNIEXPORT void JNICALL
Java_netscape_javascript_JSObject_setSlot(JNIEnv* env,
jobject java_wrapper_obj,
jint slot,
jobject java_obj)
{
nsresult result = theLiveConnectManager->SetSlot(env, Unwrap_JSObject(env, java_wrapper_obj), slot, NULL, 0, NULL, java_obj);
}
/*
* Class: netscape_javascript_JSObject
* Method: removeMember
* Signature: (Ljava/lang/String;)V
*/
class RemoveMemberMessage : public JavaMessage {
jsobject mObject;
const jchar* mPropertyName;
jsize mLength;
public:
RemoveMemberMessage(jsobject obj, const jchar* propertyName, jsize length);
virtual void execute(JNIEnv* env);
};
RemoveMemberMessage::RemoveMemberMessage(jsobject obj, const jchar* propertyName, jsize length)
: mObject(obj), mPropertyName(propertyName), mLength(length)
{
}
void RemoveMemberMessage::execute(JNIEnv* env)
{
nsresult result = theLiveConnectManager->RemoveMember(env, mObject, mPropertyName, mLength, NULL, 0, NULL);
}
JNIEXPORT void JNICALL
Java_netscape_javascript_JSObject_removeMember(JNIEnv* env,
jobject java_wrapper_obj,
jstring property_name_jstr)
{
if (property_name_jstr == NULL) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "illegal null member name");
return;
}
/* Get the Unicode string for the JS property name */
jboolean is_copy;
const jchar* property_name_ucs2 = env->GetStringChars(property_name_jstr, &is_copy);
jsize property_name_len = env->GetStringLength(property_name_jstr);
jsobject js_obj = Unwrap_JSObject(env, java_wrapper_obj);
RemoveMemberMessage msg(js_obj, property_name_ucs2, property_name_len);
sendMessage(env, &msg);
env->ReleaseStringChars(property_name_jstr, property_name_ucs2);
}
class CallMessage : public JavaMessage {
jsobject mObject;
const jchar* mFunctionName;
jsize mLength;
jobjectArray mJavaArgs;
jobject* mJavaResult;
public:
CallMessage(jsobject obj, const jchar* functionName, jsize length, jobjectArray java_args, jobject* javaResult);
virtual void execute(JNIEnv* env);
};
CallMessage::CallMessage(jsobject obj, const jchar* functionName, jsize length, jobjectArray javaArgs, jobject* javaResult)
: mObject(obj), mFunctionName(functionName), mLength(length),
mJavaArgs(javaArgs), mJavaResult(javaResult)
{
}
void CallMessage::execute(JNIEnv* env)
{
nsresult status = theLiveConnectManager->Call(env, mObject, mFunctionName, mLength, mJavaArgs, NULL, 0, NULL, mJavaResult);
}
/*
* Class: netscape_javascript_JSObject
* Method: call
* Signature: (Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
Java_netscape_javascript_JSObject_call(JNIEnv* env, jobject java_wrapper_obj,
jstring function_name_jstr, jobjectArray java_args)
{
if (function_name_jstr == NULL) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "illegal null function name");
return NULL;
}
/* Get the Unicode string for the JS function name */
jboolean is_copy;
const jchar* function_name_ucs2 = env->GetStringChars(function_name_jstr, &is_copy);
jsize function_name_len = env->GetStringLength(function_name_jstr);
jsobject js_obj = Unwrap_JSObject(env, java_wrapper_obj);
jobject jresult = NULL;
CallMessage msg(js_obj, function_name_ucs2, function_name_len, java_args, &jresult);
sendMessage(env, &msg);
env->ReleaseStringChars(function_name_jstr, function_name_ucs2);
return jresult;
}
class EvalMessage : public JavaMessage {
JNIEnv* mEnv;
jsobject mObject;
const jchar* mScript;
jsize mLength;
jobject* mJavaResult;
public:
EvalMessage(jsobject obj, const jchar* script, jsize length, jobject* javaResult);
virtual void execute(JNIEnv* env);
};
EvalMessage::EvalMessage(jsobject obj, const jchar* script, jsize length, jobject* javaResult)
: mObject(obj), mScript(script), mLength(length), mJavaResult(javaResult)
{
}
void EvalMessage::execute(JNIEnv* env)
{
nsresult status = theLiveConnectManager->Eval(env, mObject, mScript, mLength, NULL, 0, NULL, mJavaResult);
}
/*
* Class: netscape_javascript_JSObject
* Method: eval
* Signature: (Ljava/lang/String;)Ljava/lang/Object;
*/
JNIEXPORT jobject JNICALL
Java_netscape_javascript_JSObject_eval(JNIEnv* env,
jobject java_wrapper_obj,
jstring script_jstr)
{
/* Get the Unicode string for the JS function name */
if (script_jstr == NULL) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "illegal null script string");
return NULL;
}
jboolean is_copy;
const jchar* script_ucs2 = env->GetStringChars(script_jstr, &is_copy);
jsize script_len = env->GetStringLength(script_jstr);
/* unwrap the JS object from the Java object. */
jsobject js_obj = Unwrap_JSObject(env, java_wrapper_obj);
jobject jresult = NULL;
/* determine the plugin instance so we can obtain its codebase. */
MRJPluginInstance* pluginInstance = theJVMPlugin->getPluginInstance(env);
if (pluginInstance == NULL) {
env->ThrowNew(env->FindClass("java/lang/NullPointerException"), "illegal JNIEnv (can't find plugin)");
return NULL;
}
EvalMessage msg(js_obj, script_ucs2, script_len, &jresult);
sendMessage(env, &msg);
// Make sure it gets released!
pluginInstance->Release();
env->ReleaseStringChars(script_jstr, script_ucs2);
return jresult;
}
/*
* Class: netscape_javascript_JSObject
* Method: toString
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL
Java_netscape_javascript_JSObject_toString(JNIEnv* env, jobject java_wrapper_obj)
{
/* unwrap the JS object from the Java object. */
jstring jresult = NULL;
jsobject js_obj = Unwrap_JSObject(env, java_wrapper_obj);
class ToStringMessage : public JavaMessage {
jsobject mObject;
jstring* mStringResult;
public:
ToStringMessage(jsobject js_obj, jstring* stringResult)
: mObject(js_obj), mStringResult(stringResult)
{
}
virtual void execute(JNIEnv* env)
{
nsresult status = theLiveConnectManager->ToString(env, mObject, mStringResult);
}
} msg(js_obj, &jresult);
sendMessage(env, &msg);
return jresult;
}
/*
* Class: netscape_javascript_JSObject
* Method: getWindow
* Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject;
*/
class GetWindowMessage : public JavaMessage {
nsIPluginInstance* mPluginInstance;
jsobject* mWindowResult;
public:
GetWindowMessage(nsIPluginInstance* pluginInstance, jsobject* windowResult);
virtual void execute(JNIEnv* env);
};
GetWindowMessage::GetWindowMessage(nsIPluginInstance* pluginInstance, jsobject* windowResult)
: mPluginInstance(pluginInstance), mWindowResult(windowResult)
{
}
void GetWindowMessage::execute(JNIEnv* env)
{
nsresult status = theLiveConnectManager->GetWindow(env,mPluginInstance, NULL, 0, NULL, mWindowResult);
}
JNIEXPORT jobject JNICALL
Java_netscape_javascript_JSObject_getWindow(JNIEnv* env,
jclass js_object_class,
jobject java_applet_obj)
{
jsobject jswindow = NULL;
MRJPluginInstance* pluginInstance = theJVMPlugin->getPluginInstance(java_applet_obj);
if (pluginInstance != NULL) {
GetWindowMessage msg(pluginInstance, &jswindow);
sendMessage(env, &msg);
pluginInstance->Release();
if (jswindow != NULL)
return Wrap_JSObject(env, jswindow);
}
return NULL;
}
/*
* Class: netscape_javascript_JSObject
* Method: finalize
* Signature: ()V
*/
JNIEXPORT void JNICALL
Java_netscape_javascript_JSObject_finalize(JNIEnv* env, jobject java_wrapper_obj)
{
jsobject jsobj = Unwrap_JSObject(env, java_wrapper_obj);
class FinalizeMessage : public JavaMessage {
jsobject m_jsobj;
public:
FinalizeMessage(jsobject jsobj)
: m_jsobj(jsobj)
{
}
virtual void execute(JNIEnv* env)
{
nsresult result = theLiveConnectManager->FinalizeJSObject(env, m_jsobj);
}
};
FinalizeMessage msg(jsobj);
sendMessage(env, &msg);
}

Просмотреть файл

@ -0,0 +1,34 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
LiveConnectNativeMethods.h
*/
#pragma once
#include "nsError.h"
#include <jni.h>
class MRJPlugin;
nsresult InitLiveConnectSupport(MRJPlugin* jvmPlugin);
nsresult ShutdownLiveConnectSupport(void);
jobject Wrap_JSObject(JNIEnv* env, jint js_obj);
jint Unwrap_JSObject(JNIEnv* env, jobject java_wrapper_obj);

Просмотреть файл

@ -0,0 +1,53 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
LocalPort.h
Simple utility class to put a Quickdraw GrafPort into a known state.
by Patrick C. Beard.
*/
#pragma once
#include <Quickdraw.h>
class LocalPort {
public:
LocalPort(GrafPtr port)
{
fPort = port;
fOrigin.h = fOrigin.v = 0;
}
LocalPort(GrafPtr port, Point origin)
{
fPort = port;
fOrigin.h = origin.h;
fOrigin.v = origin.v;
}
void Enter();
void Exit();
private:
GrafPtr fPort;
Point fOrigin;
GrafPtr fOldPort;
Point fOldOrigin;
};

Просмотреть файл

@ -0,0 +1,374 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJConsole.cpp
Implements the JVM console interface.
by Patrick C. Beard.
*/
#include <Appearance.h>
#include <Gestalt.h>
#include <string.h>
#include "MRJConsole.h"
#include "MRJPlugin.h"
#include "MRJSession.h"
#include "TopLevelFrame.h"
#include "nsIPluginManager2.h"
extern nsIPluginManager2* thePluginManager2;
MRJConsole* theConsole = NULL;
nsID MRJConsole::sInterfaceIDs[] = { NS_IJVMCONSOLE_IID };
MRJConsole::MRJConsole(MRJPlugin* plugin)
: SupportsMixin((nsIJVMConsole*)this, sInterfaceIDs, sizeof(sInterfaceIDs) / sizeof(nsID)),
mPlugin(plugin), mSession(NULL), mIsInitialized(PR_FALSE),
mConsoleClass(NULL), mInitMethod(NULL), mDisposeMethod(NULL),
mShowMethod(NULL), mHideMethod(NULL), mVisibleMethod(NULL), mPrintMethod(NULL), mFinishMethod(NULL),
mResults(NULL), mContext(NULL), mFrame(NULL)
{
// Initialize();
}
MRJConsole::~MRJConsole()
{
theConsole = NULL;
if (mSession != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
if (mConsoleClass != NULL) {
if (mDisposeMethod != NULL)
env->CallStaticVoidMethod(mConsoleClass, mDisposeMethod);
env->DeleteGlobalRef(mConsoleClass);
mConsoleClass = NULL;
}
if (mResults != NULL) {
env->DeleteGlobalRef(mResults);
mResults = NULL;
}
if (mContext != NULL) {
JMDisposeAWTContext(mContext);
mContext = NULL;
}
}
}
NS_METHOD MRJConsole::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
nsresult result = queryInterface(aIID, aInstancePtr);
if (result == NS_NOINTERFACE)
result = mPlugin->queryInterface(aIID, aInstancePtr);
return result;
}
nsrefcnt MRJConsole::AddRef() { return addRef(); }
nsrefcnt MRJConsole::Release() { return release(); }
#pragma mark ***** MRJConsole *****
NS_METHOD MRJConsole::ShowConsole()
{
Initialize();
if (mShowMethod != NULL) {
CallConsoleMethod(mShowMethod);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD MRJConsole::HideConsole()
{
Initialize();
if (mHideMethod != NULL) {
CallConsoleMethod(mHideMethod);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_METHOD MRJConsole::IsConsoleVisible(PRBool* isVisible)
{
// don't initialize here, because if we haven't been initialized, it can't be visible.
*isVisible = PR_FALSE;
if (mVisibleMethod != NULL) {
CallConsoleMethod(mVisibleMethod, mResults);
jboolean isCopy;
JNIEnv* env = mSession->getCurrentEnv();
jboolean* elements = env->GetBooleanArrayElements(mResults, &isCopy);
*isVisible = elements[0];
env->ReleaseBooleanArrayElements(mResults, elements, JNI_ABORT);
}
return NS_OK;
}
// Prints a message to the Java console. The encodingName specifies the
// encoding of the message, and if NULL, specifies the default platform
// encoding.
NS_METHOD MRJConsole::Print(const char* msg, const char* encodingName)
{
Initialize();
if (mPrintMethod != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
jstring jmsg = env->NewStringUTF(msg);
jvalue args[1]; args[0].l = jmsg;
JMExecJNIStaticMethodInContext(mContext, env, mConsoleClass, mPrintMethod, 1, args);
env->DeleteLocalRef(jmsg);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
// Writes a message to the Java console immediately, in the current thread.
void MRJConsole::write(const void *message, UInt32 messageLengthInBytes)
{
if (mPrintMethod != NULL) {
char* buffer = new char[messageLengthInBytes + 1];
if (buffer != NULL) {
memcpy(buffer, message, messageLengthInBytes);
buffer[messageLengthInBytes] = '\0';
JNIEnv* env = mSession->getCurrentEnv();
jstring jmsg = env->NewStringUTF(buffer);
if (jmsg != NULL) {
env->CallStaticVoidMethod(mConsoleClass, mPrintMethod, jmsg);
env->DeleteLocalRef(jmsg);
}
delete buffer;
}
}
}
NS_METHOD MRJConsole::HandleEvent(nsPluginEvent* pluginEvent, PRBool* eventHandled)
{
*eventHandled = PR_TRUE;
if (pluginEvent != NULL) {
EventRecord* event = pluginEvent->event;
if (event->what == nullEvent) {
// Give MRJ another quantum of time.
MRJSession* session = mPlugin->getSession();
session->idle(kDefaultJMTime);
} else {
TopLevelFrame* frame = mFrame;
if (frame != NULL) {
switch (event->what) {
case nsPluginEventType_GetFocusEvent:
frame->focusEvent(true);
break;
case nsPluginEventType_LoseFocusEvent:
frame->focusEvent(false);
break;
case nsPluginEventType_AdjustCursorEvent:
frame->idle(event->modifiers);
break;
case nsPluginEventType_MenuCommandEvent:
frame->menuSelected(event->message, event->modifiers);
break;
default:
*eventHandled = frame->handleEvent(event);
break;
}
}
}
}
return NS_OK;
}
OSStatus MRJConsole::CallConsoleMethod(jmethodID method)
{
JNIEnv* env = mSession->getCurrentEnv();
OSStatus status = JMExecJNIStaticMethodInContext(mContext, env, mConsoleClass, method, 0, NULL);
env->CallStaticVoidMethod(mConsoleClass, mFinishMethod);
return status;
}
OSStatus MRJConsole::CallConsoleMethod(jmethodID method, jobject arg)
{
jvalue args[1];
args[0].l = arg;
JNIEnv* env = mSession->getCurrentEnv();
OSStatus status = JMExecJNIStaticMethodInContext(mContext, env, mConsoleClass, method, 1, args);
env->CallStaticVoidMethod(mConsoleClass, mFinishMethod);
return status;
}
static OSStatus requestFrame(JMAWTContextRef contextRef, JMFrameRef frameRef, JMFrameKind kind,
const Rect* initialBounds, Boolean resizeable, JMFrameCallbacks* cb)
{
extern JMFrameCallbacks theFrameCallbacks;
// set up the viewer frame's callbacks.
BlockMoveData(&theFrameCallbacks, cb, sizeof(theFrameCallbacks));
MRJConsole* thisConsole = NULL;
OSStatus status = ::JMGetAWTContextData(contextRef, (JMClientData*)&thisConsole);
if (status == noErr && thePluginManager2 != NULL) {
// Can only do this safely if we are using the new API.
TopLevelFrame* frame = new TopLevelFrame(thisConsole, frameRef, kind, initialBounds, resizeable);
status = ::JMSetFrameData(frameRef, frame);
thisConsole->setFrame(frame);
}
return status;
}
static OSStatus releaseFrame(JMAWTContextRef contextRef, JMFrameRef frameRef)
{
MRJConsole* thisConsole = NULL;
OSStatus status = ::JMGetAWTContextData(contextRef, (JMClientData*)&thisConsole);
MRJFrame* thisFrame = NULL;
status = ::JMGetFrameData(frameRef, (JMClientData*)&thisFrame);
if (thisFrame != NULL) {
status = ::JMSetFrameData(frameRef, NULL);
thisConsole->setFrame(NULL);
delete thisFrame;
}
return status;
}
static SInt16 getUniqueMenuID(JMAWTContextRef contextRef, Boolean isSubmenu)
{
MRJConsole* thisConsole = NULL;
OSStatus status = ::JMGetAWTContextData(contextRef, (JMClientData*)&thisConsole);
if (thePluginManager2 != NULL) {
PRInt16 menuID;
if (thePluginManager2->AllocateMenuID(thisConsole, isSubmenu, &menuID) == NS_OK)
return menuID;
}
return -1;
}
static Boolean appearanceManagerExists()
{
long response = 0;
return (Gestalt(gestaltAppearanceAttr, &response) == noErr && (response & (1 << gestaltAppearanceExists)));
}
static OSStatus JMTextToStr255(JMTextRef textRef, Str255 str)
{
UInt32 length = 0;
OSStatus status = JMGetTextBytes(textRef, kTextEncodingMacRoman, &str[1], sizeof(Str255) - 1, &length);
if (status == noErr)
str[0] = (unsigned char)(status == noErr ? length : 0);
return status;
}
inline int min(int x, int y) { return (x <= y ? x : y); }
static void push(StringPtr dest, StringPtr str)
{
int length = dest[0];
int newLength = min(255, length + str[0]);
if (newLength > length)
::BlockMoveData(&str[1], &dest[1] + length, newLength - length);
}
static void exceptionOccurred(JMAWTContextRef context, JMTextRef exceptionName, JMTextRef exceptionMsg, JMTextRef stackTrace)
{
// why not display this using the Appearance Manager's wizzy new alert?
if (appearanceManagerExists()) {
OSStatus status;
Str255 preason = { '\0' }, pmessage = { '\0'}, ptrace = { '\0' };
if (exceptionName != NULL) {
status = ::JMTextToStr255(exceptionName, preason);
if (exceptionMsg != NULL) {
status = ::JMTextToStr255(exceptionMsg, pmessage);
push(preason, "\p (");
push(preason, pmessage);
push(preason, "\p)");
}
}
if (stackTrace != NULL)
status = ::JMTextToStr255(stackTrace, ptrace);
SInt16 itemHit = 0;
OSErr result = ::StandardAlert(kAlertPlainAlert, preason, ptrace, NULL, &itemHit);
}
}
void MRJConsole::Initialize()
{
if (mIsInitialized)
return;
mSession = mPlugin->getSession();
JNIEnv* env = mSession->getCurrentEnv();
jclass consoleClass = env->FindClass("netscape/oji/MRJConsole");
if (consoleClass == NULL) return;
mConsoleClass = (jclass) env->NewGlobalRef(consoleClass);
mInitMethod = env->GetStaticMethodID(consoleClass, "init", "()V");
mDisposeMethod = env->GetStaticMethodID(consoleClass, "dispose", "()V");
mShowMethod = env->GetStaticMethodID(consoleClass, "show", "()V");
mHideMethod = env->GetStaticMethodID(consoleClass, "hide", "()V");
mVisibleMethod = env->GetStaticMethodID(consoleClass, "visible", "([Z)V");
mPrintMethod = env->GetStaticMethodID(consoleClass, "print", "(Ljava/lang/String;)V");
mFinishMethod = env->GetStaticMethodID(consoleClass, "finish", "()V");
jbooleanArray results = env->NewBooleanArray(1);
mResults = (jbooleanArray) env->NewGlobalRef(results);
env->DeleteLocalRef(results);
// Create an AWT context to work in.
JMAWTContextCallbacks callbacks = {
kJMVersion, /* should be set to kJMVersion */
&requestFrame, /* a new frame is being created. */
&releaseFrame, /* an existing frame is being destroyed. */
&getUniqueMenuID, /* a new menu will be created with this id. */
&exceptionOccurred, /* just some notification that some recent operation caused an exception. You can't do anything really from here. */
};
OSStatus status = ::JMNewAWTContext(&mContext, mSession->getSessionRef(), &callbacks, this);
// Finally, call the Java initialize method, and wait for it to complete.
if (mInitMethod != NULL && status == noErr) {
status = JMExecJNIStaticMethodInContext(mContext, env, consoleClass, mInitMethod, 0, NULL);
env->CallStaticVoidMethod(mConsoleClass, mFinishMethod);
}
env->DeleteLocalRef(consoleClass);
mIsInitialized = (status == noErr);
if (mIsInitialized)
theConsole = this;
}

Просмотреть файл

@ -0,0 +1,103 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJConsole.h
Implements the JVM console interface.
by Patrick C. Beard.
*/
#include "nsIJVMConsole.h"
#include "nsIEventHandler.h"
#include "SupportsMixin.h"
#include <jni.h>
#include <JManager.h>
class MRJPlugin;
class MRJSession;
class TopLevelFrame;
class MRJConsole : public nsIJVMConsole,
public nsIEventHandler,
public SupportsMixin {
public:
MRJConsole(MRJPlugin* plugin);
virtual ~MRJConsole();
// NS_DECL_ISUPPORTS
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
// nsIJVMConsole methods.
NS_IMETHOD
ShowConsole(void);
NS_IMETHOD
HideConsole(void);
NS_IMETHOD
IsConsoleVisible(PRBool* isVisible);
// Prints a message to the Java console. The encodingName specifies the
// encoding of the message, and if NULL, specifies the default platform
// encoding.
NS_IMETHOD
Print(const char* msg, const char* encodingName = NULL);
NS_IMETHOD
HandleEvent(nsPluginEvent* event, PRBool* eventHandled);
// Private implementation methods.
void setFrame(TopLevelFrame* frame) { mFrame = frame; }
void write(const void *message, UInt32 messageLengthInBytes);
private:
// Private implementation methods.
OSStatus CallConsoleMethod(jmethodID method);
OSStatus CallConsoleMethod(jmethodID method, jobject arg);
void Initialize();
private:
MRJPlugin* mPlugin;
MRJSession* mSession;
PRBool mIsInitialized;
jclass mConsoleClass;
jmethodID mInitMethod;
jmethodID mDisposeMethod;
jmethodID mShowMethod;
jmethodID mHideMethod;
jmethodID mVisibleMethod;
jmethodID mPrintMethod;
jmethodID mFinishMethod;
jbooleanArray mResults;
JMAWTContextRef mContext;
TopLevelFrame* mFrame;
// support for nsISupports.
static nsID sInterfaceIDs[];
};

Просмотреть файл

@ -0,0 +1,222 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MJRConsole.java
Simple Java console for MRJ.
All methods are called asynchronously, using JMExecJNIStaticMethodInContext(). After posting
each call this way, MRJConsole.finish() is called, which waits on MRJConsole.class. Each
public method calls MRJConsole.done(), which notifies. This should probably be changed
to a pure Java approach.
by Patrick C. Beard.
*/
package netscape.oji;
import java.io.*;
import java.awt.*;
import java.awt.event.*;
class ConsoleWindow extends Frame {
TextArea text;
ConsoleWindow(String title) {
super("Java Console");
addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
hide();
}
});
add(text = new TextArea());
setSize(300, 200);
ActionListener dumpThreadsListener =
new ActionListener() {
public void actionPerformed(ActionEvent e) {
dumpThreads();
}
};
// Create a console menu.
MenuBar menuBar = new MenuBar();
Menu consoleMenu = new Menu("Console");
consoleMenu.add(newItem("Dump Threads", dumpThreadsListener));
menuBar.add(consoleMenu);
setMenuBar(menuBar);
}
private MenuItem newItem(String title, ActionListener listener) {
MenuItem item = new MenuItem(title);
item.addActionListener(listener);
return item;
}
public void dumpThreads() {
System.out.println("Dumping threads...");
}
}
public class MRJConsole {
// Save primordial System streams.
private static InputStream in;
private static PrintStream out;
private static PrintStream err;
private static ConsoleWindow window;
native static int readLine(byte[] buffer, int offset, int length);
native static void writeLine(byte[] buffer, int offset, int length);
private static class Input extends InputStream {
byte[] buffer = new byte[1024];
int position = 0;
int count = 0;
private void fillBuffer() throws EOFException {
// int length = readLine(buffer, 0, buffer.length);
int length = 1024;
if (length == -1)
throw new EOFException();
count = length;
position = 0;
}
public int read() throws IOException {
synchronized(this) {
if (position >= count)
fillBuffer();
return buffer[position++];
}
}
public int read(byte[] b, int offset, int length) throws IOException {
synchronized(this) {
// only fill the buffer at the outset, always returns at most one line of data.
if (position >= count)
fillBuffer();
int initialOffset = offset;
while (offset < length && position < count) {
b[offset++] = buffer[position++];
}
return (offset - initialOffset);
}
}
}
private static class Output extends OutputStream implements Runnable {
StringBuffer buffer = new StringBuffer();
public Output() {
Thread flusher = new Thread(this, getClass().getName() + "-Flusher");
flusher.setDaemon(true);
flusher.start();
}
public synchronized void write(int b) throws IOException {
this.buffer.append((char)b);
notify();
}
public synchronized void write(byte[] buffer, int offset, int count) throws IOException {
this.buffer.append(new String(buffer, 0, offset, count));
notify();
}
public synchronized void flush() throws IOException {
String value = this.buffer.toString();
window.text.append(value);
this.buffer.setLength(0);
}
/**
* When I/O occurs, it is placed in a StringBuffer, which is flushed in a different thread.
* This prevents deadlocks that could occur when the AWT itself is printing messages.
*/
public synchronized void run() {
for (;;) {
try {
wait();
flush();
} catch (InterruptedException ie) {
} catch (IOException ioe) {
}
}
}
}
private static class Error extends Output {}
public static void init() {
in = System.in;
out = System.out;
err = System.err;
window = new ConsoleWindow("Java Console");
System.setIn(new Input());
System.setOut(new PrintStream(new Output()));
System.setErr(new PrintStream(new Error()));
done();
}
public static void dispose() {
System.setIn(in);
System.setOut(out);
System.setErr(err);
window.dispose();
window = null;
done();
}
public static void show() {
window.show();
done();
}
public static void hide() {
window.hide();
done();
}
public static void visible(boolean[] result) {
result[0] = window.isVisible();
done();
}
public static void print(String text) {
System.out.print(text);
done();
}
public static synchronized void finish() {
try {
MRJConsole.class.wait();
} catch (InterruptedException ie) {
}
}
private static synchronized void done() {
MRJConsole.class.notify();
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,126 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJContext.h
Manages Java content using the MacOS Runtime for Java.
by Patrick C. Beard.
*/
#pragma once
#include "jni.h"
#include "JManager.h"
#include "nsplugindefs.h"
//
// Instance state information about the plugin.
//
// *Developers*: Use this struct to hold per-instance
// information that youÕll need in the
// various functions in this file.
//
class MRJSession;
class MRJPluginInstance;
class nsIPluginInstancePeer;
struct nsPluginWindow;
class MRJFrame;
class MRJPage;
struct MRJPageAttributes;
class MRJContext {
public:
MRJContext(MRJSession* session, MRJPluginInstance* instance);
~MRJContext();
void processAppletTag();
Boolean createContext();
JMAWTContextRef getContextRef();
Boolean appletLoaded();
Boolean loadApplet();
Boolean isActive();
void suspendApplet();
void resumeApplet();
jobject getApplet();
void idle(short modifiers);
void drawApplet();
void activate(Boolean active);
void resume(Boolean inFront);
void click(const EventRecord* event, MRJFrame* frame);
void keyPress(long message, short modifiers);
void keyRelease(long message, short modifiers);
void setWindow(nsPluginWindow* pluginWindow);
Boolean inspectClipping();
Boolean inspectWindow();
void setClipping(RgnHandle clipRgn);
MRJFrame* findFrame(WindowRef window);
GrafPtr getPort();
void showFrames();
void hideFrames();
const char* getCodeBase();
private:
void localToFrame(Point* pt);
void ensureValidPort();
void setVisibility();
static OSStatus requestFrame(JMAWTContextRef context, JMFrameRef newFrame, JMFrameKind kind,
const Rect *initialBounds, Boolean resizeable, JMFrameCallbacks *callbacks);
static OSStatus releaseFrame(JMAWTContextRef context, JMFrameRef oldFrame);
static SInt16 getUniqueMenuID(JMAWTContextRef context, Boolean isSubmenu);
static void exceptionOccurred(JMAWTContextRef context, JMTextRef exceptionName, JMTextRef exceptionMsg, JMTextRef stackTrace);
static void showDocument(JMAppletViewerRef viewer, JMTextRef urlString, JMTextRef windowName);
static void setStatusMessage(JMAppletViewerRef viewer, JMTextRef statusMsg);
void showURL(const char* url, const char* target);
void showStatus(const char* message);
SInt16 allocateMenuID(Boolean isSubmenu);
OSStatus createFrame(JMFrameRef frameRef, JMFrameKind kind, const Rect* initialBounds, Boolean resizeable);
// Finds a suitable MRJPage object for this document URL, or creates one.
MRJPage* findPage(const MRJPageAttributes& attributes);
private:
MRJPluginInstance* mPluginInstance;
MRJSession* mSession;
JMSessionRef mSessionRef;
nsIPluginInstancePeer* mPeer;
JMAppletLocatorRef mLocator;
JMAWTContextRef mContext;
JMAppletViewerRef mViewer;
JMFrameRef mViewerFrame;
Boolean mIsActive;
nsPluginWindow mCache;
nsPluginWindow* mPluginWindow;
RgnHandle mPluginClipping;
char* mCodeBase;
MRJPage* mPage;
};

Просмотреть файл

@ -0,0 +1,190 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJFrame.cpp
Encapsulates a JManager frame.
by Patrick C. Beard.
*/
#include "MRJFrame.h"
#include "LocalPort.h"
#include "nsplugindefs.h"
MRJFrame::MRJFrame(JMFrameRef frameRef)
: mFrameRef(frameRef), mActive(false), mFocused(false)
{
}
MRJFrame::~MRJFrame()
{
}
/* Stub implementations. */
void MRJFrame::setSize(const Rect* newSize) {}
void MRJFrame::invalRect(const Rect* invalidRect) {}
void MRJFrame::showHide(Boolean visible) {}
void MRJFrame::setTitle(const StringPtr title) {}
void MRJFrame::checkUpdate() {}
void MRJFrame::reorder(ReorderRequest request) {}
void MRJFrame::setResizeable(Boolean resizeable) {}
Boolean MRJFrame::handleEvent(const EventRecord* event)
{
Boolean eventHandled = true;
switch (event->what) {
case nsPluginEventType_AdjustCursorEvent:
idle(event->modifiers);
break;
case ::mouseDown:
click(event);
break;
case keyDown:
case autoKey:
keyPress(event->message, event->modifiers);
break;
case keyUp:
keyRelease(event->message, event->modifiers);
break;
case updateEvt:
update();
break;
case activateEvt:
activate((event->modifiers & activeFlag) != 0);
break;
#if 0
case osEvt:
resume((event->message & resumeFlag) != 0);
eventHandled = false;
break;
#endif
default:
eventHandled = false;
break;
}
return eventHandled;
}
void MRJFrame::idle(SInt16 modifiers)
{
LocalPort port(getPort());
port.Enter();
Point pt;
::GetMouse(&pt);
::JMFrameMouseOver(mFrameRef, pt, modifiers);
port.Exit();
}
void MRJFrame::update()
{
GrafPtr framePort = getPort();
if (framePort != NULL)
::JMFrameUpdate(mFrameRef, framePort->clipRgn);
}
void MRJFrame::activate(Boolean active)
{
if (mActive != active) {
mActive = active;
::JMFrameActivate(mFrameRef, active);
}
}
void MRJFrame::focusEvent(Boolean gotFocus)
{
if (&::JMFrameFocus != NULL) {
if (gotFocus != mFocused) {
if (gotFocus) {
// HACK, until focus really works.
if (mActive != gotFocus) {
mActive = gotFocus;
::JMFrameActivate(mFrameRef, gotFocus);
}
}
mFocused = gotFocus;
::JMFrameFocus(mFrameRef, gotFocus);
}
} else {
if (mActive != gotFocus) {
mActive = gotFocus;
::JMFrameActivate(mFrameRef, gotFocus);
}
}
}
void MRJFrame::resume(Boolean inFront)
{
::JMFrameResume(mFrameRef, inFront);
}
void MRJFrame::click(const EventRecord* event)
{
// make the frame's port current, and move its origin to (0, 0).
// this is needed to transform the mouse click location to frame coordinates.
LocalPort port(getPort());
port.Enter();
Point localWhere = event->where;
::GlobalToLocal(&localWhere);
click(event, localWhere);
// restore the plugin port's origin, and restore the current port.
port.Exit();
}
void MRJFrame::click(const EventRecord* event, Point localWhere)
{
if (&::JMFrameClickWithEventRecord != NULL)
::JMFrameClickWithEventRecord(mFrameRef, localWhere, event);
else
::JMFrameClick(mFrameRef, localWhere, event->modifiers);
}
void MRJFrame::keyPress(UInt32 message, SInt16 modifiers)
{
::JMFrameKey(mFrameRef, message & charCodeMask, (message & keyCodeMask) >> 8, modifiers);
}
void MRJFrame::keyRelease(UInt32 message, SInt16 modifiers)
{
::JMFrameKeyRelease(mFrameRef, message & charCodeMask, (message & keyCodeMask) >> 8, modifiers);
}
void MRJFrame::menuSelected(UInt32 message, SInt16 modifiers)
{
MenuHandle menu = ::GetMenuHandle(short(message >> 16));
if (menu != NULL) {
short item = short(message);
if (&::JMMenuSelectedWithModifiers != NULL)
::JMMenuSelectedWithModifiers(::JMGetFrameContext(mFrameRef), menu, item, modifiers);
else
::JMMenuSelected(::JMGetFrameContext(mFrameRef), menu, item);
}
}

Просмотреть файл

@ -0,0 +1,69 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJFrame.h
Encapsulates a JManager frame.
by Patrick C. Beard.
*/
#pragma once
#include "jni.h"
#include "JManager.h"
struct EventRecord;
class MRJFrame {
public:
MRJFrame(JMFrameRef frameRef);
virtual ~MRJFrame();
/** Methods used to implement the JMFrame callback protocol. */
virtual void setSize(const Rect* newSize);
virtual void invalRect(const Rect* invalidRect);
virtual void showHide(Boolean visible);
virtual void setTitle(const StringPtr title);
virtual void checkUpdate();
virtual void reorder(ReorderRequest request);
virtual void setResizeable(Boolean resizeable);
/** Methods to handle various events. */
virtual Boolean handleEvent(const EventRecord* event);
virtual void idle(SInt16 modifiers);
virtual void update();
virtual void activate(Boolean active);
virtual void resume(Boolean inFront);
virtual void click(const EventRecord* event);
virtual void click(const EventRecord* event, Point localWhere);
virtual void keyPress(UInt32 message, SInt16 modifiers);
virtual void keyRelease(UInt32 message, SInt16 modifiers);
virtual void focusEvent(Boolean gotFocus);
virtual void menuSelected(UInt32 message, SInt16 modifiers);
protected:
virtual GrafPtr getPort() = 0;
protected:
JMFrameRef mFrameRef;
Boolean mActive;
Boolean mFocused;
};

Просмотреть файл

@ -0,0 +1,114 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJMonitor.cpp
Provides a C++ interface to Java monitors.
by Patrick C. Beard.
*/
#include "MRJMonitor.h"
#include "MRJSession.h"
MRJMonitor::MRJMonitor(MRJSession* session, jobject monitor)
: mSession(session), mMonitor(NULL), mWaitMethod(NULL), mNotifyMethod(NULL), mNotifyAllMethod(NULL)
{
JNIEnv* env = mSession->getCurrentEnv();
jclass javaLangObject = env->FindClass("java/lang/Object");
if (javaLangObject != NULL) {
// look up method IDs.
mWaitMethod = env->GetMethodID(javaLangObject, "wait", "()V");
mTimedWaitMethod = env->GetMethodID(javaLangObject, "wait", "(J)V");
mNotifyMethod = env->GetMethodID(javaLangObject, "notify", "()V");
mNotifyAllMethod = env->GetMethodID(javaLangObject, "notifyAll", "()V");
Boolean allocateMonitor = (monitor == NULL);
if (allocateMonitor)
monitor = env->AllocObject(javaLangObject);
if (monitor != NULL)
mMonitor = env->NewGlobalRef(monitor);
if (allocateMonitor)
env->DeleteLocalRef(monitor);
env->DeleteLocalRef(javaLangObject);
}
}
MRJMonitor::~MRJMonitor()
{
if (mMonitor != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
env->DeleteGlobalRef(mMonitor);
mMonitor = NULL;
}
}
void MRJMonitor::enter()
{
JNIEnv* env = mSession->getCurrentEnv();
env->MonitorEnter(mMonitor);
}
void MRJMonitor::exit()
{
JNIEnv* env = mSession->getCurrentEnv();
env->MonitorExit(mMonitor);
}
void MRJMonitor::wait()
{
if (mMonitor != NULL && mWaitMethod != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
env->MonitorEnter(mMonitor);
env->CallVoidMethod(mMonitor, mWaitMethod);
env->MonitorExit(mMonitor);
}
}
void MRJMonitor::wait(long long millis)
{
if (mMonitor != NULL && mWaitMethod != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
env->MonitorEnter(mMonitor);
env->CallVoidMethod(mMonitor, mTimedWaitMethod, jlong(millis));
env->MonitorExit(mMonitor);
}
}
void MRJMonitor::notify()
{
if (mMonitor != NULL && mNotifyMethod != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
env->MonitorEnter(mMonitor);
env->CallVoidMethod(mMonitor, mNotifyMethod);
env->MonitorExit(mMonitor);
}
}
void MRJMonitor::notifyAll()
{
if (mMonitor != NULL && mNotifyAllMethod != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
env->MonitorEnter(mMonitor);
env->CallVoidMethod(mMonitor, mNotifyAllMethod);
env->MonitorExit(mMonitor);
}
}

Просмотреть файл

@ -0,0 +1,54 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJMonitor.h
Provides a C++ interface to Java monitors.
by Patrick C. Beard.
*/
#include "Monitor.h"
#ifndef JNI_H
#include <jni.h>
#endif
class MRJSession;
class MRJMonitor : public Monitor {
public:
MRJMonitor(MRJSession* session, jobject monitor = NULL);
~MRJMonitor();
virtual void enter();
virtual void exit();
virtual void wait();
virtual void wait(long long millis);
virtual void notify();
virtual void notifyAll();
private:
MRJSession* mSession;
jobject mMonitor;
jmethodID mWaitMethod;
jmethodID mTimedWaitMethod;
jmethodID mNotifyMethod;
jmethodID mNotifyAllMethod;
};

Просмотреть файл

@ -0,0 +1,134 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJPage.cpp
Encapsulates the new MRJ Page API, which loads applets into a common context.
by Patrick C. Beard.
*/
#include "MRJPage.h"
#include "MRJSession.h"
#include "StringUtils.h"
MRJPage::MRJPage(MRJSession* session, UInt32 documentID, const char* codeBase, const char* archive, Boolean mayScript)
: mRefCount(0), mNextPage(NULL), mSession(session), mPageRef(NULL),
mDocumentID(documentID), mCodeBase(strdup(codeBase)), mArchive(strdup(archive)), mMayScript(mayScript)
{
pushPage();
if (&::JMNewAppletPage != NULL) {
OSStatus status = ::JMNewAppletPage(&mPageRef, session->getSessionRef());
if (status != noErr) mPageRef = NULL;
}
}
MRJPage::MRJPage(MRJSession* session, const MRJPageAttributes& attributes)
: mRefCount(0), mNextPage(NULL), mSession(session), mPageRef(NULL),
mDocumentID(attributes.documentID), mCodeBase(strdup(attributes.codeBase)),
mArchive(strdup(attributes.archive)), mMayScript(attributes.mayScript)
{
pushPage();
if (&::JMNewAppletPage != NULL) {
OSStatus status = ::JMNewAppletPage(&mPageRef, session->getSessionRef());
if (status != noErr) mPageRef = NULL;
}
}
MRJPage::~MRJPage()
{
popPage();
if (&::JMDisposeAppletPage != NULL && mPageRef != NULL) {
OSStatus status = ::JMDisposeAppletPage(mPageRef);
mPageRef = NULL;
}
if (mCodeBase != NULL) {
delete[] mCodeBase;
mCodeBase = NULL;
}
if (mArchive != NULL) {
delete[] mArchive;
mArchive = NULL;
}
}
UInt16 MRJPage::AddRef()
{
return (++mRefCount);
}
UInt16 MRJPage::Release()
{
UInt16 result = --mRefCount;
if (result == 0) {
delete this;
}
return result;
}
Boolean MRJPage::createContext(JMAWTContextRef* outContext, const JMAWTContextCallbacks * callbacks, JMClientData data)
{
OSStatus status = noErr;
if (&::JMNewAWTContextInPage != NULL && mPageRef != NULL) {
status = ::JMNewAWTContextInPage(outContext, mSession->getSessionRef(), mPageRef, callbacks, data);
} else {
status = ::JMNewAWTContext(outContext, mSession->getSessionRef(), callbacks, data);
}
return (status == noErr);
}
static MRJPage* thePageList = NULL;
MRJPage* MRJPage::getFirstPage()
{
return thePageList;
}
MRJPage* MRJPage::getNextPage()
{
return mNextPage;
}
void MRJPage::pushPage()
{
// put this on the global list of pages.
mNextPage = thePageList;
thePageList = this;
}
void MRJPage::popPage()
{
// Remove this page from the global list.
MRJPage** link = &thePageList;
MRJPage* page = *link;
while (page != NULL) {
if (page == this) {
*link = mNextPage;
mNextPage = NULL;
break;
}
link = &page->mNextPage;
page = *link;
}
}

Просмотреть файл

@ -0,0 +1,83 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJPage.h
Encapsulates the MRJ data structure.
by Patrick C. Beard.
*/
#ifndef __TYPES__
#include <Types.h>
#endif
#include "JManager.h"
// For now.
typedef struct OpaqueJMAppletPageRef* JMAppletPageRef;
class MRJSession;
struct MRJPageAttributes {
UInt32 documentID;
const char* codeBase;
const char* archive;
Boolean mayScript;
};
class MRJPage {
public:
MRJPage(MRJSession* session, UInt32 documentID, const char* codeBase, const char* archive, Boolean mayScript);
MRJPage(MRJSession* session, const MRJPageAttributes& attributes);
~MRJPage();
// Pages are reference counted.
UInt16 AddRef(void);
UInt16 Release(void);
JMAppletPageRef getPageRef() { return mPageRef; }
UInt32 getDocumentID() { return mDocumentID; }
const char* getCodeBase() { return mCodeBase; }
const char* getArchive() { return mArchive; }
Boolean getMayScript() { return mMayScript; }
// Creating AWTContexts.
Boolean createContext(JMAWTContextRef* outContext,
const JMAWTContextCallbacks * callbacks,
JMClientData data);
// Accessing the list of instances.
static MRJPage* getFirstPage(void);
MRJPage* getNextPage(void);
private:
void pushPage();
void popPage();
private:
UInt16 mRefCount;
MRJPage* mNextPage;
MRJSession* mSession;
JMAppletPageRef mPageRef;
UInt32 mDocumentID;
char* mCodeBase;
char* mArchive;
Boolean mMayScript;
};

Просмотреть файл

@ -0,0 +1,658 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJPlugin.cpp
XP COM Plugin Implementation.
by Patrick C. Beard.
*/
#include "MRJPlugin.h"
#include "MRJSession.h"
#include "MRJContext.h"
#include "MRJFrame.h"
#include "MRJConsole.h"
#include "nsIMalloc.h"
#include "nsRepository.h"
#include "nsIJVMManager.h"
#include "nsIPluginManager2.h"
#include "nsIPluginInstancePeer.h"
#include "nsIWindowlessPlugInstPeer.h"
#include "LiveConnectNativeMethods.h"
#include "CSecureJNI2.h"
extern nsIPluginManager* thePluginManager; // now in badaptor.cpp.
extern nsIPlugin* thePlugin;
nsIPluginManager2* thePluginManager2 = NULL;
nsIMalloc* theMemoryAllocator = NULL;
// Common interface IDs.
static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID);
static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID);
static NS_DEFINE_IID(kIPluginManager2IID, NS_IPLUGINMANAGER2_IID);
static NS_DEFINE_IID(kIMallocIID, NS_IMALLOC_IID);
static NS_DEFINE_IID(kIJVMManagerIID, NS_IJVMMANAGER_IID);
static NS_DEFINE_IID(kIThreadManagerIID, NS_ITHREADMANAGER_IID);
static NS_DEFINE_IID(kIRunnableIID, NS_IRUNNABLE_IID);
static NS_DEFINE_IID(kIPluginInstanceIID, NS_IPLUGININSTANCE_IID);
static NS_DEFINE_IID(kIJVMPluginInstanceIID, NS_IJVMPLUGININSTANCE_IID);
static NS_DEFINE_IID(kIWindowlessPluginInstancePeerIID, NS_IWINDOWLESSPLUGININSTANCEPEER_IID);
#pragma export on
/* NS_METHOD NP_CreatePlugin(NPIPluginManager* manager, NPIPlugin* *result)
{
thePluginManager = manager;
*result = new MRJPlugin(manager);
return nsPluginError_NoError;
} */
nsresult NSGetFactory(const nsCID &classID, nsIFactory **aFactory)
{
if (classID.Equals(kIPluginIID)) {
static MRJPlugin thePlugin;
*aFactory = &thePlugin;
::thePlugin = &thePlugin;
// *aFactory = new MRJPlugin();
return NS_OK;
}
return NS_NOINTERFACE;
}
#pragma export off
extern "C" void cfm_NSShutdownPlugin(void);
void cfm_NSShutdownPlugin()
{
if (thePlugin != NULL) {
nsrefcnt refs = thePlugin->Release();
while (refs > 0 && thePlugin != NULL)
refs = thePlugin->Release();
}
}
//
// The MEAT of the plugin.
//
#pragma mark *** MRJPlugin ***
nsID MRJPlugin::sInterfaceIDs[] = { NS_IPLUGIN_IID, NS_IJVMPLUGIN_IID };
MRJPlugin::MRJPlugin()
: SupportsMixin((nsIJVMPlugin*)this, sInterfaceIDs, sizeof(sInterfaceIDs) / sizeof(nsID)),
mManager(NULL), mThreadManager(NULL), mSession(NULL), mConsole(NULL), mIsEnabled(false), mPluginThreadID(0)
{
}
MRJPlugin::~MRJPlugin()
{
// make sure the plugin is no longer visible.
::thePlugin = NULL;
// Release the console.
if (mConsole != NULL) {
mConsole->Release();
mConsole = NULL;
}
// tear down the MRJ session, if it exists.
if (mSession != NULL) {
delete mSession;
mSession = NULL;
}
// Release the manager?
if (mManager != NULL) {
mManager->Release();
mManager = NULL;
}
if (mThreadManager != NULL) {
mThreadManager->Release();
mThreadManager = NULL;
}
}
// PCB: Metrowerks pre-processor bug? The following macro won't compile.
// NS_IMPL_ISUPPORTS(MRJPlugin, NP_IPLUGIN_IID)
NS_METHOD MRJPlugin::QueryInterface(const nsIID& aIID, void** instancePtr)
{
if (aIID.Equals(kIRunnableIID)) {
*instancePtr = (void*) (nsIRunnable*) this;
return NS_OK;
}
nsresult result = queryInterface(aIID, instancePtr);
if (result == NS_NOINTERFACE) {
result = mConsole->queryInterface(aIID, instancePtr);
}
return result;
}
nsrefcnt MRJPlugin::AddRef(void) { return addRef(); }
nsrefcnt MRJPlugin::Release(void) { return release(); }
NS_METHOD MRJPlugin::CreateInstance(nsISupports *aOuter, const nsIID& aIID, void **aResult)
{
if (aIID.Equals(kIPluginInstanceIID) || aIID.Equals(kIJVMPluginInstanceIID)) {
if (StartupJVM(NULL) == NS_OK) {
MRJPluginInstance* instance = new MRJPluginInstance(this);
instance->AddRef(); // if not us, then who will take this burden?
*aResult = instance;
return NS_OK;
}
return NS_ERROR_FAILURE;
}
return NS_NOINTERFACE;
}
NS_METHOD MRJPlugin::Initialize(nsISupports* browserInterfaces)
{
nsresult result = NS_OK;
// try to get a plugin manager.
if (thePluginManager == NULL) {
result = browserInterfaces->QueryInterface(kIPluginManagerIID, &thePluginManager);
if (result != NS_OK || thePluginManager == NULL)
return NS_ERROR_FAILURE;
}
// see if the enhanced plugin manager exists.
if (thePluginManager2 == NULL) {
result = browserInterfaces->QueryInterface(kIPluginManager2IID, &thePluginManager2);
if (result != NS_OK)
thePluginManager2 = NULL;
}
// see if IMalloc exists.
if (theMemoryAllocator == NULL) {
result = browserInterfaces->QueryInterface(kIMallocIID, &theMemoryAllocator);
if (result != NS_OK)
theMemoryAllocator = NULL;
}
// try to get a JVM manager. we have to be able to run without one.
result = browserInterfaces->QueryInterface(kIJVMManagerIID, &mManager);
if (result != NS_OK)
mManager = NULL;
// try to get a Thread manager.
result = browserInterfaces->QueryInterface(kIThreadManagerIID, &mThreadManager);
if (result != NS_OK)
mThreadManager = NULL;
if (mThreadManager != NULL)
mThreadManager->GetCurrentThread(&mPluginThreadID);
// create a console, only if we can register windows.
if (thePluginManager2 != NULL) {
mConsole = new MRJConsole(this);
mConsole->AddRef();
}
return NS_OK;
}
NS_METHOD MRJPlugin::GetMIMEDescription(const char* *result)
{
*result = NPJVM_MIME_TYPE;
return NS_OK;
}
MRJSession* MRJPlugin::getSession()
{
StartupJVM(NULL);
return mSession;
}
nsIJVMManager* MRJPlugin::getManager()
{
return mManager;
}
nsIThreadManager* MRJPlugin::getThreadManager()
{
return mThreadManager;
}
NS_METHOD MRJPlugin::StartupJVM(nsJVMInitArgs* initArgs)
{
if (mSession == NULL) {
// start a session with MRJ.
mSession = new MRJSession();
if (mSession->getStatus() != noErr) {
// how can we signal an error?
delete mSession;
mSession = NULL;
return NS_ERROR_FAILURE;
}
// Apply the initialization args.
if (initArgs != NULL && initArgs->version >= nsJVMInitArgs_Version) {
const char* classPathAdditions = initArgs->classpathAdditions;
if (classPathAdditions != NULL) {
// what format will this be in? UNIX paths, separated by ':' characters.
char* paths = new char[1 + strlen(classPathAdditions)];
if (paths != NULL) {
strcpy(paths, classPathAdditions);
char* path = strtok(paths, ":");
while (path != NULL) {
static char urlPrefix[] = { "file://" };
char* fileURL = new char[sizeof(urlPrefix) + strlen(path)];
if (fileURL != NULL) {
strcat(strcpy(fileURL, urlPrefix), path);
mSession->addURLToClassPath(fileURL);
delete[] fileURL;
}
path = strtok(NULL, ":");
}
delete[] paths;
}
}
}
InitLiveConnectSupport(this);
#if 0
// start our idle thread.
if (mThreadManager != NULL) {
PRUint32 threadID;
mThreadManager->CreateThread(&threadID, this);
}
#endif
mIsEnabled = true;
}
return NS_OK;
}
NS_METHOD MRJPlugin::ShutdownJVM(PRBool fullShutdown)
{
if (fullShutdown) {
if (mSession != NULL) {
delete mSession;
mSession = NULL;
}
}
return NS_OK;
}
NS_METHOD MRJPlugin::AddToClassPath(const char* dirPath)
{
if (mSession != NULL) {
mSession->addToClassPath(dirPath);
return NS_OK;
}
return NS_JVM_ERROR_WRONG_CLASSES;
}
NS_METHOD MRJPlugin::GetClassPath(const char* *result)
{
char* classPath = mSession->getProperty("java.class.path");
*result = classPath;
return (classPath != NULL ? NS_OK : NS_ERROR_FAILURE);
}
NS_METHOD MRJPlugin::GetJavaWrapper(JNIEnv* env, jint jsobj, jobject *jobj)
{
// use jsobj as key into a table.
// if not in the table, then create a new netscape.javascript.JSObject that references this.
*jobj = Wrap_JSObject(env, jsobj);
return NS_OK;
}
NS_METHOD MRJPlugin::GetJavaVM(JavaVM* *result)
{
*result = NULL;
if (StartupJVM(NULL) == NS_OK) {
*result = mSession->getJavaVM();
return NS_OK;
}
return NS_ERROR_FAILURE;
}
nsrefcnt MRJPlugin::GetJNIEnv(JNIEnv* *result)
{
JNIEnv* env = NULL;
if (StartupJVM(NULL) == NS_OK) {
#if 1
env = mSession->getCurrentEnv();
#else
JDK1_1AttachArgs args;
JavaVM* vm = mSession->getJavaVM();
jint result = vm->AttachCurrentThread(&env, &args);
if (result != 0)
env = NULL;
#endif
}
*result = env;
return 1;
}
nsrefcnt MRJPlugin::ReleaseJNIEnv(JNIEnv* env)
{
return 0;
}
NS_METHOD MRJPlugin::CreateSecureEnv(JNIEnv* proxyEnv, nsISecureJNI2* *outSecureEnv)
{
// Need to spawn a new JVM communication thread here.
NS_DEFINE_IID(kISecureJNI2IID, NS_ISECUREJNI2_IID);
return CSecureJNI2::Create(NULL, this, proxyEnv, kISecureJNI2IID, (void**)outSecureEnv);
}
NS_METHOD MRJPlugin::SpendTime(PRUint32 timeMillis)
{
nsresult result = NS_OK;
// Only do this if there aren't any plugin instances.
// if (true || MRJPluginInstance::getInstances() == NULL) {
result = StartupJVM(NULL);
if (result == NS_OK)
mSession->idle(timeMillis);
// }
return result;
}
NS_METHOD MRJPlugin::Run()
{
while (mSession != NULL) {
mSession->idle();
mThreadManager->Sleep();
}
return NS_OK;
}
MRJPluginInstance* MRJPlugin::getPluginInstance(jobject applet)
{
JNIEnv* env = mSession->getCurrentEnv();
MRJPluginInstance* instance = MRJPluginInstance::getInstances();
while (instance != NULL) {
jobject object = NULL;
if (instance->GetJavaObject(&object) == NS_OK && env->IsSameObject(applet, object)) {
instance->AddRef();
return instance;
}
instance = instance->getNextInstance();
}
return NULL;
}
MRJPluginInstance* MRJPlugin::getPluginInstance(JNIEnv* jenv)
{
// Apple will provide an API that maps a JNIEnv to an JMAWTContextRef. We can map this to the MRJContext/Applet/Instance.
MRJPluginInstance* instance = MRJPluginInstance::getInstances();
if (&::JMJNIToAWTContext != NULL) {
JMAWTContextRef contextRef = ::JMJNIToAWTContext(mSession->getSessionRef(), jenv);
if (contextRef != NULL) {
while (instance != NULL) {
if (instance->getContext()->getContextRef() == contextRef) {
instance->AddRef();
return instance;
}
instance = instance->getNextInstance();
}
}
} else {
if (instance != NULL) {
instance->AddRef();
return instance;
}
}
return NULL;
}
Boolean MRJPlugin::inPluginThread()
{
PRUint32 currentThreadID = -1;
if (mThreadManager != NULL)
mThreadManager->GetCurrentThread(&currentThreadID);
return (mPluginThreadID == currentThreadID);
}
#pragma mark *** MRJPluginInstance ***
NS_METHOD MRJPluginInstance::QueryInterface(const nsIID& aIID, void** aInstancePtr)
{
return queryInterface(aIID, aInstancePtr);
}
nsrefcnt MRJPluginInstance::AddRef() { return addRef(); }
nsrefcnt MRJPluginInstance::Release() { return release(); }
nsID MRJPluginInstance::sInterfaceIDs[] = { NS_IPLUGININSTANCE_IID, NS_IJVMPLUGININSTANCE_IID };
MRJPluginInstance::MRJPluginInstance(MRJPlugin* plugin)
: SupportsMixin(this, sInterfaceIDs, sizeof(sInterfaceIDs) / sizeof(nsID)),
mPeer(NULL), mWindowlessPeer(NULL),
mPlugin(plugin), mSession(plugin->getSession()),
mContext(NULL), mApplet(NULL),
mNext(NULL)
{
// add this instance to the instance list.
pushInstance();
// Tell the plugin we are retaining a reference.
mPlugin->AddRef();
}
MRJPluginInstance::~MRJPluginInstance()
{
// Remove this instance from the global list.
popInstance();
if (mContext != NULL) {
delete mContext;
mContext = NULL;
}
if (mPlugin != NULL) {
mPlugin->Release();
mPlugin = NULL;
}
if (mWindowlessPeer != NULL) {
mWindowlessPeer->Release();
mWindowlessPeer = NULL;
}
if (mPeer != NULL) {
mPeer->Release();
mPeer = NULL;
}
if (mApplet != NULL) {
JNIEnv* env = mSession->getCurrentEnv();
env->DeleteGlobalRef(mApplet);
mApplet = NULL;
}
}
NS_METHOD MRJPluginInstance::Initialize(nsIPluginInstancePeer* peer)
{
// Tell the peer we are retaining a reference.
mPeer = peer;
mPeer->AddRef();
// See if we have a windowless peer.
nsresult result = mPeer->QueryInterface(kIWindowlessPluginInstancePeerIID, &mWindowlessPeer);
if (result != NS_OK) mWindowlessPeer = NULL;
// create a context for the applet we will run.
mContext = new MRJContext(mSession, this);
mContext->processAppletTag();
mContext->createContext();
return NS_OK;
}
NS_METHOD MRJPluginInstance::GetPeer(nsIPluginInstancePeer* *result)
{
mPeer->AddRef();
*result = mPeer;
return NS_OK;
}
NS_METHOD MRJPluginInstance::Start()
{
// Take this moment to show the applet's frames (if any).
mContext->showFrames();
mContext->resumeApplet();
return NS_OK;
}
NS_METHOD MRJPluginInstance::Stop()
{
// Take this moment to hide the applet's frames.
mContext->hideFrames();
mContext->suspendApplet();
return NS_OK;
}
NS_METHOD MRJPluginInstance::Destroy()
{
// Release();
return NS_OK;
}
/** FIXME: Need an intelligent way to track changes to the NPPluginWindow. */
NS_METHOD MRJPluginInstance::SetWindow(nsPluginWindow* pluginWindow)
{
mContext->setWindow(pluginWindow);
return NS_OK;
}
NS_METHOD MRJPluginInstance::HandleEvent(nsPluginEvent* pluginEvent, PRBool* eventHandled)
{
*eventHandled = PR_TRUE;
if (pluginEvent != NULL) {
EventRecord* event = pluginEvent->event;
// Check for clipping changes.
if (event->what == nsPluginEventType_ClippingChangedEvent) {
mContext->setClipping(RgnHandle(event->message));
return NS_OK;
}
// Check for coordinate system changes.
// visibilityChanged = mContext->inspectWindow();
// assume the browser will generate the correct update events?
if (mContext->inspectWindow() && mWindowlessPeer != NULL)
mWindowlessPeer->ForceRedraw();
if (event->what == nullEvent) {
// Give MRJ another quantum of time.
mSession->idle(kDefaultJMTime); // now SpendTime does this.
} else {
MRJFrame* frame = mContext->findFrame(WindowRef(pluginEvent->window));
if (frame != NULL) {
switch (event->what) {
case nsPluginEventType_GetFocusEvent:
frame->focusEvent(true);
break;
case nsPluginEventType_LoseFocusEvent:
frame->focusEvent(false);
break;
case nsPluginEventType_AdjustCursorEvent:
frame->idle(event->modifiers);
break;
case nsPluginEventType_MenuCommandEvent:
frame->menuSelected(event->message, event->modifiers);
break;
default:
*eventHandled = frame->handleEvent(event);
break;
}
}
}
}
return NS_OK;
}
NS_METHOD MRJPluginInstance::GetJavaObject(jobject *result)
{
if (mApplet == NULL) {
jobject applet = mContext->getApplet();
JNIEnv* env = mSession->getCurrentEnv();
mApplet = env->NewGlobalRef(applet);
}
*result = mApplet;
return NS_OK;
}
// Accessing the list of instances.
static MRJPluginInstance* theInstances = NULL;
void MRJPluginInstance::pushInstance()
{
mNext = theInstances;
theInstances = this;
}
void MRJPluginInstance::popInstance()
{
MRJPluginInstance** link = &theInstances;
MRJPluginInstance* instance = *link;
while (instance != NULL) {
if (instance == this) {
*link = mNext;
mNext = NULL;
break;
}
link = &instance->mNext;
instance = *link;
}
}
MRJPluginInstance* MRJPluginInstance::getInstances()
{
return theInstances;
}
MRJPluginInstance* MRJPluginInstance::getNextInstance()
{
return mNext;
}
MRJContext* MRJPluginInstance::getContext()
{
return mContext;
}
MRJSession* MRJPluginInstance::getSession()
{
return mSession;
}

Просмотреть файл

@ -0,0 +1,330 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJPlugin.h
MRJPlugin encapsulates the global state of the MRJ plugin as a single COM object.
MRJPluginInstance represents an instance of the MRJ plugin.
by Patrick C. Beard.
*/
#pragma once
#include "nsIJVMPlugin.h"
#include "nsIThreadManager.h"
#include "nsIJVMPluginInstance.h"
#include "SupportsMixin.h"
class MRJPlugin;
class MRJPluginInstance;
class MRJSession;
class MRJContext;
class MRJConsole;
class nsIJVMManager;
class MRJPlugin : public nsIJVMPlugin, public nsIRunnable,
public SupportsMixin {
public:
MRJPlugin();
virtual ~MRJPlugin();
// Currently, this is a singleton, statically allocated object.
void operator delete(void* ptr) {}
// NS_DECL_ISUPPORTS
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
// The Release method on NPIPlugin corresponds to NPP_Shutdown.
// The old NPP_New call has been factored into two plugin instance methods:
//
// NewInstance -- called once, after the plugin instance is created. This
// method is used to initialize the new plugin instance (although the actual
// plugin instance object will be created by the plugin manager).
//
// NPIPluginInstance::Start -- called when the plugin instance is to be
// started. This happens in two circumstances: (1) after the plugin instance
// is first initialized, and (2) after a plugin instance is returned to
// (e.g. by going back in the window history) after previously being stopped
// by the Stop method.
// nsIFactory Methods.
NS_IMETHOD
CreateInstance(nsISupports *aOuter, const nsIID& aIID, void **aResult);
NS_IMETHOD
LockFactory(PRBool aLock) { return NS_ERROR_FAILURE; }
// nsIPlugin Methods.
// This call initializes the plugin and will be called before any new
// instances are created. It is passed browserInterfaces on which QueryInterface
// may be used to obtain an nsIPluginManager, and other interfaces.
NS_IMETHOD
Initialize(nsISupports* browserInterfaces);
// (Corresponds to NPP_Shutdown.)
// Called when the browser is done with the plugin factory, or when
// the plugin is disabled by the user.
NS_IMETHOD
Shutdown(void) { return NS_OK; }
// (Corresponds to NPP_GetMIMEDescription.)
NS_IMETHOD
GetMIMEDescription(const char* *result);
// (Corresponds to NPP_GetValue.)
NS_IMETHOD
GetValue(nsPluginVariable variable, void *value)
{
return NS_ERROR_FAILURE;
}
// (Corresponds to NPP_SetValue.)
NS_IMETHOD
SetValue(nsPluginVariable variable, void *value)
{
return NS_ERROR_FAILURE;
}
// JVM Plugin Methods.
// This method us used to start the Java virtual machine.
// It sets up any global state necessary to host Java programs.
// Note that calling this method is distinctly separate from
// initializing the nsIJVMPlugin object (done by the Initialize
// method).
NS_IMETHOD
StartupJVM(nsJVMInitArgs* initargs);
// This method us used to stop the Java virtual machine.
// It tears down any global state necessary to host Java programs.
// The fullShutdown flag specifies whether the browser is quitting
// (PR_TRUE) or simply whether the JVM is being shut down (PR_FALSE).
NS_IMETHOD
ShutdownJVM(PRBool fullShutdown);
// Causes the JVM to append a new directory to its classpath.
// If the JVM doesn't support this operation, an error is returned.
NS_IMETHOD
AddToClassPath(const char* dirPath);
// Causes the JVM to remove a directory from its classpath.
// If the JVM doesn't support this operation, an error is returned.
NS_IMETHOD
RemoveFromClassPath(const char* dirPath)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// Returns the current classpath in use by the JVM.
NS_IMETHOD
GetClassPath(const char* *result);
NS_IMETHOD
GetJavaWrapper(JNIEnv* env, jint jsobj, jobject *jobj);
NS_IMETHOD
GetJavaVM(JavaVM* *result);
// nsIJNIPlugin Methods.
// Find or create a JNIEnv for the current thread.
// Returns NULL if an error occurs.
NS_IMETHOD_(nsrefcnt)
GetJNIEnv(JNIEnv* *result);
// This method must be called when the caller is done using the JNIEnv.
// This decrements a refcount associated with it may free it.
NS_IMETHOD_(nsrefcnt)
ReleaseJNIEnv(JNIEnv* env);
/**
* This creates a new secure communication channel with Java. The second parameter,
* nativeEnv, if non-NULL, will be the actual thread for Java communication.
* Otherwise, a new thread should be created.
* @param proxyEnv the env to be used by all clients on the browser side
* @return outSecureEnv the secure environment used by the proxyEnv
*/
NS_IMETHOD
CreateSecureEnv(JNIEnv* proxyEnv, nsISecureJNI2* *outSecureEnv);
/**
* Gives time to the JVM from the main event loop of the browser. This is
* necessary when there aren't any plugin instances around, but Java threads exist.
*/
NS_IMETHOD
SpendTime(PRUint32 timeMillis);
/**
* The Run method gives time to the JVM periodically. This makes SpendTIme() obsolete.
*/
NS_IMETHOD
Run();
// NON-INTERFACE methods, for internal use only.
MRJSession* getSession();
nsIJVMManager* getManager();
nsIThreadManager* getThreadManager();
MRJPluginInstance* getPluginInstance(jobject applet);
MRJPluginInstance* getPluginInstance(JNIEnv* jenv);
Boolean inPluginThread();
private:
nsIJVMManager* mManager;
nsIThreadManager* mThreadManager;
MRJSession* mSession;
MRJConsole* mConsole;
PRUint32 mPluginThreadID;
Boolean mIsEnabled;
// support for nsISupports.
static nsID sInterfaceIDs[];
};
class MRJPluginInstance : public nsIJVMPluginInstance,
private SupportsMixin {
public:
MRJPluginInstance(MRJPlugin* plugin);
virtual ~MRJPluginInstance();
// NS_DECL_ISUPPORTS
NS_IMETHOD QueryInterface(const nsIID& aIID, void** aInstancePtr);
NS_IMETHOD_(nsrefcnt) AddRef(void);
NS_IMETHOD_(nsrefcnt) Release(void);
// (Corresponds to NPP_HandleEvent.)
NS_IMETHOD
HandleEvent(nsPluginEvent* event, PRBool* handled);
// The Release method on NPIPluginInstance corresponds to NPP_Destroy.
NS_IMETHOD
Initialize(nsIPluginInstancePeer* peer);
// Required backpointer to the peer.
NS_IMETHOD
GetPeer(nsIPluginInstancePeer* *result);
// See comment for nsIPlugin::CreateInstance, above.
NS_IMETHOD
Start(void);
// The old NPP_Destroy call has been factored into two plugin instance
// methods:
//
// Stop -- called when the plugin instance is to be stopped (e.g. by
// displaying another plugin manager window, causing the page containing
// the plugin to become removed from the display).
//
// Destroy -- called once, before the plugin instance peer is to be
// destroyed. This method is used to destroy the plugin instance.
NS_IMETHOD
Stop(void);
NS_IMETHOD
Destroy(void);
// (Corresponds to NPP_SetWindow.)
NS_IMETHOD
SetWindow(nsPluginWindow* window);
// (Corresponds to NPP_NewStream.)
NS_IMETHOD
NewStream(nsIPluginStreamPeer* peer, nsIPluginStream* *result)
{
*result = NULL;
return NS_ERROR_NOT_IMPLEMENTED;
}
// (Corresponds to NPP_Print.)
NS_IMETHOD
Print(nsPluginPrint* platformPrint)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// (Corresponds to NPP_URLNotify.)
NS_IMETHOD
URLNotify(const char* url, const char* target,
nsPluginReason reason, void* notifyData)
{
return NS_OK;
}
/**
* Returns the value of a variable associated with the plugin instance.
*
* @param variable - the plugin instance variable to get
* @param value - the address of where to store the resulting value
* @result - NS_OK if this operation was successful
*/
NS_IMETHOD
GetValue(nsPluginInstanceVariable variable, void *value)
{
return NS_ERROR_NOT_IMPLEMENTED;
}
// nsIJVMPluginInstance methods.
// This method is called when LiveConnect wants to find the Java object
// associated with this plugin instance, e.g. the Applet or JavaBean object.
NS_IMETHOD
GetJavaObject(jobject *result);
NS_IMETHOD
GetText(const char* *result)
{
*result = NULL;
return NS_OK;
}
// Accessing the list of instances.
static MRJPluginInstance* getInstances(void);
MRJPluginInstance* getNextInstance(void);
MRJContext* getContext(void);
MRJSession* getSession(void);
private:
void pushInstance();
void popInstance();
private:
nsIPluginInstancePeer* mPeer;
nsIWindowlessPluginInstancePeer* mWindowlessPeer;
MRJPlugin* mPlugin;
MRJSession* mSession;
MRJContext* mContext;
jobject mApplet;
// maintain a list of instances.
MRJPluginInstance* mNext;
// support for nsISupports.
static nsID sInterfaceIDs[];
};

Просмотреть файл

@ -0,0 +1,322 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJSession.cpp
Encapsulates a session with the MacOS Runtime for Java.
by Patrick C. Beard.
*/
#include "MRJSession.h"
#include "MRJContext.h"
#include "MRJConsole.h"
#include "MRJMonitor.h"
#include <string.h>
#include <Memory.h>
#include <Files.h>
#include <Dialogs.h>
#include <Appearance.h>
extern MRJConsole* theConsole;
static Boolean appearanceManagerExists()
{
long response = 0;
return (Gestalt(gestaltAppearanceAttr, &response) == noErr && (response & (1 << gestaltAppearanceExists)));
}
static void debug_out(StringPtr stream, const void *message, UInt32 messageLengthInBytes)
{
Str255 pmsg;
pmsg[0] = messageLengthInBytes;
::BlockMoveData(message, &pmsg[1], pmsg[0]);
// why not display this using the Appearance Manager's wizzy new alert?
if (appearanceManagerExists()) {
static AlertStdAlertParamRec params = {
false, // Boolean movable; /* Make alert movable modal */
false, // Boolean helpButton; /* Is there a help button? */
NULL, // ModalFilterUPP filterProc; /* Event filter */
"\pOK", // StringPtr defaultText; /* Text for button in OK position */
NULL, // StringPtr cancelText; /* Text for button in cancel position */
NULL, // StringPtr otherText; /* Text for button in left position */
1, // SInt16 defaultButton; /* Which button behaves as the default */
0, // SInt16 cancelButton; /* Which one behaves as cancel (can be 0) */
kWindowDefaultPosition
// UInt16 position; /* Position (kWindowDefaultPosition in this case */
/* equals kWindowAlertPositionParentWindowScreen) */
};
SInt16 itemHit = 0;
OSErr result = ::StandardAlert(kAlertPlainAlert, stream, pmsg, &params, &itemHit);
} else {
::DebugStr(pmsg);
}
}
static void java_stdout(JMSessionRef session, const void *message, SInt32 messageLengthInBytes)
{
// if (theConsole != NULL)
// theConsole->write(message, messageLengthInBytes);
/* else
debug_out("\pSystem.out:", message, messageLengthInBytes); */
}
static void java_stderr(JMSessionRef session, const void *message, SInt32 messageLengthInBytes)
{
// if (theConsole != NULL)
// theConsole->write(message, messageLengthInBytes);
/* else
debug_out("\pSystem.err:", message, messageLengthInBytes); */
}
static SInt32 java_stdin(JMSessionRef session, void *buffer, SInt32 maxBufferLength)
{
return -1;
}
static Boolean java_exit(JMSessionRef session, SInt32 status)
{
return false; /* not allowed in a plugin. */
}
static Boolean java_authenticate(JMSessionRef session, const char *url, const char *realm, char userName[255], char password[255])
{
return false;
}
static void java_lowmem(JMSessionRef session)
{
/* can ask Netscape to purge some memory. */
// NPN_MemFlush(512 * 1024);
}
MRJSession::MRJSession()
: mSession(NULL), mStatus(noErr), mMainEnv(NULL), mFirst(NULL), mLast(NULL), mMessageMonitor(NULL), mLockCount(0)
{
// Make sure JManager exists.
if (&::JMGetVersion != NULL && ::JMGetVersion() >= kJMVersion) {
static JMSessionCallbacks callbacks = {
kJMVersion, /* should be set to kJMVersion */
&java_stdout, /* JM will route "stdout" to this function. */
&java_stderr, /* JM will route "stderr" to this function. */
&java_stdin, /* read from console - can be nil for default behavior (no console IO) */
&java_exit, /* handle System.exit(int) requests */
&java_authenticate, /* present basic authentication dialog */
&java_lowmem /* Low Memory notification Proc */
};
mStatus = ::JMOpenSession(&mSession, eJManager2Defaults, eCheckRemoteCode,
&callbacks, kTextEncodingMacRoman, NULL);
// capture the main environment, so it can be distinguished from true Java threads.
if (mStatus == noErr) mMainEnv = ::JMGetCurrentEnv(mSession);
// create a monitor for the message queue to unblock Java threads.
mMessageMonitor = new MRJMonitor(this);
} else {
mStatus = kJMVersionError;
}
}
MRJSession::~MRJSession()
{
if (mMessageMonitor != NULL) {
mMessageMonitor->notifyAll();
delete mMessageMonitor;
}
if (mSession != NULL) {
mStatus = ::JMCloseSession(mSession);
mSession = NULL;
}
}
JMSessionRef MRJSession::getSessionRef()
{
return mSession;
}
JNIEnv* MRJSession::getCurrentEnv()
{
return ::JMGetCurrentEnv(mSession);
}
JNIEnv* MRJSession::getMainEnv()
{
return mMainEnv;
}
JavaVM* MRJSession::getJavaVM()
{
JNIEnv* env = ::JMGetCurrentEnv(mSession);
JavaVM* vm = NULL;
env->GetJavaVM(&vm);
return vm;
}
Boolean MRJSession::onMainThread()
{
JNIEnv* env = ::JMGetCurrentEnv(mSession);
return (env == mMainEnv);
}
inline StringPtr c2p(const char* cstr, StringPtr pstr)
{
pstr[0] = (unsigned char)strlen(cstr);
::BlockMoveData(cstr, pstr + 1, pstr[0]);
return pstr;
}
Boolean MRJSession::addToClassPath(const char* dirPath)
{
// Need to convert the path into an FSSpec, and add it MRJ's class path.
Str255 path;
FSSpec pathSpec;
OSStatus status = ::FSMakeFSSpec(0, 0, c2p(dirPath, path), &pathSpec);
if (status == noErr)
status = ::JMAddToClassPath(mSession, &pathSpec);
return (status == noErr);
}
Boolean MRJSession::addURLToClassPath(const char* fileURL)
{
OSStatus status = noErr;
// Need to convert the URL into an FSSpec, and add it MRJ's class path.
JMTextRef urlRef = NULL;
status = ::JMNewTextRef(mSession, &urlRef, kTextEncodingMacRoman, fileURL, strlen(fileURL));
if (status == noErr) {
FSSpec pathSpec;
status = ::JMURLToFSS(mSession, urlRef, &pathSpec);
if (status == noErr)
status = ::JMAddToClassPath(mSession, &pathSpec);
::JMDisposeTextRef(urlRef);
}
return (status == noErr);
}
char* MRJSession::getProperty(const char* propertyName)
{
char* result = NULL;
OSStatus status = noErr;
JMTextRef nameRef = NULL, valueRef = NULL;
status = ::JMNewTextRef(mSession, &nameRef, kTextEncodingMacRoman, propertyName, strlen(propertyName));
if (status == noErr) {
status = ::JMGetSessionProperty(mSession, nameRef, &valueRef);
::JMDisposeTextRef(nameRef);
if (status == noErr && valueRef != NULL) {
UInt32 valueLength = 0;
status = ::JMGetTextLengthInBytes(valueRef, kTextEncodingMacRoman, &valueLength);
if (status == noErr) {
result = new char[valueLength + 1];
if (result != NULL) {
UInt32 actualLength;
status = ::JMGetTextBytes(valueRef, kTextEncodingMacRoman, result, valueLength, &actualLength);
result[valueLength] = '\0';
}
::JMDisposeTextRef(valueRef);
}
}
}
return result;
}
void MRJSession::setStatus(OSStatus status)
{
mStatus = status;
}
OSStatus MRJSession::getStatus()
{
return mStatus;
}
void MRJSession::idle(UInt32 milliseconds)
{
// Each call to idle processes a single message.
dispatchMessage();
// Guard against entering the VM multiple times.
if (mLockCount == 0) {
lock();
mStatus = ::JMIdle(mSession, milliseconds);
unlock();
}
#if 0
else {
// sleep the current thread.
JNIEnv* env = getCurrentEnv();
jclass threadClass = env->FindClass("java/lang/Thread");
if (threadClass != NULL) {
jmethodID sleepMethod = env->GetStaticMethodID(threadClass, "sleep", "(J)V");
env->CallStaticVoidMethod(threadClass, sleepMethod, jlong(milliseconds));
env->DeleteLocalRef(threadClass);
}
}
#endif
}
void MRJSession::sendMessage(NativeMessage* message)
{
// can't block the main env, otherwise messages will never be processed!
if (onMainThread()) {
message->execute();
} else {
postMessage(message);
mMessageMonitor->wait();
}
}
/**
* Put a message on the queue.
*/
void MRJSession::postMessage(NativeMessage* message)
{
if (mFirst == NULL) {
mFirst = mLast = message;
} else {
mLast->setNext(message);
mLast = message;
}
message->setNext(NULL);
}
void MRJSession::dispatchMessage()
{
if (mFirst != NULL) {
NativeMessage* message = mFirst;
mFirst = message->getNext();
if (mFirst == NULL) mLast = NULL;
message->setNext(NULL);
message->execute();
mMessageMonitor->notify();
}
}
void MRJSession::lock()
{
++mLockCount;
}
void MRJSession::unlock()
{
--mLockCount;
}

Просмотреть файл

@ -0,0 +1,96 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
MRJSession.h
Encapsulates a session with the MacOS Runtime for Java.
by Patrick C. Beard.
*/
#pragma once
#include "jni.h"
#include "JManager.h"
class NativeMessage {
public:
NativeMessage() : mNext(NULL) {}
virtual void execute() = 0;
void setNext(NativeMessage* next) { mNext = next; }
NativeMessage* getNext() { return mNext; }
private:
NativeMessage* mNext;
};
// FIXME: need an interface for setting security options, etc.
class MRJContext;
class Monitor;
class MRJSession {
public:
MRJSession();
virtual ~MRJSession();
JMSessionRef getSessionRef();
JNIEnv* getCurrentEnv();
JNIEnv* getMainEnv();
JavaVM* getJavaVM();
Boolean onMainThread();
Boolean addToClassPath(const char* dirPath);
Boolean addURLToClassPath(const char* fileURL);
char* getProperty(const char* propertyName);
void setStatus(OSStatus status);
OSStatus getStatus();
void idle(UInt32 milliseconds = kDefaultJMTime);
void sendMessage(NativeMessage* message);
/**
* Used to prevent reentering the VM.
*/
void lock();
void unlock();
private:
void postMessage(NativeMessage* message);
void dispatchMessage();
private:
JMSessionRef mSession;
OSStatus mStatus;
JNIEnv* mMainEnv;
// Message queue.
NativeMessage* mFirst;
NativeMessage* mLast;
Monitor* mMessageMonitor;
UInt32 mLockCount;
};

Просмотреть файл

@ -0,0 +1,39 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
Monitor.h
Abstract class representing monitors.
by Patrick C. Beard.
*/
#pragma once
class Monitor {
public:
virtual ~Monitor() {}
virtual void enter() = 0;
virtual void exit() = 0;
virtual void wait() = 0;
virtual void wait(long long millis) = 0;
virtual void notify() = 0;
virtual void notifyAll() = 0;
};

Просмотреть файл

@ -0,0 +1,87 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
NativeMonitor.cpp
Provides a C++ interface to native monitors.
by Patrick C. Beard.
*/
#include "NativeMonitor.h"
#include "MRJSession.h"
#include "nsIThreadManager.h"
NativeMonitor::NativeMonitor(MRJSession* session, nsIThreadManager* manager, void* address)
: mSession(session), mManager(manager), mAddress(address)
{
if (address == NULL)
mAddress = this;
}
NativeMonitor::~NativeMonitor() {}
void NativeMonitor::enter()
{
mManager->EnterMonitor(mAddress);
}
void NativeMonitor::exit()
{
mManager->ExitMonitor(mAddress);
}
void NativeMonitor::wait()
{
// this is weird hackery, but we don't want to let the VM be reentered while we wait on a native monitor.
Boolean inJavaThread = (mSession->getMainEnv() != mSession->getCurrentEnv());
if (inJavaThread)
mSession->lock();
if (mManager->EnterMonitor(mAddress) == NS_OK) {
mManager->Wait(mAddress);
mManager->ExitMonitor(mAddress);
}
if (inJavaThread)
mSession->unlock();
}
void NativeMonitor::wait(long long millis)
{
if (mManager->EnterMonitor(mAddress) == NS_OK) {
mManager->Wait(mAddress, PRUint32(millis));
mManager->ExitMonitor(mAddress);
}
}
void NativeMonitor::notify()
{
if (mManager->EnterMonitor(mAddress) == NS_OK) {
mManager->Notify(mAddress);
mManager->ExitMonitor(mAddress);
}
}
void NativeMonitor::notifyAll()
{
if (mManager->EnterMonitor(mAddress) == NS_OK) {
mManager->NotifyAll(mAddress);
mManager->ExitMonitor(mAddress);
}
}

Просмотреть файл

@ -0,0 +1,48 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
NativeMonitor.h
Provides a C++ interface to native monitors.
by Patrick C. Beard.
*/
#include "Monitor.h"
class MRJSession;
class nsIThreadManager;
class NativeMonitor : public Monitor {
public:
NativeMonitor(MRJSession* session, nsIThreadManager* manager, void* address = NULL);
virtual ~NativeMonitor();
virtual void enter();
virtual void exit();
virtual void wait();
virtual void wait(long long millis);
virtual void notify();
virtual void notifyAll();
private:
MRJSession* mSession;
nsIThreadManager* mManager;
void* mAddress;
};

Просмотреть файл

@ -0,0 +1,48 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
PluginNew.cpp
new & delete operators for plugins.
by Patrick C. Beard.
*/
#include <new.h>
#include "jni.h"
#include "nsIMalloc.h"
// Warning: this forces all C++ allocation to go through Navigator's memory allocation
// Routines. As such, static constructors that use operator new may not work. This can
// be fixed if we delay static construction (see the call to __InitCode__() in npmac.cpp).
extern nsIMalloc* theMemoryAllocator;
void* operator new(size_t size)
{
if (theMemoryAllocator != NULL)
return theMemoryAllocator->Alloc(size);
return NULL;
}
void operator delete(void* ptr)
{
if (ptr != NULL && theMemoryAllocator != NULL)
theMemoryAllocator->Free(ptr);
}

Просмотреть файл

@ -0,0 +1,67 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
StringUtils.cpp
*/
#include "StringUtils.h"
#include <string.h>
inline unsigned char toupper(unsigned char c)
{
return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;
}
int strcasecmp(const char * str1, const char * str2)
{
#if !__POWERPC__
const unsigned char * p1 = (unsigned char *) str1;
const unsigned char * p2 = (unsigned char *) str2;
unsigned char c1, c2;
while (toupper(c1 = *p1++) == toupper(c2 = *p2++))
if (!c1)
return(0);
#else
const unsigned char * p1 = (unsigned char *) str1 - 1;
const unsigned char * p2 = (unsigned char *) str2 - 1;
unsigned long c1, c2;
while (toupper(c1 = *++p1) == toupper(c2 = *++p2))
if (!c1)
return(0);
#endif
return(toupper(c1) - toupper(c2));
}
char* strdup(const char* str)
{
if (str != NULL) {
char* result = new char[::strlen(str) + 1];
if (result != NULL)
::strcpy(result, str);
return result;
}
return NULL;
}

Просмотреть файл

@ -0,0 +1,34 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
StringUtils.h
String utilities.
*/
#pragma once
/**
* Case-insensitive string comparison.
*/
int strcasecmp(const char * str1, const char * str2);
/**
* Duplicates a C string, returns NULL if failed, or passed NULL.
*/
char* strdup(const char* str);

Просмотреть файл

@ -0,0 +1,80 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
SupportsMixin.cpp
Experimental way to implement nsISupports interface.
by Patrick C. Beard.
*/
#include "SupportsMixin.h"
// Standard ISupported Method Implementations.
SupportsMixin::SupportsMixin(nsISupports* instance, nsID* ids, UInt32 idCount)
: mInstance(instance), mRefCount(0), mIDs(ids), mIDCount(idCount)
{
}
SupportsMixin::~SupportsMixin()
{
if (mRefCount > 0) {
::DebugStr("\pmRefCount > 0!");
}
}
nsresult SupportsMixin::queryInterface(const nsIID& aIID, void** aInstancePtr)
{
if (aInstancePtr == NULL) {
return NS_ERROR_NULL_POINTER;
}
// first check to see if it's one of our known interfaces.
// need to solve the non-left inheritance graph case.
nsID* ids = mIDs;
UInt32 count = mIDCount;
for (UInt32 i = 0; i < count; i++) {
if (aIID.Equals(ids[i])) {
*aInstancePtr = (void*) mInstance;
addRef();
return NS_OK;
}
}
// finally, does the interface match nsISupports?
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
if (aIID.Equals(kISupportsIID)) {
*aInstancePtr = (void*) mInstance;
addRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
nsrefcnt SupportsMixin::addRef()
{
return ++mRefCount;
}
nsrefcnt SupportsMixin::release()
{
if (--mRefCount == 0) {
delete this;
return 0;
}
return mRefCount;
}

Просмотреть файл

@ -0,0 +1,44 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
SupportsMixin.h
Experimental way to implement nsISupports interface.
by Patrick C. Beard.
*/
#pragma once
#include "nsISupports.h"
class SupportsMixin {
public:
SupportsMixin(nsISupports* instance, nsID* ids, UInt32 idCount);
virtual ~SupportsMixin();
nsresult queryInterface(const nsIID& aIID, void** aInstancePtr);
nsrefcnt addRef(void);
nsrefcnt release(void);
protected:
nsISupports* mInstance;
nsrefcnt mRefCount;
nsID* mIDs;
UInt32 mIDCount;
};

Просмотреть файл

@ -0,0 +1,260 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
TopLevelFrame.cpp
An MRJFrame sub-class that manages the behavior of a top-level window
running inside the Communicator.
by Patrick C. Beard.
*/
#include <Controls.h>
#include <Events.h>
#include "TopLevelFrame.h"
#include "LocalPort.h"
#include "nsIPluginManager2.h"
extern nsIPluginManager2* thePluginManager2;
static void UnsetPort(GrafPtr port);
static short getModifiers();
TopLevelFrame::TopLevelFrame(nsIEventHandler* handler, JMFrameRef frameRef, JMFrameKind kind,
const Rect* initialBounds, Boolean resizeable)
: MRJFrame(frameRef),
mHandler(handler), mWindow(NULL), mBounds(*initialBounds)
{
Boolean hasGoAway = true;
SInt16 windowProc = documentProc;
SInt16 resizeHeight = resizeable ? 15 : 0;
switch (kind) {
case eBorderlessModelessWindowFrame:
hasGoAway = false;
windowProc = plainDBox;
// mBounds.bottom += resizeHeight;
resizeable = false;
break;
case eModelessWindowFrame:
case eModelessDialogFrame:
hasGoAway = true;
windowProc = resizeable ? zoomDocProc : documentProc;
// mBounds.bottom += resizeHeight;
break;
case eModalWindowFrame:
hasGoAway = true;
// We have to allow resizeable modal windows.
windowProc = resizeable ? documentProc : movableDBoxProc;
break;
}
mWindow = ::NewCWindow(NULL, &mBounds, "\p", false, windowProc, WindowPtr(-1), hasGoAway, long(this));
if (mWindow != NULL) {
if (getModifiers() & controlKey) {
// hack: Try creating a root control, to see if that messes up MRJ controls.
ControlHandle rootControl = NULL;
OSErr result = ::GetRootControl(mWindow, &rootControl);
if (result != noErr || rootControl == NULL) {
result = ::CreateRootControl(mWindow, &rootControl);
if (result == noErr && rootControl != NULL) {
FSSpec dumpFile = { -1, 2, "\pJava Console Controls" };
result = DumpControlHierarchy(mWindow, &dumpFile);
}
}
}
Point zeroPt = { 0, 0 };
::JMSetFrameVisibility(frameRef, mWindow, zeroPt, nil);
}
}
TopLevelFrame::~TopLevelFrame()
{
// make sure the window is hidden (and unregistered with the browser).
showHide(false);
// make sure this port isn't ever current again.
::UnsetPort(mWindow);
if (mWindow != NULL)
::DisposeWindow(mWindow);
}
void TopLevelFrame::setSize(const Rect* newSize)
{
mBounds = *newSize;
if (mWindow != NULL) {
SInt16 width = newSize->right - newSize->left;
SInt16 height = newSize->bottom - newSize->top;
::SizeWindow(mWindow, width, height, true);
::MoveWindow(mWindow, newSize->left, newSize->top, false);
}
}
void TopLevelFrame::invalRect(const Rect* invalidRect)
{
if (mWindow != NULL) {
::InvalRect(invalidRect);
}
}
void TopLevelFrame::showHide(Boolean visible)
{
if (mWindow != NULL && visible != IsWindowVisible(mWindow)) {
if (visible) {
// Have to notify the browser that this window exists, so that it will receive events.
thePluginManager2->RegisterWindow(mHandler, mWindow);
// the plugin manager takes care of showing the window.
// ::ShowWindow(mWindow);
// ::SelectWindow(mWindow);
} else {
// the plugin manager takes care of hiding the window.
// ::HideWindow(mWindow);
// Let the browser know it doesn't have to send events anymore.
thePluginManager2->UnregisterWindow(mHandler, mWindow);
}
// ::ShowHide(mWindow, visible);
}
}
void TopLevelFrame::setTitle(const StringPtr title)
{
if (mWindow != NULL) {
::SetWTitle(mWindow, title);
}
}
void TopLevelFrame::checkUpdate()
{
}
void TopLevelFrame::reorder(ReorderRequest request)
{
switch (request) {
case eBringToFront: /* bring the window to front */
break;
case eSendToBack: /* send the window to back */
break;
case eSendBehindFront: /* send the window behind the front window */
break;
}
}
void TopLevelFrame::setResizeable(Boolean resizeable)
{
// this might have to recreate the window, no?
}
static void computeBounds(WindowRef window, Rect* bounds)
{
LocalPort port(window);
port.Enter();
Point position = { 0, 0 };
::LocalToGlobal(&position);
*bounds = window->portRect;
port.Exit();
::OffsetRect(bounds, position.h, position.v);
}
void TopLevelFrame::activate(Boolean active)
{
focusEvent(active);
MRJFrame::activate(active);
}
void TopLevelFrame::click(const EventRecord* event)
{
Point where = event->where;
SInt16 modifiers = event->modifiers;
WindowRef hitWindow;
short partCode = ::FindWindow(where, &hitWindow);
switch (partCode) {
case inContent:
::SelectWindow(mWindow);
MRJFrame::click(event);
break;
case inDrag:
Rect bounds = (**GetGrayRgn()).rgnBBox;
DragWindow(mWindow, where, &bounds);
computeBounds(mWindow, &mBounds);
break;
case inGrow:
Rect limits = { 30, 30, 5000, 5000 };
long result = GrowWindow(mWindow, where, &limits);
if (result != 0) {
short width = (result & 0xFFFF);
short height = (result >> 16) & 0xFFFF;
Rect newBounds;
topLeft(newBounds) = topLeft(mBounds);
newBounds.right = newBounds.left + width;
newBounds.bottom = newBounds.top + height;
::JMSetFrameSize(mFrameRef, &newBounds);
}
break;
case inGoAway:
if (::TrackGoAway(mWindow, where))
::JMFrameGoAway(mFrameRef);
break;
case inZoomIn:
case inZoomOut:
if (::TrackBox(mWindow, where, partCode)) {
ZoomWindow(mWindow, partCode, true);
computeBounds(mWindow, &mBounds);
::JMSetFrameSize(mFrameRef, &mBounds);
}
break;
case inCollapseBox:
break;
}
}
WindowRef TopLevelFrame::getWindow()
{
return mWindow;
}
GrafPtr TopLevelFrame::getPort()
{
return mWindow;
}
static void UnsetPort(GrafPtr port)
{
GrafPtr curPort;
::GetPort(&curPort);
if (curPort == port) {
::GetWMgrPort(&port);
::SetPort(port);
}
}
static short getModifiers()
{
EventRecord event;
::OSEventAvail(0, &event);
return event.modifiers;
}

Просмотреть файл

@ -0,0 +1,62 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
TopLevelFrame.h
An MRJFrame sub-class that manages the behavior of a top-level window
running inside the Communicator.
by Patrick C. Beard.
*/
#pragma once
#include "MRJFrame.h"
#ifndef __MACWINDOWS__
#include <MacWindows.h>
#endif
class nsIEventHandler;
class TopLevelFrame : public MRJFrame {
public:
TopLevelFrame(nsIEventHandler* handler, JMFrameRef frameRef, JMFrameKind kind, const Rect* initialBounds, Boolean resizeable);
virtual ~TopLevelFrame();
virtual void setSize(const Rect* newSize);
virtual void invalRect(const Rect* invalidRect);
virtual void showHide(Boolean visible);
virtual void setTitle(const StringPtr title);
virtual void checkUpdate();
virtual void reorder(ReorderRequest request);
virtual void setResizeable(Boolean resizeable);
virtual void activate(Boolean active);
virtual void click(const EventRecord* event);
WindowRef getWindow();
protected:
virtual GrafPtr getPort();
private:
nsIEventHandler* mHandler;
WindowRef mWindow;
Rect mBounds;
};

Просмотреть файл

@ -0,0 +1,681 @@
/*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
// npmac.cpp
//
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
#include <Processes.h>
#include <Gestalt.h>
#include <CodeFragments.h>
#include <Timer.h>
#include <Resources.h>
#include <ToolUtils.h>
#define XP_MAC 1
#define NDEBUG 1
//
// A4Stuff.h contains the definition of EnterCodeResource and
// EnterCodeResource, used for setting up the code resourceÕs
// globals for 68K (analagous to the function SetCurrentA5
// defined by the toolbox).
//
#include <A4Stuff.h>
#include "jri.h"
#include "npapi.h"
//
// The Mixed Mode procInfos defined in npupp.h assume Think C-
// style calling conventions. These conventions are used by
// Metrowerks with the exception of pointer return types, which
// in Metrowerks 68K are returned in A0, instead of the standard
// D0. Thus, since NPN_MemAlloc and NPN_UserAgent return pointers,
// Mixed Mode will return the values to a 68K plugin in D0, but
// a 68K plugin compiled by Metrowerks will expect the result in
// A0. The following pragma forces Metrowerks to use D0 instead.
//
#ifdef __MWERKS__
#ifndef powerc
#pragma pointers_in_D0
#endif
#endif
#include "npupp.h"
#ifdef __MWERKS__
#ifndef powerc
#pragma pointers_in_A0
#endif
#endif
// The following fix for static initializers (which fixes a preious
// incompatibility with some parts of PowerPlant, was submitted by
// Jan Ulbrich.
#ifdef __MWERKS__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef powerc
extern void __InitCode__(void);
#else
extern void __sinit(void);
#define __InitCode__ __sinit
#endif
extern void __destroy_global_chain(void);
#ifdef __cplusplus
}
#endif // __cplusplus
#endif // __MWERKS__
//
// Define PLUGIN_TRACE to 1 to have the wrapper functions emit
// DebugStr messages whenever they are called.
//
#define PLUGIN_TRACE 0
#if PLUGIN_TRACE
#define PLUGINDEBUGSTR(msg) ::DebugStr(msg)
#else
#define PLUGINDEBUGSTR
#endif
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
// Globals
//
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
QDGlobals* gQDPtr; // Pointer to NetscapeÕs QuickDraw globals
short gResFile; // Refnum of the pluginÕs resource file
NPNetscapeFuncs gNetscapeFuncs; // Function table for procs in Netscape called by plugin
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
// Wrapper functions for all calls from the plugin to Netscape.
// These functions let the plugin developer just call the APIs
// as documented and defined in npapi.h, without needing to know
// about the function table and call macros in npupp.h.
//
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor)
{
*plugin_major = NP_VERSION_MAJOR;
*plugin_minor = NP_VERSION_MINOR;
*netscape_major = gNetscapeFuncs.version >> 8; // Major version is in high byte
*netscape_minor = gNetscapeFuncs.version & 0xFF; // Minor version is in low byte
}
NPError NPN_GetURLNotify(NPP instance, const char* url, const char* window, void* notifyData)
{
int navMinorVers = gNetscapeFuncs.version & 0xFF;
NPError err;
if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
{
err = CallNPN_GetURLNotifyProc(gNetscapeFuncs.geturlnotify, instance, url, window, notifyData);
}
else
{
err = NPERR_INCOMPATIBLE_VERSION_ERROR;
}
return err;
}
NPError NPN_GetURL(NPP instance, const char* url, const char* window)
{
return CallNPN_GetURLProc(gNetscapeFuncs.geturl, instance, url, window);
}
NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData)
{
int navMinorVers = gNetscapeFuncs.version & 0xFF;
NPError err;
if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
{
err = CallNPN_PostURLNotifyProc(gNetscapeFuncs.posturlnotify, instance, url,
window, len, buf, file, notifyData);
}
else
{
err = NPERR_INCOMPATIBLE_VERSION_ERROR;
}
return err;
}
NPError NPN_PostURL(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file)
{
return CallNPN_PostURLProc(gNetscapeFuncs.posturl, instance, url, window, len, buf, file);
}
NPError NPN_RequestRead(NPStream* stream, NPByteRange* rangeList)
{
return CallNPN_RequestReadProc(gNetscapeFuncs.requestread, stream, rangeList);
}
NPError NPN_NewStream(NPP instance, NPMIMEType type, const char* window, NPStream** stream)
{
int navMinorVers = gNetscapeFuncs.version & 0xFF;
NPError err;
if( navMinorVers >= NPVERS_HAS_STREAMOUTPUT )
{
err = CallNPN_NewStreamProc(gNetscapeFuncs.newstream, instance, type, window, stream);
}
else
{
err = NPERR_INCOMPATIBLE_VERSION_ERROR;
}
return err;
}
int32 NPN_Write(NPP instance, NPStream* stream, int32 len, void* buffer)
{
int navMinorVers = gNetscapeFuncs.version & 0xFF;
NPError err;
if( navMinorVers >= NPVERS_HAS_STREAMOUTPUT )
{
err = CallNPN_WriteProc(gNetscapeFuncs.write, instance, stream, len, buffer);
}
else
{
err = NPERR_INCOMPATIBLE_VERSION_ERROR;
}
return err;
}
NPError NPN_DestroyStream(NPP instance, NPStream* stream, NPError reason)
{
int navMinorVers = gNetscapeFuncs.version & 0xFF;
NPError err;
if( navMinorVers >= NPVERS_HAS_STREAMOUTPUT )
{
err = CallNPN_DestroyStreamProc(gNetscapeFuncs.destroystream, instance, stream, reason);
}
else
{
err = NPERR_INCOMPATIBLE_VERSION_ERROR;
}
return err;
}
void NPN_Status(NPP instance, const char* message)
{
CallNPN_StatusProc(gNetscapeFuncs.status, instance, message);
}
const char* NPN_UserAgent(NPP instance)
{
return CallNPN_UserAgentProc(gNetscapeFuncs.uagent, instance);
}
#define DEBUG_MEMORY 0
void* NPN_MemAlloc(uint32 size)
{
#if DEBUG_MEMORY
return (void*) NewPtrClear(size);
#else
return CallNPN_MemAllocProc(gNetscapeFuncs.memalloc, size);
#endif
}
void NPN_MemFree(void* ptr)
{
#if DEBUG_MEMORY
DisposePtr(Ptr(ptr));
#else
CallNPN_MemFreeProc(gNetscapeFuncs.memfree, ptr);
#endif
}
uint32 NPN_MemFlush(uint32 size)
{
return CallNPN_MemFlushProc(gNetscapeFuncs.memflush, size);
}
void NPN_ReloadPlugins(NPBool reloadPages)
{
CallNPN_ReloadPluginsProc(gNetscapeFuncs.reloadplugins, reloadPages);
}
JRIEnv* NPN_GetJavaEnv(void)
{
return CallNPN_GetJavaEnvProc( gNetscapeFuncs.getJavaEnv );
}
jref NPN_GetJavaPeer(NPP instance)
{
return CallNPN_GetJavaPeerProc( gNetscapeFuncs.getJavaPeer, instance );
}
NPError NPN_GetValue(NPP instance, NPNVariable variable, void *value)
{
return CallNPN_GetValueProc( gNetscapeFuncs.getvalue, instance, variable, value);
}
NPError NPN_SetValue(NPP instance, NPPVariable variable, void *value)
{
return CallNPN_SetValueProc( gNetscapeFuncs.setvalue, instance, variable, value);
}
void NPN_InvalidateRect(NPP instance, NPRect *rect)
{
CallNPN_InvalidateRectProc( gNetscapeFuncs.invalidaterect, instance, rect);
}
void NPN_InvalidateRegion(NPP instance, NPRegion region)
{
CallNPN_InvalidateRegionProc( gNetscapeFuncs.invalidateregion, instance, region);
}
void NPN_ForceRedraw(NPP instance)
{
CallNPN_ForceRedrawProc( gNetscapeFuncs.forceredraw, instance);
}
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
//
// Wrapper functions for all calls from Netscape to the plugin.
// These functions let the plugin developer just create the APIs
// as documented and defined in npapi.h, without needing to
// install those functions in the function table or worry about
// setting up globals for 68K plugins.
//
//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
NPError Private_Initialize(void);
void Private_Shutdown(void);
NPError Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved);
NPError Private_Destroy(NPP instance, NPSavedData** save);
NPError Private_SetWindow(NPP instance, NPWindow* window);
NPError Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype);
NPError Private_DestroyStream(NPP instance, NPStream* stream, NPError reason);
int32 Private_WriteReady(NPP instance, NPStream* stream);
int32 Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer);
void Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname);
void Private_Print(NPP instance, NPPrint* platformPrint);
int16 Private_HandleEvent(NPP instance, void* event);
void Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData);
jref Private_GetJavaClass(void);
NPError Private_Initialize(void)
{
NPError err;
EnterCodeResource();
PLUGINDEBUGSTR("\pInitialize;g;");
err = NPP_Initialize();
ExitCodeResource();
return err;
}
void Private_Shutdown(void)
{
EnterCodeResource();
PLUGINDEBUGSTR("\pShutdown;g;");
NPP_Shutdown();
__destroy_global_chain();
ExitCodeResource();
}
NPError Private_New(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved)
{
EnterCodeResource();
NPError ret = NPP_New(pluginType, instance, mode, argc, argn, argv, saved);
PLUGINDEBUGSTR("\pNew;g;");
ExitCodeResource();
return ret;
}
NPError Private_Destroy(NPP instance, NPSavedData** save)
{
NPError err;
EnterCodeResource();
PLUGINDEBUGSTR("\pDestroy;g;");
err = NPP_Destroy(instance, save);
ExitCodeResource();
return err;
}
NPError Private_SetWindow(NPP instance, NPWindow* window)
{
NPError err;
EnterCodeResource();
PLUGINDEBUGSTR("\pSetWindow;g;");
err = NPP_SetWindow(instance, window);
ExitCodeResource();
return err;
}
NPError Private_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype)
{
NPError err;
EnterCodeResource();
PLUGINDEBUGSTR("\pNewStream;g;");
err = NPP_NewStream(instance, type, stream, seekable, stype);
ExitCodeResource();
return err;
}
int32 Private_WriteReady(NPP instance, NPStream* stream)
{
int32 result;
EnterCodeResource();
PLUGINDEBUGSTR("\pWriteReady;g;");
result = NPP_WriteReady(instance, stream);
ExitCodeResource();
return result;
}
int32 Private_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer)
{
int32 result;
EnterCodeResource();
PLUGINDEBUGSTR("\pWrite;g;");
result = NPP_Write(instance, stream, offset, len, buffer);
ExitCodeResource();
return result;
}
void Private_StreamAsFile(NPP instance, NPStream* stream, const char* fname)
{
EnterCodeResource();
PLUGINDEBUGSTR("\pStreamAsFile;g;");
NPP_StreamAsFile(instance, stream, fname);
ExitCodeResource();
}
NPError Private_DestroyStream(NPP instance, NPStream* stream, NPError reason)
{
NPError err;
EnterCodeResource();
PLUGINDEBUGSTR("\pDestroyStream;g;");
err = NPP_DestroyStream(instance, stream, reason);
ExitCodeResource();
return err;
}
int16 Private_HandleEvent(NPP instance, void* event)
{
int16 result;
EnterCodeResource();
PLUGINDEBUGSTR("\pHandleEvent;g;");
result = NPP_HandleEvent(instance, event);
ExitCodeResource();
return result;
}
void Private_Print(NPP instance, NPPrint* platformPrint)
{
EnterCodeResource();
PLUGINDEBUGSTR("\pPrint;g;");
NPP_Print(instance, platformPrint);
ExitCodeResource();
}
void Private_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData)
{
EnterCodeResource();
PLUGINDEBUGSTR("\pURLNotify;g;");
NPP_URLNotify(instance, url, reason, notifyData);
ExitCodeResource();
}
jref Private_GetJavaClass(void)
{
EnterCodeResource();
PLUGINDEBUGSTR("\pGetJavaClass;g;");
jref clazz = NPP_GetJavaClass();
ExitCodeResource();
if (clazz)
{
JRIEnv* env = NPN_GetJavaEnv();
return (jref)JRI_NewGlobalRef(env, clazz);
}
return NULL;
}
void SetUpQD(void);
void SetUpQD(void)
{
ProcessSerialNumber PSN;
FSSpec myFSSpec;
Str63 name;
ProcessInfoRec infoRec;
OSErr result = noErr;
CFragConnectionID connID;
Str255 errName;
//
// Memorize the pluginÕs resource file
// refnum for later use.
//
gResFile = CurResFile();
//
// Ask the system if CFM is available.
//
long response;
OSErr err = Gestalt(gestaltCFMAttr, &response);
Boolean hasCFM = BitTst(&response, 31-gestaltCFMPresent);
if (hasCFM)
{
//
// GetProcessInformation takes a process serial number and
// will give us back the name and FSSpec of the application.
// See the Process Manager in IM.
//
infoRec.processInfoLength = sizeof(ProcessInfoRec);
infoRec.processName = name;
infoRec.processAppSpec = &myFSSpec;
PSN.highLongOfPSN = 0;
PSN.lowLongOfPSN = kCurrentProcess;
result = GetProcessInformation(&PSN, &infoRec);
if (result != noErr)
PLUGINDEBUGSTR("\pFailed in GetProcessInformation");
}
else
//
// If no CFM installed, assume it must be a 68K app.
//
result = -1;
if (result == noErr)
{
//
// Now that we know the app name and FSSpec, we can call GetDiskFragment
// to get a connID to use in a subsequent call to FindSymbol (it will also
// return the address of ÒmainÓ in app, which we ignore). If GetDiskFragment
// returns an error, we assume the app must be 68K.
//
Ptr mainAddr;
result = GetDiskFragment(infoRec.processAppSpec, 0L, 0L, infoRec.processName,
kReferenceCFrag, &connID, (Ptr*)&mainAddr, errName);
}
if (result == noErr)
{
//
// The app is a PPC code fragment, so call FindSymbol
// to get the exported ÒqdÓ symbol so we can access its
// QuickDraw globals.
//
CFragSymbolClass symClass;
result = FindSymbol(connID, "\pqd", (Ptr*)&gQDPtr, &symClass);
if (result != noErr)
PLUGINDEBUGSTR("\pFailed in FindSymbol qd");
}
else
{
//
// The app is 68K, so use its A5 to compute the address
// of its QuickDraw globals.
//
gQDPtr = (QDGlobals*)(*((long*)SetCurrentA5()) - (sizeof(QDGlobals) - sizeof(GrafPtr)));
}
}
NPError main(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* unloadUpp);
#pragma export on
#if GENERATINGCFM
RoutineDescriptor mainRD = BUILD_ROUTINE_DESCRIPTOR(uppNPP_MainEntryProcInfo, main);
#endif
#pragma export off
NPError main(NPNetscapeFuncs* nsTable, NPPluginFuncs* pluginFuncs, NPP_ShutdownUPP* unloadUpp)
{
EnterCodeResource();
PLUGINDEBUGSTR("\pmain");
NPError err = NPERR_NO_ERROR;
//
// Ensure that everything Netscape passed us is valid!
//
if ((nsTable == NULL) || (pluginFuncs == NULL) || (unloadUpp == NULL))
err = NPERR_INVALID_FUNCTABLE_ERROR;
//
// Check the ÒmajorÓ version passed in NetscapeÕs function table.
// We wonÕt load if the major version is newer than what we expect.
// Also check that the function tables passed in are big enough for
// all the functions we need (they could be bigger, if Netscape added
// new APIs, but thatÕs OK with us -- weÕll just ignore them).
//
if (err == NPERR_NO_ERROR)
{
if ((nsTable->version >> 8) > NP_VERSION_MAJOR) // Major version is in high byte
err = NPERR_INCOMPATIBLE_VERSION_ERROR;
// if (nsTable->size < sizeof(NPNetscapeFuncs))
// err = NPERR_INVALID_FUNCTABLE_ERROR;
// if (pluginFuncs->size < sizeof(NPPluginFuncs))
// err = NPERR_INVALID_FUNCTABLE_ERROR;
}
if (err == NPERR_NO_ERROR)
{
//
// Copy all the fields of NetscapeÕs function table into our
// copy so we can call back into Netscape later. Note that
// we need to copy the fields one by one, rather than assigning
// the whole structure, because the Netscape function table
// could actually be bigger than what we expect.
//
int navMinorVers = nsTable->version & 0xFF;
gNetscapeFuncs.version = nsTable->version;
gNetscapeFuncs.size = nsTable->size;
gNetscapeFuncs.posturl = nsTable->posturl;
gNetscapeFuncs.geturl = nsTable->geturl;
gNetscapeFuncs.requestread = nsTable->requestread;
gNetscapeFuncs.newstream = nsTable->newstream;
gNetscapeFuncs.write = nsTable->write;
gNetscapeFuncs.destroystream = nsTable->destroystream;
gNetscapeFuncs.status = nsTable->status;
gNetscapeFuncs.uagent = nsTable->uagent;
gNetscapeFuncs.memalloc = nsTable->memalloc;
gNetscapeFuncs.memfree = nsTable->memfree;
gNetscapeFuncs.memflush = nsTable->memflush;
gNetscapeFuncs.reloadplugins = nsTable->reloadplugins;
if( navMinorVers >= NPVERS_HAS_LIVECONNECT )
{
gNetscapeFuncs.getJavaEnv = nsTable->getJavaEnv;
gNetscapeFuncs.getJavaPeer = nsTable->getJavaPeer;
}
if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
{
gNetscapeFuncs.geturlnotify = nsTable->geturlnotify;
gNetscapeFuncs.posturlnotify = nsTable->posturlnotify;
}
gNetscapeFuncs.getvalue = nsTable->getvalue;
gNetscapeFuncs.setvalue = nsTable->setvalue;
gNetscapeFuncs.invalidaterect = nsTable->invalidaterect;
gNetscapeFuncs.invalidateregion = nsTable->invalidateregion;
gNetscapeFuncs.forceredraw = nsTable->forceredraw;
// defer static constructors until the global functions are initialized.
__InitCode__();
//
// Set up the plugin function table that Netscape will use to
// call us. Netscape needs to know about our version and size
// and have a UniversalProcPointer for every function we implement.
//
pluginFuncs->version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
pluginFuncs->size = sizeof(NPPluginFuncs);
pluginFuncs->newp = NewNPP_NewProc(Private_New);
pluginFuncs->destroy = NewNPP_DestroyProc(Private_Destroy);
pluginFuncs->setwindow = NewNPP_SetWindowProc(Private_SetWindow);
pluginFuncs->newstream = NewNPP_NewStreamProc(Private_NewStream);
pluginFuncs->destroystream = NewNPP_DestroyStreamProc(Private_DestroyStream);
pluginFuncs->asfile = NewNPP_StreamAsFileProc(Private_StreamAsFile);
pluginFuncs->writeready = NewNPP_WriteReadyProc(Private_WriteReady);
pluginFuncs->write = NewNPP_WriteProc(Private_Write);
pluginFuncs->print = NewNPP_PrintProc(Private_Print);
pluginFuncs->event = NewNPP_HandleEventProc(Private_HandleEvent);
if( navMinorVers >= NPVERS_HAS_NOTIFICATION )
{
pluginFuncs->urlnotify = NewNPP_URLNotifyProc(Private_URLNotify);
}
if( navMinorVers >= NPVERS_HAS_LIVECONNECT )
{
pluginFuncs->javaClass = (JRIGlobalRef) Private_GetJavaClass();
}
*unloadUpp = NewNPP_ShutdownProc(Private_Shutdown);
SetUpQD();
err = Private_Initialize();
}
ExitCodeResource();
return err;
}