From 6cf0255e587c3fc511e136d60c7c7c1a6497b78c Mon Sep 17 00:00:00 2001 From: "warren%netscape.com" Date: Tue, 28 Jul 1998 02:11:07 +0000 Subject: [PATCH] Committed from OJI_19980618_TIP_MERGE1. git-svn-id: svn://10.0.0.236/trunk@6602 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/caps/include/nsCaps.h | 148 ++ mozilla/caps/include/nsCapsEnums.h | 59 + mozilla/caps/src/nsCaps.cpp | 278 ++++ mozilla/cmd/winfe/npwplat.cpp | 896 ++++++++++++ mozilla/cmd/winfe/npwplat.h | 61 + mozilla/include/np2.h | 44 + mozilla/include/npupp.h | 1213 +++++++++++++++++ mozilla/js/macbuild/LiveConnect.Prefix | 31 + mozilla/js/macbuild/LiveConnect.mcp | Bin 0 -> 61196 bytes mozilla/js/macbuild/LiveConnectClasses.mcp | Bin 0 -> 92447 bytes mozilla/js/macbuild/LiveConnectDebug.Prefix | 31 + mozilla/js/src/liveconnect/MANIFEST | 4 + mozilla/js/src/liveconnect/Makefile | 107 ++ mozilla/js/src/liveconnect/classes/Makefile | 65 + .../js/src/liveconnect/classes/makefile.win | 74 + .../netscape/javascript/JSException.java | 56 + .../classes/netscape/javascript/JSObject.java | 150 ++ .../classes/netscape/javascript/JSProxy.java | 37 + .../netscape/javascript/JSRunnable.java | 31 + .../classes/netscape/javascript/JSUtil.java | 38 + mozilla/js/src/liveconnect/jsj.c | 801 +++++++++++ mozilla/js/src/liveconnect/jsj1640.rc | 76 ++ mozilla/js/src/liveconnect/jsj_JSObject.c | 1137 +++++++++++++++ mozilla/js/src/liveconnect/jsj_JavaArray.c | 404 ++++++ mozilla/js/src/liveconnect/jsj_JavaClass.c | 584 ++++++++ mozilla/js/src/liveconnect/jsj_JavaObject.c | 713 ++++++++++ mozilla/js/src/liveconnect/jsj_JavaPackage.c | 504 +++++++ mozilla/js/src/liveconnect/jsj_array.c | 183 +++ mozilla/js/src/liveconnect/jsj_class.c | 598 ++++++++ mozilla/js/src/liveconnect/jsj_convert.c | 772 +++++++++++ mozilla/js/src/liveconnect/jsj_field.c | 386 ++++++ mozilla/js/src/liveconnect/jsj_hash.c | 481 +++++++ mozilla/js/src/liveconnect/jsj_hash.h | 141 ++ mozilla/js/src/liveconnect/jsj_method.c | 1158 ++++++++++++++++ mozilla/js/src/liveconnect/jsj_nodl.c | 0 mozilla/js/src/liveconnect/jsj_private.h | 507 +++++++ mozilla/js/src/liveconnect/jsj_utils.c | 369 +++++ mozilla/js/src/liveconnect/jsjava.h | 244 ++++ mozilla/js/src/liveconnect/makefile.win | 203 +++ .../netscape_javascript_JSObject.h | 101 ++ mozilla/modules/plugin/base/public/npupp.h | 1213 +++++++++++++++++ .../plugin/base/public/nsIEventHandler.h | 81 ++ .../public/nsIJRILiveConnectPlugInstPeer.h | 98 ++ .../base/public/nsILiveConnectPlugInstPeer.h | 86 ++ .../plugin/base/public/nsINetworkManager.h | 118 ++ .../base/public/nsIWindowlessPlugInstPeer.h | 70 + mozilla/modules/plugin/base/src/Makefile | 44 + mozilla/modules/plugin/base/src/makefile.win | 71 + .../modules/plugin/base/src/ns4xPlugin.cpp | 737 ++++++++++ mozilla/modules/plugin/base/src/ns4xPlugin.h | 213 +++ .../modules/plugin/base/src/nsIPluginHost.h | 42 + .../plugin/base/src/nsPluginFactory.cpp | 156 +++ .../plugin/base/src/nsPluginHostImpl.cpp | 578 ++++++++ .../plugin/base/src/nsPluginHostImpl.h | 102 ++ .../modules/plugin/base/src/nsPluginsCID.h | 30 + mozilla/modules/plugin/nglsrc/Makefile | 44 + mozilla/modules/plugin/nglsrc/makefile.win | 71 + mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp | 737 ++++++++++ mozilla/modules/plugin/nglsrc/ns4xPlugin.h | 213 +++ mozilla/modules/plugin/nglsrc/nsIPluginHost.h | 42 + .../modules/plugin/nglsrc/nsPluginFactory.cpp | 156 +++ .../plugin/nglsrc/nsPluginHostImpl.cpp | 578 ++++++++ .../modules/plugin/nglsrc/nsPluginHostImpl.h | 102 ++ mozilla/modules/plugin/nglsrc/nsPluginsCID.h | 30 + .../modules/plugin/public/nsIEventHandler.h | 81 ++ .../public/nsIJRILiveConnectPlugInstPeer.h | 98 ++ .../public/nsILiveConnectPlugInstPeer.h | 86 ++ .../modules/plugin/public/nsINetworkManager.h | 118 ++ .../plugin/public/nsIWindowlessPlugInstPeer.h | 70 + mozilla/nsprpub/lib/ds/plvector.c | 318 +++++ mozilla/nsprpub/lib/ds/plvector.h | 100 ++ mozilla/xpcom/src/nsIMalloc.h | 94 ++ mozilla/xpcom/src/nsMalloc.cpp | 117 ++ mozilla/xpcom/src/nsMalloc.h | 101 ++ mozilla/xpcom/src/nsVector.h | 74 + 75 files changed, 19554 insertions(+) create mode 100644 mozilla/caps/include/nsCaps.h create mode 100644 mozilla/caps/include/nsCapsEnums.h create mode 100644 mozilla/caps/src/nsCaps.cpp create mode 100644 mozilla/cmd/winfe/npwplat.cpp create mode 100644 mozilla/cmd/winfe/npwplat.h create mode 100644 mozilla/include/np2.h create mode 100644 mozilla/include/npupp.h create mode 100644 mozilla/js/macbuild/LiveConnect.Prefix create mode 100644 mozilla/js/macbuild/LiveConnect.mcp create mode 100644 mozilla/js/macbuild/LiveConnectClasses.mcp create mode 100644 mozilla/js/macbuild/LiveConnectDebug.Prefix create mode 100644 mozilla/js/src/liveconnect/MANIFEST create mode 100644 mozilla/js/src/liveconnect/Makefile create mode 100644 mozilla/js/src/liveconnect/classes/Makefile create mode 100644 mozilla/js/src/liveconnect/classes/makefile.win create mode 100644 mozilla/js/src/liveconnect/classes/netscape/javascript/JSException.java create mode 100644 mozilla/js/src/liveconnect/classes/netscape/javascript/JSObject.java create mode 100644 mozilla/js/src/liveconnect/classes/netscape/javascript/JSProxy.java create mode 100644 mozilla/js/src/liveconnect/classes/netscape/javascript/JSRunnable.java create mode 100644 mozilla/js/src/liveconnect/classes/netscape/javascript/JSUtil.java create mode 100644 mozilla/js/src/liveconnect/jsj.c create mode 100644 mozilla/js/src/liveconnect/jsj1640.rc create mode 100644 mozilla/js/src/liveconnect/jsj_JSObject.c create mode 100644 mozilla/js/src/liveconnect/jsj_JavaArray.c create mode 100644 mozilla/js/src/liveconnect/jsj_JavaClass.c create mode 100644 mozilla/js/src/liveconnect/jsj_JavaObject.c create mode 100644 mozilla/js/src/liveconnect/jsj_JavaPackage.c create mode 100644 mozilla/js/src/liveconnect/jsj_array.c create mode 100644 mozilla/js/src/liveconnect/jsj_class.c create mode 100644 mozilla/js/src/liveconnect/jsj_convert.c create mode 100644 mozilla/js/src/liveconnect/jsj_field.c create mode 100644 mozilla/js/src/liveconnect/jsj_hash.c create mode 100644 mozilla/js/src/liveconnect/jsj_hash.h create mode 100644 mozilla/js/src/liveconnect/jsj_method.c create mode 100644 mozilla/js/src/liveconnect/jsj_nodl.c create mode 100644 mozilla/js/src/liveconnect/jsj_private.h create mode 100644 mozilla/js/src/liveconnect/jsj_utils.c create mode 100644 mozilla/js/src/liveconnect/jsjava.h create mode 100644 mozilla/js/src/liveconnect/makefile.win create mode 100644 mozilla/js/src/liveconnect/netscape_javascript_JSObject.h create mode 100644 mozilla/modules/plugin/base/public/npupp.h create mode 100644 mozilla/modules/plugin/base/public/nsIEventHandler.h create mode 100644 mozilla/modules/plugin/base/public/nsIJRILiveConnectPlugInstPeer.h create mode 100644 mozilla/modules/plugin/base/public/nsILiveConnectPlugInstPeer.h create mode 100644 mozilla/modules/plugin/base/public/nsINetworkManager.h create mode 100644 mozilla/modules/plugin/base/public/nsIWindowlessPlugInstPeer.h create mode 100644 mozilla/modules/plugin/base/src/Makefile create mode 100644 mozilla/modules/plugin/base/src/makefile.win create mode 100644 mozilla/modules/plugin/base/src/ns4xPlugin.cpp create mode 100644 mozilla/modules/plugin/base/src/ns4xPlugin.h create mode 100644 mozilla/modules/plugin/base/src/nsIPluginHost.h create mode 100644 mozilla/modules/plugin/base/src/nsPluginFactory.cpp create mode 100644 mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp create mode 100644 mozilla/modules/plugin/base/src/nsPluginHostImpl.h create mode 100644 mozilla/modules/plugin/base/src/nsPluginsCID.h create mode 100644 mozilla/modules/plugin/nglsrc/Makefile create mode 100644 mozilla/modules/plugin/nglsrc/makefile.win create mode 100644 mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp create mode 100644 mozilla/modules/plugin/nglsrc/ns4xPlugin.h create mode 100644 mozilla/modules/plugin/nglsrc/nsIPluginHost.h create mode 100644 mozilla/modules/plugin/nglsrc/nsPluginFactory.cpp create mode 100644 mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp create mode 100644 mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h create mode 100644 mozilla/modules/plugin/nglsrc/nsPluginsCID.h create mode 100644 mozilla/modules/plugin/public/nsIEventHandler.h create mode 100644 mozilla/modules/plugin/public/nsIJRILiveConnectPlugInstPeer.h create mode 100644 mozilla/modules/plugin/public/nsILiveConnectPlugInstPeer.h create mode 100644 mozilla/modules/plugin/public/nsINetworkManager.h create mode 100644 mozilla/modules/plugin/public/nsIWindowlessPlugInstPeer.h create mode 100644 mozilla/nsprpub/lib/ds/plvector.c create mode 100644 mozilla/nsprpub/lib/ds/plvector.h create mode 100644 mozilla/xpcom/src/nsIMalloc.h create mode 100644 mozilla/xpcom/src/nsMalloc.cpp create mode 100644 mozilla/xpcom/src/nsMalloc.h create mode 100644 mozilla/xpcom/src/nsVector.h diff --git a/mozilla/caps/include/nsCaps.h b/mozilla/caps/include/nsCaps.h new file mode 100644 index 00000000000..fe2f7a87944 --- /dev/null +++ b/mozilla/caps/include/nsCaps.h @@ -0,0 +1,148 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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. + */ + +#ifndef _NS_CAPS_H_ +#define _NS_CAPS_H_ + +#include "prtypes.h" +#include "nsCapsEnums.h" + +PR_BEGIN_EXTERN_C + +struct nsPrincipal; +struct nsTarget; +struct nsPrivilegeManager; +struct nsPrivilege; +struct nsPrivilegeTable; +struct NSJSJavaFrameWrapper; + +/* wrappers for nsPrivilegeManager object */ +PR_EXTERN(PRBool) +nsCapsRegisterPrincipal(struct nsPrincipal *principal); + +PR_EXTERN(PRBool) +nsCapsEnablePrivilege(struct nsTarget *target, PRInt32 callerDepth); + +PR_EXTERN(PRBool) +nsCapsIsPrivilegeEnabled(struct nsTarget *target, PRInt32 callerDepth); + +PR_EXTERN(PRBool) +nsCapsRevertPrivilege(struct nsTarget *target, PRInt32 callerDepth); + +PR_EXTERN(PRBool) +nsCapsDisablePrivilege(struct nsTarget *target, PRInt32 callerDepth); + +PR_EXTERN(void*) +nsCapsGetClassPrincipalsFromStack(PRInt32 callerDepth); + +PR_EXTERN(nsSetComparisonType) +nsCapsComparePrincipalArray(void* prin1Array, void* prin2Array); + +PR_EXTERN(void*) +nsCapsIntersectPrincipalArray(void* prin1Array, void* prin2Array); + +PR_EXTERN(PRBool) +nsCapsCanExtendTrust(void* from, void* to); + + +/* wrappers for nsPrincipal object */ +PR_EXTERN(struct nsPrincipal *) +nsCapsNewPrincipal(nsPrincipalType type, void * key, + PRUint32 key_len, void *zig); + +PR_EXTERN(const char *) +nsCapsPrincipalToString(struct nsPrincipal *principal); + +PR_EXTERN(PRBool) +nsCapsIsCodebaseExact(struct nsPrincipal *principal); + +PR_EXTERN(const char *) +nsCapsPrincipalGetVendor(struct nsPrincipal *principal); + +PR_EXTERN(void *) +nsCapsNewPrincipalArray(PRUint32 count); + +PR_EXTERN(void) +nsCapsFreePrincipalArray(void *prinArray); + +PR_EXTERN(void *) +nsCapsGetPrincipalArrayElement(void *prinArray, PRUint32 index); + +PR_EXTERN(void) +nsCapsSetPrincipalArrayElement(void *prinArray, PRUint32 index, void *element); + +PR_EXTERN(PRUint32) +nsCapsGetPrincipalArraySize(void *prinArray); + + +/* wrappers for nsTarget object */ +PR_EXTERN(struct nsTarget *) +nsCapsFindTarget(char *name); + + +/* wrappers for nsPrivilege object */ +PR_EXTERN(nsPermissionState) +nsCapsGetPermission(struct nsPrivilege *privilege); + + +/* wrappers for nsPrivilegeTable object */ +PR_EXTERN(struct nsPrivilege *) +nsCapsGetPrivilege(struct nsPrivilegeTable *annotation, struct nsTarget *target); + +/* Methods for stack walking */ + +extern struct NSJSJavaFrameWrapper * (*nsCapsNewNSJSJavaFrameWrapperCallback)(void); +PR_EXTERN(void) +setNewNSJSJavaFrameWrapperCallback(struct NSJSJavaFrameWrapper * (*fp)(void)); + +extern void (*nsCapsFreeNSJSJavaFrameWrapperCallback)(struct NSJSJavaFrameWrapper *); +PR_EXTERN(void) +setFreeNSJSJavaFrameWrapperCallback(void (*fp)(struct NSJSJavaFrameWrapper *)); + +extern void (*nsCapsGetStartFrameCallback)(struct NSJSJavaFrameWrapper *); +PR_EXTERN(void) +setGetStartFrameCallback(void (*fp)(struct NSJSJavaFrameWrapper *)); + +extern PRBool (*nsCapsIsEndOfFrameCallback)(struct NSJSJavaFrameWrapper *); +PR_EXTERN(void) +setIsEndOfFrameCallback(PRBool (*fp)(struct NSJSJavaFrameWrapper *)); + +extern PRBool (*nsCapsIsValidFrameCallback)(struct NSJSJavaFrameWrapper *); +PR_EXTERN(void) +setIsValidFrameCallback(PRBool (*fp)(struct NSJSJavaFrameWrapper *)); + +extern void * (*nsCapsGetNextFrameCallback)(struct NSJSJavaFrameWrapper *, int *); +PR_EXTERN(void) +setGetNextFrameCallback(void * (*fp)(struct NSJSJavaFrameWrapper *, int *)); + +extern void * (*nsCapsGetPrincipalArrayCallback)(struct NSJSJavaFrameWrapper *); +PR_EXTERN(void) +setOJIGetPrincipalArrayCallback(void * (*fp)(struct NSJSJavaFrameWrapper *)); + +extern void * (*nsCapsGetAnnotationCallback)(struct NSJSJavaFrameWrapper *); +PR_EXTERN(void) +setOJIGetAnnotationCallback(void * (*fp)(struct NSJSJavaFrameWrapper *)); + +extern void * (*nsCapsSetAnnotationCallback)(struct NSJSJavaFrameWrapper *, void *); +PR_EXTERN(void) +setOJISetAnnotationCallback(void * (*fp)(struct NSJSJavaFrameWrapper *, void *)); + + +PR_END_EXTERN_C + +#endif /* _NS_CAPS_H_ */ diff --git a/mozilla/caps/include/nsCapsEnums.h b/mozilla/caps/include/nsCapsEnums.h new file mode 100644 index 00000000000..5d127ac4a20 --- /dev/null +++ b/mozilla/caps/include/nsCapsEnums.h @@ -0,0 +1,59 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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. + */ + +#ifndef _NS_CAPS_ENUMS_H_ +#define _NS_CAPS_ENUMS_H_ + +typedef enum nsSetComparisonType { + nsSetComparisonType_ProperSubset=-1, + nsSetComparisonType_Equal=0, + nsSetComparisonType_NoSubset=1 +} nsSetComparisonType; + +/** + * number of possible permissions (allowed, forbidden, or blank) + */ +typedef enum nsPermissionState { + nsPermissionState_Forbidden = 0, + nsPermissionState_Allowed, + nsPermissionState_Blank, + nsPermissionState_NumberOfPermissions +} nsPermissionState; + +/** + * number of possible durations (scope, session, or forever) + */ +typedef enum nsDurationState { + nsDurationState_Scope=0, + nsDurationState_Session, + nsDurationState_Forever, + nsDurationState_NumberOfDurations +} nsDurationState; + + +/* The following should match what is in nsJVM plugin's java security code */ +typedef enum nsPrincipalType { + nsPrincipalType_Unknown=-1, + nsPrincipalType_CodebaseExact=10, + nsPrincipalType_CodebaseRegexp, + nsPrincipalType_Cert, + nsPrincipalType_CertFingerPrint, + nsPrincipalType_CertKey +} nsPrincipalType; + +#endif /* _NS_CAPS_ENUMS_H_ */ diff --git a/mozilla/caps/src/nsCaps.cpp b/mozilla/caps/src/nsCaps.cpp new file mode 100644 index 00000000000..5c0c2128184 --- /dev/null +++ b/mozilla/caps/src/nsCaps.cpp @@ -0,0 +1,278 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* + * 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. + */ + + +#include "prtypes.h" +#include "nspr.h" +#include "prmem.h" +#include "prmon.h" +#include "prlog.h" + +#include "nsCaps.h" +#include "nsPrivilegeManager.h" +#include "nsPrivilege.h" +#include "nsPrivilegeTable.h" +#include "nsPrincipal.h" +#include "nsTarget.h" + +PR_BEGIN_EXTERN_C + + +/* + * C API FOR JS + * + * All of the following methods are used by JS (the code located + * in lib/libmocha area). + */ + +/* wrappers for nsPrivilegeManager object */ +PR_IMPLEMENT(PRBool) +nsCapsRegisterPrincipal(struct nsPrincipal *principal) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + nsPrivManager->registerPrincipal(principal); + return PR_TRUE; +} + +PR_IMPLEMENT(PRBool) +nsCapsEnablePrivilege(struct nsTarget *target, PRInt32 callerDepth) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->enablePrivilege(target, callerDepth); +} + +PR_IMPLEMENT(PRBool) +nsCapsIsPrivilegeEnabled(struct nsTarget *target, PRInt32 callerDepth) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->isPrivilegeEnabled(target, callerDepth); +} + +PR_IMPLEMENT(PRBool) +nsCapsRevertPrivilege(struct nsTarget *target, PRInt32 callerDepth) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->revertPrivilege(target, callerDepth); +} + +PR_IMPLEMENT(PRBool) +nsCapsDisablePrivilege(struct nsTarget *target, PRInt32 callerDepth) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->disablePrivilege(target, callerDepth); +} + +PR_IMPLEMENT(void*) +nsCapsGetClassPrincipalsFromStack(PRInt32 callerDepth) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return (void *)nsPrivManager->getClassPrincipalsFromStack(callerDepth); +} + +PR_IMPLEMENT(nsSetComparisonType) +nsCapsComparePrincipalArray(void* prin1Array, void* prin2Array) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->comparePrincipalArray((nsPrincipalArray*)prin1Array, + (nsPrincipalArray*)prin2Array); +} + +PR_IMPLEMENT(void*) +nsCapsIntersectPrincipalArray(void* prin1Array, void* prin2Array) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->intersectPrincipalArray((nsPrincipalArray*)prin1Array, + (nsPrincipalArray*)prin2Array); +} + +PR_IMPLEMENT(PRBool) +nsCapsCanExtendTrust(void* from, void* to) +{ + nsPrivilegeManager *nsPrivManager = nsPrivilegeManager::getPrivilegeManager(); + return nsPrivManager->canExtendTrust((nsPrincipalArray*)from, + (nsPrincipalArray*)to); +} + +/* wrappers for nsPrincipal object */ +PR_IMPLEMENT(struct nsPrincipal *) +nsCapsNewPrincipal(nsPrincipalType type, void * key, + PRUint32 key_len, void *zig) +{ + return new nsPrincipal(type, key, key_len, zig); +} + +PR_IMPLEMENT(const char *) +nsCapsPrincipalToString(struct nsPrincipal *principal) +{ + return principal->toString(); +} + +PR_IMPLEMENT(PRBool) +nsCapsIsCodebaseExact(struct nsPrincipal *principal) +{ + return principal->isCodebaseExact(); +} + +PR_IMPLEMENT(const char *) +nsCapsPrincipalGetVendor(struct nsPrincipal *principal) +{ + return principal->getVendor(); +} + +PR_EXTERN(void *) +nsCapsNewPrincipalArray(PRUint32 count) +{ + nsPrincipalArray *prinArray = new nsPrincipalArray(); + prinArray->SetSize(count, 1); + return prinArray; +} + +PR_EXTERN(void) +nsCapsFreePrincipalArray(void *prinArrayArg) +{ + nsPrincipalArray *prinArray = (nsPrincipalArray *)prinArrayArg; + if (prinArray) { + prinArray->RemoveAll(); + delete prinArray; + } +} + +PR_EXTERN(void *) +nsCapsGetPrincipalArrayElement(void *prinArrayArg, PRUint32 index) +{ + nsPrincipalArray *prinArray = (nsPrincipalArray *)prinArrayArg; + if (prinArray == NULL) { + return NULL; + } + return prinArray->Get(index); +} + +PR_EXTERN(void) +nsCapsSetPrincipalArrayElement(void *prinArrayArg, PRUint32 index, void *element) +{ + nsPrincipalArray *prinArray = (nsPrincipalArray *)prinArrayArg; + if (prinArray == NULL) { + return; + } + prinArray->Set(index, element); +} + +PR_EXTERN(PRUint32) +nsCapsGetPrincipalArraySize(void *prinArrayArg) +{ + nsPrincipalArray *prinArray = (nsPrincipalArray *)prinArrayArg; + if (prinArray == NULL) { + return 0; + } + return prinArray->GetSize(); +} + +/* wrappers for nsTarget object */ +PR_IMPLEMENT(struct nsTarget *) +nsCapsFindTarget(char *name) +{ + return nsTarget::findTarget(name); +} + +/* wrappers for nsPrivilege object */ +PR_IMPLEMENT(nsPermissionState) +nsCapsGetPermission(struct nsPrivilege *privilege) +{ + return privilege->getPermission(); +} + +/* wrappers for nsPrivilegeTable object */ +PR_IMPLEMENT(struct nsPrivilege *) +nsCapsGetPrivilege(struct nsPrivilegeTable *annotation, struct nsTarget *target) +{ + return annotation->get(target); +} + + +/* Methods for stack walking */ +struct NSJSJavaFrameWrapper * (*nsCapsNewNSJSJavaFrameWrapperCallback)(void) = NULL; +PR_IMPLEMENT(void) +setNewNSJSJavaFrameWrapperCallback(struct NSJSJavaFrameWrapper * (*fp)(void)) +{ + nsCapsNewNSJSJavaFrameWrapperCallback = fp; +} + + +void (*nsCapsFreeNSJSJavaFrameWrapperCallback)(struct NSJSJavaFrameWrapper *); +PR_IMPLEMENT(void) +setFreeNSJSJavaFrameWrapperCallback(void (*fp)(struct NSJSJavaFrameWrapper *)) +{ + nsCapsFreeNSJSJavaFrameWrapperCallback = fp; +} + + +void (*nsCapsGetStartFrameCallback)(struct NSJSJavaFrameWrapper *); +PR_IMPLEMENT(void) +setGetStartFrameCallback(void (*fp)(struct NSJSJavaFrameWrapper *)) +{ + nsCapsGetStartFrameCallback = fp; +} + +PRBool (*nsCapsIsEndOfFrameCallback)(struct NSJSJavaFrameWrapper *); +PR_IMPLEMENT(void) +setIsEndOfFrameCallback(PRBool (*fp)(struct NSJSJavaFrameWrapper *)) +{ + nsCapsIsEndOfFrameCallback = fp; +} + + +PRBool (*nsCapsIsValidFrameCallback)(struct NSJSJavaFrameWrapper *); +PR_IMPLEMENT(void) +setIsValidFrameCallback(PRBool (*fp)(struct NSJSJavaFrameWrapper *)) +{ + nsCapsIsValidFrameCallback = fp; +} + + +void * (*nsCapsGetNextFrameCallback)(struct NSJSJavaFrameWrapper *, int *); +PR_IMPLEMENT(void) +setGetNextFrameCallback(void * (*fp)(struct NSJSJavaFrameWrapper *, int *)) +{ + nsCapsGetNextFrameCallback = fp; +} + + +void * (*nsCapsGetPrincipalArrayCallback)(struct NSJSJavaFrameWrapper *); +PR_IMPLEMENT(void) +setOJIGetPrincipalArrayCallback(void * (*fp)(struct NSJSJavaFrameWrapper *)) +{ + nsCapsGetPrincipalArrayCallback = fp; +} + + +void * (*nsCapsGetAnnotationCallback)(struct NSJSJavaFrameWrapper *); +PR_IMPLEMENT(void) +setOJIGetAnnotationCallback(void * (*fp)(struct NSJSJavaFrameWrapper *)) +{ + nsCapsGetAnnotationCallback = fp; +} + + +void * (*nsCapsSetAnnotationCallback)(struct NSJSJavaFrameWrapper *, void *); +PR_IMPLEMENT(void) +setOJISetAnnotationCallback(void * (*fp)(struct NSJSJavaFrameWrapper *, void *)) +{ + nsCapsSetAnnotationCallback = fp; +} + +PR_END_EXTERN_C diff --git a/mozilla/cmd/winfe/npwplat.cpp b/mozilla/cmd/winfe/npwplat.cpp new file mode 100644 index 00000000000..c2d809cdbba --- /dev/null +++ b/mozilla/cmd/winfe/npwplat.cpp @@ -0,0 +1,896 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +// npwplat.cpp +#include "stdafx.h" +#include +#include +#include +#include +#include +#include +#include +#ifdef WIN32 + #include + #include +#else + #include + #include +#endif +#include "npwplat.h" +#include "nppg.h" +#include "plgindll.h" +#include "np.h" +#include "helper.h" +#if defined(OJI) +#include "jvmmgr.h" +#elif defined(JAVA) +#include "java.h" +#endif +#include "edt.h" +#include "npglue.h" + +NPPMgtBlk* g_pRegisteredPluginList = NULL; + +// Tests that the directory specified by "dir" exists. +// Returns true if it does. + +static XP_Bool wfe_CheckDir(const char * dir) +{ + int ret; + XP_StatStruct statinfo; + + ret = _stat((char *) dir, &statinfo); + if(ret == -1) + return(FALSE); + + return(TRUE); + +} + +// Get the name of the directory where plugins live. "csDirname" is where the +// name of the dir is written to, and the trailing slash is removed. +// It always returns NPERR_NO_ERROR, since the Nav had to be started to get +// here, and the plugin dir is under where Nav started from. +NPError wfe_GetPluginsDirectory(CString& csDirname) +{ + char ca_default[_MAX_PATH]; + ::GetModuleFileName(AfxGetApp()->m_hInstance, ca_default, _MAX_PATH); + char *cp_lastslash = ::strrchr(ca_default, '\\'); + *cp_lastslash = NULL; + csDirname = ca_default; + csDirname += "\\plugins"; + return NPERR_NO_ERROR; +} + +// Fetches the "MIME type" string from the DLL VERSIONINFO structure. +// "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle +// to a plugin management data structure created during fe_RegisterPlugin(). +// The string is copied from the VERSIONINFO data into the +// "pNPMgtBlk->szMIMEType" member. +// An error is returned if out of memory. The MIME type string IS +// required, so an error is returned if the string does not exist. +NPError wfe_GetPluginMIMEType(VS_FIXEDFILEINFO* pVersionInfo, + NPPMgtBlk* pNPMgtBlk) +{ + // get the mime type of this plugin + static char szMimeTypeBlock[] = "StringFileInfo\\040904E4\\MIMEType"; + void* lpBuffer = NULL; + UINT uValueSize = 0; + if(::VerQueryValue(pVersionInfo, szMimeTypeBlock, + &lpBuffer, &uValueSize) == 0) // couldn't find MIME type + return NPERR_GENERIC_ERROR; + + pNPMgtBlk->szMIMEType = new char[uValueSize]; + if(pNPMgtBlk->szMIMEType == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + + strcpy(pNPMgtBlk->szMIMEType, (const char*)lpBuffer); + + return NPERR_NO_ERROR; +} + +// Fetches the "File Extents" string from the DLL VERSIONINFO structure. +// "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle +// to a plugin management data structure created during fe_RegisterPlugin(). +// The string is copied from the VERSIONINFO data into the +// "pNPMgtBlk->szFileExtents" member. +// An error is returned if out of memory, but the extents string is not +// required, so it is not an error if the string does not exist. +NPError wfe_GetPluginExtents(VS_FIXEDFILEINFO* pVersionInfo, + NPPMgtBlk* pNPMgtBlk) +{ // get the file extent list of this plugin + pNPMgtBlk->szFileExtents = NULL; + + static char szFileExtentsBlock[] = "StringFileInfo\\040904E4\\FileExtents"; + void* lpBuffer = NULL; + UINT uValueSize = 0; + + if(::VerQueryValue(pVersionInfo, szFileExtentsBlock, + &lpBuffer, &uValueSize) == 0) + // couldn't find file extent + return NPERR_NO_ERROR; + + if((*((char*)lpBuffer) == '\0') || (uValueSize == 0)) // no extents + return NPERR_NO_ERROR; + + // alloc char array + pNPMgtBlk->szFileExtents = new char[uValueSize]; + if(pNPMgtBlk->szFileExtents == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + strcpy(pNPMgtBlk->szFileExtents, (const char*)lpBuffer); + + return NPERR_NO_ERROR; +} + +// Fetches the "File Open Template" string from the DLL VERSIONINFO structure. +// "pVersionInfo" is ptr to the VERSIONINFO data, and "pNPMgtBlk" is a handle +// to a plugin management data structure created during fe_RegisterPlugin(). +// The string is copied from the VERSIONINFO data into the +// "pNPMgtBlk->szFileOpenName" member. +// An error is returned if out of memory, but the template string is not +// required, so it is not an error if the string does not exist. +NPError wfe_GetPluginFileOpenTemplate(VS_FIXEDFILEINFO* pVersionInfo, + NPPMgtBlk* pNPMgtBlk) +{ // get the file open template this plugin + pNPMgtBlk->szFileOpenName = NULL; + + static char szFileOpenBlock[] = "StringFileInfo\\040904E4\\FileOpenName"; + void* lpBuffer = NULL; + UINT uValueSize = 0; + + if(::VerQueryValue(pVersionInfo, szFileOpenBlock, + &lpBuffer, &uValueSize) == 0) + // couldn't find file extent + return NPERR_NO_ERROR; + + if((*((char*)lpBuffer) == '\0') || (uValueSize == 0)) // no extents + return NPERR_NO_ERROR; + + // alloc char array + pNPMgtBlk->szFileOpenName = new char[uValueSize]; + if(pNPMgtBlk->szFileOpenName == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + strcpy(pNPMgtBlk->szFileOpenName, (const char*)lpBuffer); + + return NPERR_NO_ERROR; +} + +// Fetches the plugin name and description from the resource info. +// Uses predefined version information strings +NPError wfe_GetPluginNameAndDescription(VS_FIXEDFILEINFO* pVersionInfo, + CString& strName, + CString& strDescription) +{ + static char szNameBlock[] = "StringFileInfo\\040904E4\\ProductName"; + static char szDescBlock[] = "StringFileInfo\\040904E4\\FileDescription"; + void* lpBuffer = NULL; + UINT uValueSize = 0; + + // Get the product name + if(::VerQueryValue(pVersionInfo, szNameBlock, &lpBuffer, &uValueSize) > 0) + strName = (LPSTR)lpBuffer; + + // Get the file description + if(::VerQueryValue(pVersionInfo, szDescBlock, &lpBuffer, &uValueSize) > 0) + strDescription = (LPSTR)lpBuffer; + + return NPERR_NO_ERROR; +} + +// Loads plugin properties from the DLL VERSIONINFO data structure. +// MIME type and version are required, but file extents and string +// file open templates are optional. "pPluginFilespec" is a string +// containing the file name of a DLL. "pNPMgtBlk" is a handle to a +// plugin management data structure created during fe_RegisterPlugin(). +// Returns an error if "pPluginFilespec" did not have the required MIME +// type and version fields. +// +// Also returns the plugin name and description +NPError wfe_GetPluginProperties(char* pPluginFilespec, + NPPMgtBlk* pNPMgtBlk, + CString& strPluginName, + CString& strPluginDescription) +{ + // prepare to read the version info tags + DWORD dwHandle = NULL; + DWORD dwVerInfoSize = ::GetFileVersionInfoSize(pPluginFilespec, &dwHandle); + if(dwVerInfoSize == NULL) + return NPERR_GENERIC_ERROR; + + VS_FIXEDFILEINFO* pVersionInfo = + (VS_FIXEDFILEINFO*)new char[dwVerInfoSize]; + if(pVersionInfo == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + + if(::GetFileVersionInfo(pPluginFilespec, dwHandle, + dwVerInfoSize, pVersionInfo) == 0) + { + delete [] (char*)pVersionInfo; + return NPERR_GENERIC_ERROR; + } + + NPError result; + // get the mime type of this plugin + if((result = wfe_GetPluginMIMEType(pVersionInfo, pNPMgtBlk)) + != NPERR_NO_ERROR) + { + delete [] (char*)pVersionInfo; + return result; + } + + // get the file extent list of this plugin + if((result = wfe_GetPluginExtents(pVersionInfo, pNPMgtBlk)) + != NPERR_NO_ERROR) + + { + delete [] pNPMgtBlk->szMIMEType; + delete [] (char*)pVersionInfo; + return result; + } + + // get the file type template string of this plugin + if((result = wfe_GetPluginFileOpenTemplate(pVersionInfo, pNPMgtBlk)) + != NPERR_NO_ERROR) + + { + delete [] pNPMgtBlk->szFileExtents; + delete [] pNPMgtBlk->szMIMEType; + delete [] (char*)pVersionInfo; + return result; + } + + // get the version of this plugin + void* lpBuffer = NULL; + UINT uValueSize = 0; + if(::VerQueryValue(pVersionInfo, "\\", &lpBuffer, &uValueSize) == 0) + { // couldn't find versioninfo + delete [] pNPMgtBlk->szFileExtents; + delete [] pNPMgtBlk->szMIMEType; + delete [] (char*)pVersionInfo; + return NPERR_GENERIC_ERROR; + } + pNPMgtBlk->versionMS = ((VS_FIXEDFILEINFO*)lpBuffer)->dwProductVersionMS; + pNPMgtBlk->versionLS = ((VS_FIXEDFILEINFO*)lpBuffer)->dwProductVersionLS; + + // get the plugin name and description. It's not fatal if these fail + wfe_GetPluginNameAndDescription(pVersionInfo, strPluginName, strPluginDescription); + + delete [] (char*)pVersionInfo; + + return NPERR_NO_ERROR; +} + +// Given a file open filter, e.g. Text Documents(*.txt), extracts the +// description and returns a copy of it +static LPSTR +ExtractDescription(LPCSTR lpszFileOpenFilter) +{ + ASSERT(lpszFileOpenFilter); + + LPSTR lpszDescription = XP_STRDUP(lpszFileOpenFilter); + + // Strip off an filter pattern at the end + LPSTR lpszPattern = strrchr(lpszDescription, '('); + + if (lpszPattern) + *lpszPattern = '\0'; + + return lpszDescription; +} + +// Registers one plugin. "pPluginFilespec" is a string containing the file +// name of a DLL. +// This function can be called more than once so a plugin which has copied +// into the plugins subdir AFTER the Nav has started can be registered +// and loaded. +// The DLL is a plugin candidate, and is qualified during +// this function, by checking the DLL VERSIONINFO data structure for a +// MIME type string. If this string is found successfully, the handle +// of the management block is used to register the plugin for its MIME type. +// The extents which are to be associated with this MIME type are also grokked +// from the VERSIONINFO data structure, once the candidate is accepted. +// This function also takes the opportunity to overrided any helper app, by +// setting a helper app data structure member to allow the plugin to handle +// the MIME type instead of the helper, (pApp->how_handle = HANDLE_VIA_PLUGIN). +// Returns an error if "pPluginFilespec" was not registered. +NPError fe_RegisterPlugin(char* pPluginFilespec) +{ + CString strName, strDescription; + + // initialize a new plugin list mgt block + NPPMgtBlk* pNPMgtBlk = new NPPMgtBlk; + if(pNPMgtBlk == NULL) // fatal, can't continue + return NPERR_OUT_OF_MEMORY_ERROR; + + pNPMgtBlk->pPluginFuncs = NULL; + pNPMgtBlk->pLibrary = NULL; + pNPMgtBlk->uRefCount = 0; + pNPMgtBlk->next = NULL; + + // determine the MIME type and version of this plugin + if(wfe_GetPluginProperties(pPluginFilespec, pNPMgtBlk, strName, strDescription) != NPERR_NO_ERROR) + { + delete pNPMgtBlk; + return NPERR_GENERIC_ERROR; + } + + // if a plugin is already registered for this MIME type, return. this + // allows downloading and registering new plugins without exiting the nav + for(NPPMgtBlk* pListBlk = g_pRegisteredPluginList; pListBlk != NULL; + pListBlk = pListBlk->next) { + BOOL bSameFile = + (strcmp(pListBlk->pPluginFilename, pPluginFilespec) == 0); + BOOL bSameMIMEtype = + (strstr(pNPMgtBlk->szMIMEType, pListBlk->szMIMEType) != NULL); + if(bSameFile && bSameMIMEtype) { + // the plugin DLL's filename and the MIME type it's registering for + // are the same, don't reregister + delete pNPMgtBlk; + return NPERR_GENERIC_ERROR; + } + } + + pNPMgtBlk->pPluginFilename = XP_STRDUP(pPluginFilespec); + if(pNPMgtBlk->pPluginFilename == NULL) // fatal, can't continue + { + delete pNPMgtBlk; + return NPERR_OUT_OF_MEMORY_ERROR; + } + + // Register the plugin file with the XP plugin code + NPL_RegisterPluginFile(strName, pNPMgtBlk->pPluginFilename, strDescription, + pNPMgtBlk); + + // Iterate through the filename extensions. These are a list which are + // delimited via the '|' character. The list of MIME Types,File Extents, + // and Open Names must all coordinate + char *pStartMIME, *pEndMIME, *pStartExt, *pEndExt, *pStartName, *pEndName; + + pStartMIME = pNPMgtBlk->szMIMEType; + pStartExt = pNPMgtBlk->szFileExtents; + pStartName = pNPMgtBlk->szFileOpenName; + + pEndMIME = strchr(pStartMIME ,'|'); + while (pEndMIME) { + pEndExt = strchr(pStartExt,'|'); + pEndName = strchr(pStartName,'|'); + if (pEndMIME) *pEndMIME = 0; + else return NPERR_GENERIC_ERROR; + if (pEndExt) *pEndExt = 0; + else return NPERR_GENERIC_ERROR; + if (pEndName) *pEndName = 0; + else return NPERR_GENERIC_ERROR; + + // Register the MIME type with the XP plugin code. We need to pass in + // a description. If there's a file open template specified, then use the + // description from there. Otherwise use the MIME type + LPSTR lpszDescription = NULL; + + if (pStartName) + lpszDescription = ExtractDescription(pStartName); + + NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ? + lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE); + + if (lpszDescription) + XP_FREE(lpszDescription); + + CHelperApp *pApp; + if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) { + // We've a match. + // Make sure the app is marked to handle the load + // via a plugin + pApp->how_handle = HANDLE_VIA_PLUGIN; + } + + if ((pEndMIME+1) && (pEndExt+1) && (pEndName+1)) { + pStartMIME = pEndMIME+1; + pStartExt = pEndExt+1; + pStartName = pEndName+1; + } + pEndMIME = strchr(pStartMIME ,'|'); + } + + // Register the MIME type with the XP plugin code. We need to pass in + // a description. If there's a file open template specified, then use the + // description from there. Otherwise use the MIME type + LPSTR lpszDescription = NULL; + + if (pStartName) + lpszDescription = ExtractDescription(pStartName); + + NPL_RegisterPluginType(pStartMIME, (LPCSTR)pStartExt, lpszDescription ? + lpszDescription : pStartMIME, (void *)pStartName, pNPMgtBlk, TRUE); + + if (lpszDescription) + XP_FREE(lpszDescription); + + CHelperApp *pApp; + if(theApp.m_HelperListByType.Lookup(pStartMIME, (CObject *&)pApp)) { + // We've a match. + // Make sure the app is marked to handle the load + // via a plugin + pApp->how_handle = HANDLE_VIA_PLUGIN; + } + + // insert the plugin mgt blk at the head of the list of registered plugins. + // this means they are listed in the reverse order from which they were + // created, which doesn't matter. + pNPMgtBlk->next = g_pRegisteredPluginList; + g_pRegisteredPluginList = pNPMgtBlk; + + return NPERR_NO_ERROR; +} + +// FE_RegisterPlugins is called from navigator main via npglue's NP_Init(). Finds all +// plugins and begins tracking them using a NPPMgtBlk. Uses the NPPMgtBlk +// block handle to register the plugin with the xp plugin glue. Looks +// in the directory under the netscape.exe dir, named "plugins" and all +// subdirectories in recursive way (see fe_RegisterPlugins). If the +// directory doesn't exist, no warning dialog is shown. +// There are no input or return vals. +void fe_RegisterPlugins(char* pszPluginDir) +{ + CString csPluginSpec; + csPluginSpec = pszPluginDir; + +#if defined(JAVA) + // add directory to the java path no matter what + LJ_AddToClassPath(pszPluginDir); +#endif + + if (thePluginManager == NULL) { + static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); + nsresult rslt = nsPluginManager::Create(NULL, kIPluginManagerIID, (void**)&thePluginManager); + // XXX Out of memory already? This function should return an error code! + PR_ASSERT(rslt == NS_OK); + // keep going anyway... + } + + csPluginSpec += "\\*.*"; + +#ifndef _WIN32 + _find_t fileinfo; + unsigned result = _dos_findfirst((LPSTR)((LPCSTR)csPluginSpec), _A_NORMAL | _A_SUBDIR, &fileinfo ); + + if (result == 0) { + + result = _dos_findnext(&fileinfo); // skip "." + result = _dos_findnext(&fileinfo); // skip ".." + + CString csFileSpec; + + while(result == 0) + { + csFileSpec = pszPluginDir; + csFileSpec += "\\"; + csFileSpec += fileinfo.name; + + // we got a subdir, call recursively this function to load plugin + if (fileinfo.attrib & _A_SUBDIR ) { + fe_RegisterPlugins((LPSTR)(LPCSTR)csFileSpec); + } + else { + size_t len = strlen(fileinfo.name); + + // it's a file, see if it can be a plugin file + if ( len > 6 && // at least "np.dll" + (fileinfo.name[0] == 'n' || fileinfo.name[0] == 'N') && + (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && + !_stricmp(fileinfo.name + len - 4, ".dll")) + fe_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); +#ifdef EDITOR + // If it's a cpXXX.zip file,register it as a composer plugin. + else if ( len > 6 && // at least cp.zip + (fileinfo.name[0] == 'c' || fileinfo.name[0] == 'C') && + (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && + (!_stricmp(fileinfo.name + len - 4, ".zip") + || !_stricmp(fileinfo.name + len - 4, ".jar")) + ) + EDT_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); +#endif /* EDITOR */ + } + result = _dos_findnext(&fileinfo); + } + } +#else /* _WIN32 */ + _finddata_t fileinfo; + unsigned handle = _findfirst((LPSTR)((LPCSTR)csPluginSpec), &fileinfo ); + unsigned result = 0; + + if (handle != -1) { + result = _findnext(handle, &fileinfo); // skip "." + result = _findnext(handle, &fileinfo); // skip ".." + + + CString csFileSpec; + + while((result != -1) && (handle != -1)) + { + csFileSpec = pszPluginDir; + csFileSpec += "\\"; + csFileSpec += fileinfo.name; + + // we got a subdir, call recursively this function to load plugin + if (fileinfo.attrib & _A_SUBDIR ) { + fe_RegisterPlugins((LPSTR)(LPCSTR)csFileSpec); + } + else { + size_t len = strlen(fileinfo.name); + + // it's a file, see if it can be a plugin file + if ( len > 6 && // at least "np.dll" + (fileinfo.name[0] == 'n' || fileinfo.name[0] == 'N') && + (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && + !_stricmp(fileinfo.name + len - 4, ".dll")) + fe_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); +#ifdef EDITOR + // If it's a cpXXX.zip file, add it to the java class path. + else if ( len > 6 && // at least cp.zip + (fileinfo.name[0] == 'c' || fileinfo.name[0] == 'C') && + (fileinfo.name[1] == 'p' || fileinfo.name[1] == 'P') && + (!_stricmp(fileinfo.name + len - 4, ".zip") + || !_stricmp(fileinfo.name + len - 4, ".jar")) + ) + EDT_RegisterPlugin((LPSTR)((LPCSTR)csFileSpec)); +#endif + } + result = _findnext(handle, &fileinfo); + } + _findclose(handle); + } +#endif /* _WIN32 */ +} + +// called from the navigator main, dispatch to the previous function +void FE_RegisterPlugins() +{ + CString csPluginDir; + // get the main plugins directory and start the process + wfe_GetPluginsDirectory(csPluginDir); + fe_RegisterPlugins((LPSTR)(LPCSTR)csPluginDir); +} + +// saves the current path in the variable passed. ppPathSave is the +// address of the ptr which stores the path string. returns out of memory +// error if allocation for the string returned by _getcwd() fails. returns +// generic error if the "one deep" stack is already full. +NPError wfe_PushPath(LPSTR *ppPathSave) +{ + // only allow "one deep" stack + if(*ppPathSave != NULL) + return NPERR_GENERIC_ERROR; + + // save the CWD + *ppPathSave = _getcwd(NULL, 0); + if(*ppPathSave == NULL) + return NPERR_OUT_OF_MEMORY_ERROR; + + return NPERR_NO_ERROR; +} + +// calculate the drive letter value for _chdrive(). ascii in, int out +int wfe_MapAsciiToDriveNum(char cAsciiNum) +{ + int iDriveLetter = cAsciiNum; + if(islower(cAsciiNum)) + iDriveLetter = _toupper(cAsciiNum); + // plus one because for _chdrive(), A = 1, B = 2, etc + return iDriveLetter - 'A' + 1; +} + +// restores the path from the variable passed. pDirSave stores the pointer +// to the path string. returns an error if a path has never been pushed. +NPError wfe_PopPath(LPSTR pPathSave) +{ + // only allows "one deep" stack + if(pPathSave == NULL) + return NPERR_GENERIC_ERROR; + + // restore the drive + int chdriveErr = _chdrive(wfe_MapAsciiToDriveNum(pPathSave[0])); + + // restore the CWD + int chdirErr = _chdir(pPathSave); + free(pPathSave); + + return NPERR_NO_ERROR; +} + +// Load a plugin dll. "pluginType" is a handle to a plugin management data +// structure created during FE_RegisterPlugins(). "pNavigatorFuncs" is +// a table of entry points into Navigator, which are the services provided +// by Navigator to plugins, such as requestread() and GetUrl(). These entry +// points are stored and called by the plugin when services are needed. +// The return val is a table of functions which are entry points to the +// newly loaded plugin, such as NewStream() and Write(). +NPPluginFuncs* FE_LoadPlugin(void* pluginType, NPNetscapeFuncs* pNavigatorFuncs, np_handle* handle) +{ + if(pluginType == NULL) + return NULL; + + NPPMgtBlk* pNPMgtBlock = (NPPMgtBlk*)pluginType; + + CString csPluginDir; +#ifdef OJI + char* szExplicitDLL = strrchr(pNPMgtBlock->pPluginFilename, '\\'); + if( szExplicitDLL ) { + csPluginDir = pNPMgtBlock->pPluginFilename; // MFC copies the string + csPluginDir.SetAt( szExplicitDLL - pNPMgtBlock->pPluginFilename, '\0'); + } else { + wfe_GetPluginsDirectory(csPluginDir); + } +#else + wfe_GetPluginsDirectory(csPluginDir); +#endif /* OJI */ + + LPSTR pPathSave = NULL; // storage for one dir spec + + wfe_PushPath(&pPathSave); // save the current drive and dir + + // change the default dir so that implib'd plugins won't fail + if(_chdir(csPluginDir) != 0) { + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + + // must change the drive as well as the dir path + if(isalpha(csPluginDir[0]) && csPluginDir[1] == ':') { + if(_chdrive(wfe_MapAsciiToDriveNum(csPluginDir[0])) != 0) { + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + } + + pNPMgtBlock->pLibrary = PR_LoadLibrary(pNPMgtBlock->pPluginFilename); + + // the cross platform code should take care of the 16/32 bit issues + if(pNPMgtBlock->pLibrary == NULL) + return NULL; + + nsFactoryProc nsGetFactory = (nsFactoryProc) + PR_FindSymbol(pNPMgtBlock->pLibrary, "NSGetFactory"); + if (nsGetFactory != NULL) { + static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID); + nsIPlugin* plugin = NULL; + nsresult res = nsGetFactory(kIPluginIID, (nsIFactory**)&plugin); + PR_ASSERT(thePluginManager != NULL); + if (res == NS_OK && plugin != NULL + && plugin->Initialize((nsIPluginManager*)thePluginManager) == NS_OK) { + + handle->userPlugin = plugin; + pNPMgtBlock->pPluginFuncs = (NPPluginFuncs*)-1; // something to say it's loaded, but != 0 +#ifdef LATER // XXX coming soon... + // add the plugin directory if successful + JVM_AddToClassPathRecursively(csPluginDir); +#endif + } + else { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + } + else { + + NP_GETENTRYPOINTS getentrypoints = +#ifndef NSPR20 + (NP_GETENTRYPOINTS)PR_FindSymbol("NP_GetEntryPoints", pNPMgtBlock->pLibrary); +#else + (NP_GETENTRYPOINTS)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_GetEntryPoints"); +#endif + if(getentrypoints == NULL) + { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + + if(pNPMgtBlock->pPluginFuncs == NULL) + { + pNPMgtBlock->pPluginFuncs = new NPPluginFuncs; + pNPMgtBlock->pPluginFuncs->size = sizeof NPPluginFuncs; + pNPMgtBlock->pPluginFuncs->javaClass = NULL; + if(pNPMgtBlock->pPluginFuncs == NULL) // fatal, can't continue + { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + } + + if(getentrypoints(pNPMgtBlock->pPluginFuncs) != NPERR_NO_ERROR) + { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + delete pNPMgtBlock->pPluginFuncs; + pNPMgtBlock->pPluginFuncs = NULL; + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + + // if the plugin's major ver level is lower than the Navigator's, + // then they are incompatible, and should return an error + if(HIBYTE(pNPMgtBlock->pPluginFuncs->version) < NP_VERSION_MAJOR) + { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + delete pNPMgtBlock->pPluginFuncs; + pNPMgtBlock->pPluginFuncs = NULL; + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + + NP_PLUGININIT npinit = NULL; + + // if this DLL is not already loaded, call its initialization entry point + if(pNPMgtBlock->uRefCount == 0) { + // the NP_Initialize entry point was misnamed as NP_PluginInit, early + // in plugin project development. Its correct name is documented + // now, and new developers expect it to work. However, I don't want + // to break the plugins already in the field, so I'll accept either + // name + npinit = +#ifndef NSPR20 + (NP_PLUGININIT)PR_FindSymbol("NP_Initialize", pNPMgtBlock->pLibrary); +#else + (NP_PLUGININIT)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_Initialize"); +#endif + if(!npinit) { + npinit = +#ifndef NSPR20 + (NP_PLUGININIT)PR_FindSymbol("NP_PluginInit", pNPMgtBlock->pLibrary); +#else + (NP_PLUGININIT)PR_FindSymbol(pNPMgtBlock->pLibrary, "NP_PluginInit"); +#endif + } + } + + if(npinit == NULL) { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + delete pNPMgtBlock->pPluginFuncs; + pNPMgtBlock->pPluginFuncs = NULL; + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + + if (npinit(pNavigatorFuncs) != NPERR_NO_ERROR) { + PR_UnloadLibrary(pNPMgtBlock->pLibrary); + delete pNPMgtBlock->pPluginFuncs; + pNPMgtBlock->pPluginFuncs = NULL; + wfe_PopPath(pPathSave); // restore the path + return NULL; + } + } + + pNPMgtBlock->uRefCount++; // all is well, remember it was loaded + + // can't pop the path until plugins have been completely loaded/init'd + wfe_PopPath(pPathSave); // restore the path + return pNPMgtBlock->pPluginFuncs; +} + +// Unloads a plugin DLL. "pluginType" is a handle to a plugin management data +// structure created during FE_RegisterPlugins(). There is no return val. +void FE_UnloadPlugin(void* pluginType, struct _np_handle* handle) +{ + NPPMgtBlk* pNPMgtBlk = (NPPMgtBlk*)pluginType; + if (pNPMgtBlk == NULL) + return; + + // XXX Note that we're double refcounting here. If we were rewriting this + // from scratch, we could eliminate this pNPMgtBlk and its refcount and just + // rely on the one in the userPlugin. + + pNPMgtBlk->uRefCount--; // another one bites the dust + + // if this DLL is the last one, call its shutdown entry point + if (pNPMgtBlk->uRefCount == 0) { + if (handle->userPlugin) { + nsrefcnt cnt = handle->userPlugin->Release(); + PR_ASSERT(cnt == 0); + +#if 0 // XXX later... + // remove the plugin directory if successful + JVM_RemoveFromClassPathRecursively(csPluginDir); +#endif + } + else { + // the NP_Shutdown entry point was misnamed as NP_PluginShutdown, early + // in plugin project development. Its correct name is documented + // now, and new developers expect it to work. However, I don't want + // to break the plugins already in the field, so I'll accept either + // name + NP_PLUGINSHUTDOWN npshutdown = +#ifndef NSPR20 + (NP_PLUGINSHUTDOWN)PR_FindSymbol("NP_Shutdown", pNPMgtBlk->pLibrary); +#else + (NP_PLUGINSHUTDOWN)PR_FindSymbol(pNPMgtBlk->pLibrary, "NP_Shutdown"); +#endif + if (!npshutdown) { + npshutdown = +#ifndef NSPR20 + (NP_PLUGINSHUTDOWN)PR_FindSymbol("NP_PluginShutdown", pNPMgtBlk->pLibrary); +#else + (NP_PLUGINSHUTDOWN)PR_FindSymbol(pNPMgtBlk->pLibrary, "NP_PluginShutdown"); +#endif + } + + if (npshutdown != NULL) { + NPError result = npshutdown(); + } + } + } + + PR_UnloadLibrary(pNPMgtBlk->pLibrary); + pNPMgtBlk->pLibrary = NULL; + + if (handle->userPlugin) { + PR_ASSERT(pNPMgtBlk->pPluginFuncs == (NPPluginFuncs*)-1); // set in FE_LoadPlugin + handle->userPlugin = NULL; + } + else { + delete pNPMgtBlk->pPluginFuncs; + } + pNPMgtBlk->pPluginFuncs = NULL; +} + +// Removes a plugin DLL from memory, and frees its NPPMgtBlk management block. +// "pluginType" is a handle to the plugin management data structure created +// during FE_RegisterPlugins(). There is no return val. +void FE_UnregisterPlugin(void* pluginType) +{ + NPPMgtBlk* pNPMgtBlk = (NPPMgtBlk*)pluginType; + if(pNPMgtBlk == NULL) + return; + + if(pNPMgtBlk->pLibrary != NULL) + PR_UnloadLibrary(pNPMgtBlk->pLibrary); + + delete [] (char*)*pNPMgtBlk->pPluginFilename; + delete [] pNPMgtBlk->pPluginFilename; + delete [] pNPMgtBlk->szMIMEType; + delete pNPMgtBlk->pPluginFuncs; + delete pNPMgtBlk; +} + +// Provides the entry point used by xp plugin code, (NPGLUE.C), to control +// scroll bars. The inputs are obvious, and there is no return val. +void FE_ShowScrollBars(MWContext* pContext, XP_Bool show) +{ + if(ABSTRACTCX(pContext)->IsWindowContext()) { + CPaneCX *pPaneCX = PANECX(pContext); + + pPaneCX->ShowScrollBars(SB_BOTH, show); + } +} + +#ifdef XP_WIN32 +void* +WFE_BeginSetModuleState() +{ + return AfxSetModuleState(AfxGetAppModuleState()); +} + +void +WFE_EndSetModuleState(void* pPrevState) +{ + AfxSetModuleState((AFX_MODULE_STATE*)pPrevState); +} +#endif + + diff --git a/mozilla/cmd/winfe/npwplat.h b/mozilla/cmd/winfe/npwplat.h new file mode 100644 index 00000000000..fd168f26a1a --- /dev/null +++ b/mozilla/cmd/winfe/npwplat.h @@ -0,0 +1,61 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#ifndef _NPWPLAT_H_ +#define _NPWPLAT_H_ +#include "ntypes.h" +#include "npupp.h" +#include "prlink.h" + +typedef unsigned long NPWFEPluginType; +typedef struct _NPPMgtBlk NPPMgtBlk; + +typedef struct _NPPMgtBlk { // a management block based on plugin type + NPPMgtBlk* next; +#if !defined(XP_OS2_) + LPSTR pPluginFilename; +#else + PSZ pPluginFilename; +#endif +#if !defined(XP_OS2) + PRLibrary* pLibrary; // returned by PR_LoadLibrary +#else + HMODULE pLibrary; // returned by PR_LoadLibrary +#endif + uint16 uRefCount; // so we know when to call NP_Initialize + // and NP_Shutdown + NPPluginFuncs* pPluginFuncs; // returned by plugin during load + char* szMIMEType; + char* szFileExtents; // a ptr to a string of delimited extents, + // or NULL if empty list. + char* szFileOpenName; // a ptr to a string to put in FileOpen + // common dialog type description area + DWORD versionMS; // each word is a digit, eg, 3.1 + DWORD versionLS; // each word is a digit, eg, 2.66 +} NPPMgtBlk; + +#ifdef __cplusplus +extern "C" { +#endif + + +#ifdef __cplusplus +} +#endif + +#endif // _NPWPLAT_H_ diff --git a/mozilla/include/np2.h b/mozilla/include/np2.h new file mode 100644 index 00000000000..959202533ce --- /dev/null +++ b/mozilla/include/np2.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + + +/* + * np2.h $Revision: 3.1 $ + * Prototypes for functions exported by OJI based libplugin and called by the FEs or other XP libs. + */ + +#ifndef _NP2_H +#define _NP2_H +#include "jni.h" +#include "prthread.h" + +struct np_instance; +struct nsIPlugin; +struct nsIPluginInstance; +struct nsIPluginInstancePeer; +struct nsISupports; +PR_EXTERN(struct nsIPluginInstance*) NPL_GetOJIPluginInstance(NPEmbeddedApp *embed); +PR_EXTERN(const char *) NPL_GetText(struct nsIPluginInstance *); +PR_EXTERN(jobject) NPL_GetJavaObject(struct nsIPluginInstance *); +PR_EXTERN(void ) NPL_Release(struct nsISupports *); +PR_EXTERN(XP_Bool) NPL_IsJVMAndMochaPrefsEnabled(void); +PR_EXTERN(void)NPL_JSJInit(void); +PR_EXTERN(JNIEnv *)NPL_EnsureJNIExecEnv(PRThread* thread); + +#endif /* _NP2_H */ + diff --git a/mozilla/include/npupp.h b/mozilla/include/npupp.h new file mode 100644 index 00000000000..3260c811e4e --- /dev/null +++ b/mozilla/include/npupp.h @@ -0,0 +1,1213 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + + +/* + * npupp.h $Revision: 3.1 $ + * function call mecahnics needed by platform specific glue code. + */ + + +#ifndef _NPUPP_H_ +#define _NPUPP_H_ + +#if defined(__OS2__) +#pragma pack(1) +#endif + +#ifndef GENERATINGCFM +#define GENERATINGCFM 0 +#endif + +#ifndef _NPAPI_H_ +#include "npapi.h" +#endif + +#include "jri.h" + +/****************************************************************************************** + plug-in function table macros + for each function in and out of the plugin API we define + typedef NPP_FooUPP + #define NewNPP_FooProc + #define CallNPP_FooProc + for mac, define the UPP magic for PPC/68K calling + *******************************************************************************************/ + + +/* NPP_Initialize */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_InitializeUPP; + +enum { + uppNPP_InitializeProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPP_InitializeProc(FUNC) \ + (NPP_InitializeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_InitializeProcInfo, GetCurrentArchitecture()) +#define CallNPP_InitializeProc(FUNC) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_InitializeProcInfo) + +#else + +typedef void (* NP_LOADDS NPP_InitializeUPP)(void); +#define NewNPP_InitializeProc(FUNC) \ + ((NPP_InitializeUPP) (FUNC)) +#define CallNPP_InitializeProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPP_Shutdown */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_ShutdownUPP; + +enum { + uppNPP_ShutdownProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPP_ShutdownProc(FUNC) \ + (NPP_ShutdownUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_ShutdownProcInfo, GetCurrentArchitecture()) +#define CallNPP_ShutdownProc(FUNC) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_ShutdownProcInfo) + +#else + +typedef void (* NP_LOADDS NPP_ShutdownUPP)(void); +#define NewNPP_ShutdownProc(FUNC) \ + ((NPP_ShutdownUPP) (FUNC)) +#define CallNPP_ShutdownProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPP_New */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_NewUPP; + +enum { + uppNPP_NewProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(uint16))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int16))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char **))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(char **))) + | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(NPSavedData *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; + +#define NewNPP_NewProc(FUNC) \ + (NPP_NewUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewProcInfo, GetCurrentArchitecture()) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewProcInfo, \ + (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#else + +typedef NPError (* NP_LOADDS NPP_NewUPP)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); +#define NewNPP_NewProc(FUNC) \ + ((NPP_NewUPP) (FUNC)) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) + +#endif + + +/* NPP_Destroy */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_DestroyUPP; +enum { + uppNPP_DestroyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPSavedData **))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_DestroyProc(FUNC) \ + (NPP_DestroyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyProcInfo, GetCurrentArchitecture()) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyProcInfo, (ARG1), (ARG2)) +#else + +typedef NPError (* NP_LOADDS NPP_DestroyUPP)(NPP instance, NPSavedData** save); +#define NewNPP_DestroyProc(FUNC) \ + ((NPP_DestroyUPP) (FUNC)) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPP_SetWindow */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_SetWindowUPP; +enum { + uppNPP_SetWindowProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPWindow *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_SetWindowProc(FUNC) \ + (NPP_SetWindowUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_SetWindowProcInfo, GetCurrentArchitecture()) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_SetWindowProcInfo, (ARG1), (ARG2)) + +#else + +typedef NPError (* NP_LOADDS NPP_SetWindowUPP)(NPP instance, NPWindow* window); +#define NewNPP_SetWindowProc(FUNC) \ + ((NPP_SetWindowUPP) (FUNC)) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPP_NewStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_NewStreamUPP; +enum { + uppNPP_NewStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPBool))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(uint16 *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_NewStreamProc(FUNC) \ + (NPP_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewStreamProcInfo, GetCurrentArchitecture()) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewStreamProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#else + +typedef NPError (* NP_LOADDS NPP_NewStreamUPP)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); +#define NewNPP_NewStreamProc(FUNC) \ + ((NPP_NewStreamUPP) (FUNC)) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#endif + + +/* NPP_DestroyStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_DestroyStreamUPP; +enum { + uppNPP_DestroyStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_DestroyStreamProc(FUNC) \ + (NPP_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, GetCurrentArchitecture()) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, (NPParg), (NPStreamPtr), (NPReasonArg)) + +#else + +typedef NPError (* NP_LOADDS NPP_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPP_DestroyStreamProc(FUNC) \ + ((NPP_DestroyStreamUPP) (FUNC)) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (*(FUNC))((NPParg), (NPStreamPtr), (NPReasonArg)) + +#endif + + +/* NPP_WriteReady */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_WriteReadyUPP; +enum { + uppNPP_WriteReadyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPP_WriteReadyProc(FUNC) \ + (NPP_WriteReadyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, GetCurrentArchitecture()) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, (NPParg), (NPStreamPtr)) + +#else + +typedef int32 (* NP_LOADDS NPP_WriteReadyUPP)(NPP instance, NPStream* stream); +#define NewNPP_WriteReadyProc(FUNC) \ + ((NPP_WriteReadyUPP) (FUNC)) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr)) + +#endif + + +/* NPP_Write */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_WriteUPP; +enum { + uppNPP_WriteProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPP_WriteProc(FUNC) \ + (NPP_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteProcInfo, GetCurrentArchitecture()) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteProcInfo, (NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +#else + +typedef int32 (* NP_LOADDS NPP_WriteUPP)(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); +#define NewNPP_WriteProc(FUNC) \ + ((NPP_WriteUPP) (FUNC)) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +#endif + + +/* NPP_StreamAsFile */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_StreamAsFileUPP; +enum { + uppNPP_StreamAsFileProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; +#define NewNPP_StreamAsFileProc(FUNC) \ + (NPP_StreamAsFileUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, GetCurrentArchitecture()) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, (ARG1), (ARG2), (ARG3)) + +#else + +typedef void (* NP_LOADDS NPP_StreamAsFileUPP)(NPP instance, NPStream* stream, const char* fname); +#define NewNPP_StreamAsFileProc(FUNC) \ + ((NPP_StreamAsFileUPP) (FUNC)) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPP_Print */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_PrintUPP; +enum { + uppNPP_PrintProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPrint *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; +#define NewNPP_PrintProc(FUNC) \ + (NPP_PrintUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_PrintProcInfo, GetCurrentArchitecture()) +#define CallNPP_PrintProc(FUNC, NPParg, voidPtr) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_PrintProcInfo, (NPParg), (voidPtr)) + +#else + +typedef void (* NP_LOADDS NPP_PrintUPP)(NPP instance, NPPrint* platformPrint); +#define NewNPP_PrintProc(FUNC) \ + ((NPP_PrintUPP) (FUNC)) +#define CallNPP_PrintProc(FUNC, NPParg, NPPrintArg) \ + (*(FUNC))((NPParg), (NPPrintArg)) + +#endif + + +/* NPP_HandleEvent */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_HandleEventUPP; +enum { + uppNPP_HandleEventProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(int16))) +}; +#define NewNPP_HandleEventProc(FUNC) \ + (NPP_HandleEventUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_HandleEventProcInfo, GetCurrentArchitecture()) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (int16)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_HandleEventProcInfo, (NPParg), (voidPtr)) + +#else + +typedef int16 (* NP_LOADDS NPP_HandleEventUPP)(NPP instance, void* event); +#define NewNPP_HandleEventProc(FUNC) \ + ((NPP_HandleEventUPP) (FUNC)) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (*(FUNC))((NPParg), (voidPtr)) + +#endif + + +/* NPP_URLNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_URLNotifyUPP; +enum { + uppNPP_URLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(SIZE_CODE(0))) +}; +#define NewNPP_URLNotifyProc(FUNC) \ + (NPP_URLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) + +#else + +typedef void (* NP_LOADDS NPP_URLNotifyUPP)(NPP instance, const char* url, NPReason reason, void* notifyData); +#define NewNPP_URLNotifyProc(FUNC) \ + ((NPP_URLNotifyUPP) (FUNC)) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +#endif + + +/* NPP_GetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_GetValueUPP; +enum { + uppNPP_GetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_GetValueProc(FUNC) \ + (NPP_GetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_GetValueProcInfo, GetCurrentArchitecture()) +#define CallNPP_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_GetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPP_GetValueUPP)(NPP instance, NPPVariable variable, void *ret_alue); +#define NewNPP_GetValueProc(FUNC) \ + ((NPP_GetValueUPP) (FUNC)) +#define CallNPP_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPP_SetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_SetValueUPP; +enum { + uppNPP_SetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPNVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_SetValueProc(FUNC) \ + (NPP_SetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_SetValueProcInfo, GetCurrentArchitecture()) +#define CallNPP_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_SetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPP_SetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPP_SetValueProc(FUNC) \ + ((NPP_SetValueUPP) (FUNC)) +#define CallNPP_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + + + +/* + * Netscape entry points + */ + + +/* NPN_GetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetValueUPP; +enum { + uppNPN_GetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPNVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetValueProc(FUNC) \ + (NPN_GetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetValueProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPN_GetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPN_GetValueProc(FUNC) \ + ((NPN_GetValueUPP) (FUNC)) +#define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_SetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_SetValueUPP; +enum { + uppNPN_SetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_SetValueProc(FUNC) \ + (NPN_SetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_SetValueProcInfo, GetCurrentArchitecture()) +#define CallNPN_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_SetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPN_SetValueUPP)(NPP instance, NPPVariable variable, void *ret_alue); +#define NewNPN_SetValueProc(FUNC) \ + ((NPN_SetValueUPP) (FUNC)) +#define CallNPN_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_GetUrlNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetURLNotifyUPP; +enum { + uppNPN_GetURLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetURLNotifyProc(FUNC) \ + (NPN_GetURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) +#else + +typedef NPError (* NP_LOADDS NPN_GetURLNotifyUPP)(NPP instance, const char* url, const char* window, void* notifyData); +#define NewNPN_GetURLNotifyProc(FUNC) \ + ((NPN_GetURLNotifyUPP) (FUNC)) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) +#endif + + +/* NPN_PostUrlNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_PostURLNotifyUPP; +enum { + uppNPN_PostURLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) + | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_PostURLNotifyProc(FUNC) \ + (NPN_PostURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#else + +typedef NPError (* NP_LOADDS NPN_PostURLNotifyUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData); +#define NewNPN_PostURLNotifyProc(FUNC) \ + ((NPN_PostURLNotifyUPP) (FUNC)) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#endif + + +/* NPN_GetUrl */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetURLUPP; +enum { + uppNPN_GetURLProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetURLProc(FUNC) \ + (NPN_GetURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPN_GetURLUPP)(NPP instance, const char* url, const char* window); +#define NewNPN_GetURLProc(FUNC) \ + ((NPN_GetURLUPP) (FUNC)) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_PostUrl */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_PostURLUPP; +enum { + uppNPN_PostURLProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_PostURLProc(FUNC) \ + (NPN_PostURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLProcInfo, GetCurrentArchitecture()) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) +#else + +typedef NPError (* NP_LOADDS NPN_PostURLUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file); +#define NewNPN_PostURLProc(FUNC) \ + ((NPN_PostURLUPP) (FUNC)) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) +#endif + + +/* NPN_RequestRead */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_RequestReadUPP; +enum { + uppNPN_RequestReadProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPByteRange *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_RequestReadProc(FUNC) \ + (NPN_RequestReadUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_RequestReadProcInfo, GetCurrentArchitecture()) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_RequestReadProcInfo, (stream), (range)) + +#else + +typedef NPError (* NP_LOADDS NPN_RequestReadUPP)(NPStream* stream, NPByteRange* rangeList); +#define NewNPN_RequestReadProc(FUNC) \ + ((NPN_RequestReadUPP) (FUNC)) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (*(FUNC))((stream), (range)) + +#endif + + +/* NPN_NewStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_NewStreamUPP; +enum { + uppNPN_NewStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPStream **))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_NewStreamProc(FUNC) \ + (NPN_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_NewStreamProcInfo, GetCurrentArchitecture()) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_NewStreamProcInfo, (npp), (type), (window), (stream)) + +#else + +typedef NPError (* NP_LOADDS NPN_NewStreamUPP)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); +#define NewNPN_NewStreamProc(FUNC) \ + ((NPN_NewStreamUPP) (FUNC)) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (*(FUNC))((npp), (type), (window), (stream)) + +#endif + + +/* NPN_Write */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_WriteUPP; +enum { + uppNPN_WriteProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPN_WriteProc(FUNC) \ + (NPN_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_WriteProcInfo, GetCurrentArchitecture()) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_WriteProcInfo, (npp), (stream), (len), (buffer)) + +#else + +typedef int32 (* NP_LOADDS NPN_WriteUPP)(NPP instance, NPStream* stream, int32 len, void* buffer); +#define NewNPN_WriteProc(FUNC) \ + ((NPN_WriteUPP) (FUNC)) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (*(FUNC))((npp), (stream), (len), (buffer)) + +#endif + + +/* NPN_DestroyStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_DestroyStreamUPP; +enum { + uppNPN_DestroyStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP ))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_DestroyStreamProc(FUNC) \ + (NPN_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, GetCurrentArchitecture()) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, (npp), (stream), (reason)) + +#else + +typedef NPError (* NP_LOADDS NPN_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPN_DestroyStreamProc(FUNC) \ + ((NPN_DestroyStreamUPP) (FUNC)) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (*(FUNC))((npp), (stream), (reason)) + +#endif + + +/* NPN_Status */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_StatusUPP; +enum { + uppNPN_StatusProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *))) +}; + +#define NewNPN_StatusProc(FUNC) \ + (NPN_StatusUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_StatusProcInfo, GetCurrentArchitecture()) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_StatusProcInfo, (npp), (msg)) + +#else + +typedef void (* NP_LOADDS NPN_StatusUPP)(NPP instance, const char* message); +#define NewNPN_StatusProc(FUNC) \ + ((NPN_StatusUPP) (FUNC)) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (*(FUNC))((npp), (msg)) + +#endif + + +/* NPN_UserAgent */ +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_UserAgentUPP; +enum { + uppNPN_UserAgentProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(const char *))) +}; + +#define NewNPN_UserAgentProc(FUNC) \ + (NPN_UserAgentUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_UserAgentProcInfo, GetCurrentArchitecture()) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (const char*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_UserAgentProcInfo, (ARG1)) + +#else + +typedef const char* (* NP_LOADDS NPN_UserAgentUPP)(NPP instance); +#define NewNPN_UserAgentProc(FUNC) \ + ((NPN_UserAgentUPP) (FUNC)) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_MemAlloc */ +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemAllocUPP; +enum { + uppNPN_MemAllocProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) + | RESULT_SIZE(SIZE_CODE(sizeof(void *))) +}; + +#define NewNPN_MemAllocProc(FUNC) \ + (NPN_MemAllocUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemAllocProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (void*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemAllocProcInfo, (ARG1)) + +#else + +typedef void* (* NP_LOADDS NPN_MemAllocUPP)(uint32 size); +#define NewNPN_MemAllocProc(FUNC) \ + ((NPN_MemAllocUPP) (FUNC)) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN__MemFree */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemFreeUPP; +enum { + uppNPN_MemFreeProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *))) +}; + +#define NewNPN_MemFreeProc(FUNC) \ + (NPN_MemFreeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFreeProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFreeProcInfo, (ARG1)) + +#else + +typedef void (* NP_LOADDS NPN_MemFreeUPP)(void* ptr); +#define NewNPN_MemFreeProc(FUNC) \ + ((NPN_MemFreeUPP) (FUNC)) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_MemFlush */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemFlushUPP; +enum { + uppNPN_MemFlushProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) + | RESULT_SIZE(SIZE_CODE(sizeof(uint32))) +}; + +#define NewNPN_MemFlushProc(FUNC) \ + (NPN_MemFlushUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFlushProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (uint32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFlushProcInfo, (ARG1)) + +#else + +typedef uint32 (* NP_LOADDS NPN_MemFlushUPP)(uint32 size); +#define NewNPN_MemFlushProc(FUNC) \ + ((NPN_MemFlushUPP) (FUNC)) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + + +/* NPN_ReloadPlugins */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_ReloadPluginsUPP; +enum { + uppNPN_ReloadPluginsProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_ReloadPluginsProc(FUNC) \ + (NPN_ReloadPluginsUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, GetCurrentArchitecture()) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, (ARG1)) + +#else + +typedef void (* NP_LOADDS NPN_ReloadPluginsUPP)(NPBool reloadPages); +#define NewNPN_ReloadPluginsProc(FUNC) \ + ((NPN_ReloadPluginsUPP) (FUNC)) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_GetJavaEnv */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetJavaEnvUPP; +enum { + uppNPN_GetJavaEnvProcInfo = kThinkCStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(JRIEnv*))) +}; + +#define NewNPN_GetJavaEnvProc(FUNC) \ + (NPN_GetJavaEnvUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (JRIEnv*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo) + +#else +typedef JRIEnv* (* NP_LOADDS NPN_GetJavaEnvUPP)(void); +#define NewNPN_GetJavaEnvProc(FUNC) \ + ((NPN_GetJavaEnvUPP) (FUNC)) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPN_GetJavaPeer */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetJavaPeerUPP; +enum { + uppNPN_GetJavaPeerProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(jref))) +}; + +#define NewNPN_GetJavaPeerProc(FUNC) \ + (NPN_GetJavaPeerUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, (ARG1)) + +#else + +typedef jref (* NP_LOADDS NPN_GetJavaPeerUPP)(NPP instance); +#define NewNPN_GetJavaPeerProc(FUNC) \ + ((NPN_GetJavaPeerUPP) (FUNC)) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_InvalidateRect */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_InvalidateRectUPP; +enum { + uppNPN_InvalidateRectProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPRect *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_InvalidateRectProc(FUNC) \ + (NPN_InvalidateRectUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_InvalidateRectProcInfo, GetCurrentArchitecture()) +#define CallNPN_InvalidateRectProc(FUNC, ARG1, ARG2) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_InvalidateRectProcInfo, (ARG1), (ARG2)) + +#else + +typedef void (* NP_LOADDS NPN_InvalidateRectUPP)(NPP instance, NPRect *rect); +#define NewNPN_InvalidateRectProc(FUNC) \ + ((NPN_InvalidateRectUPP) (FUNC)) +#define CallNPN_InvalidateRectProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPN_InvalidateRegion */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_InvalidateRegionUPP; +enum { + uppNPN_InvalidateRegionProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPRegion))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_InvalidateRegionProc(FUNC) \ + (NPN_InvalidateRegionUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_InvalidateRegionProcInfo, GetCurrentArchitecture()) +#define CallNPN_InvalidateRegionProc(FUNC, ARG1, ARG2) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_InvalidateRegionProcInfo, (ARG1), (ARG2)) + +#else + +typedef void (* NP_LOADDS NPN_InvalidateRegionUPP)(NPP instance, NPRegion region); +#define NewNPN_InvalidateRegionProc(FUNC) \ + ((NPN_InvalidateRegionUPP) (FUNC)) +#define CallNPN_InvalidateRegionProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + +/* NPN_ForceRedraw */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_ForceRedrawUPP; +enum { + uppNPN_ForceRedrawProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(0))) +}; + +#define NewNPN_ForceRedrawProc(FUNC) \ + (NPN_ForceRedrawUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_ForceRedrawProcInfo, GetCurrentArchitecture()) +#define CallNPN_ForceRedrawProc(FUNC, ARG1) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_ForceRedrawProcInfo, (ARG1)) + +#else + +typedef void (* NP_LOADDS NPN_ForceRedrawUPP)(NPP instance); +#define NewNPN_ForceRedrawProc(FUNC) \ + ((NPN_ForceRedrawUPP) (FUNC)) +#define CallNPN_ForceRedrawProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/****************************************************************************************** + * The actual plugin function table definitions + *******************************************************************************************/ + +#ifdef XP_MAC +#if PRAGMA_ALIGN_SUPPORTED +#pragma options align=mac68k +#endif +#endif + +typedef struct _NPPluginFuncs { + uint16 size; + uint16 version; + NPP_NewUPP newp; + NPP_DestroyUPP destroy; + NPP_SetWindowUPP setwindow; + NPP_NewStreamUPP newstream; + NPP_DestroyStreamUPP destroystream; + NPP_StreamAsFileUPP asfile; + NPP_WriteReadyUPP writeready; + NPP_WriteUPP write; + NPP_PrintUPP print; + NPP_HandleEventUPP event; + NPP_URLNotifyUPP urlnotify; + JRIGlobalRef javaClass; + NPP_GetValueUPP getvalue; + NPP_SetValueUPP setvalue; +} NPPluginFuncs; + +typedef struct _NPNetscapeFuncs { + uint16 size; + uint16 version; + NPN_GetURLUPP geturl; + NPN_PostURLUPP posturl; + NPN_RequestReadUPP requestread; + NPN_NewStreamUPP newstream; + NPN_WriteUPP write; + NPN_DestroyStreamUPP destroystream; + NPN_StatusUPP status; + NPN_UserAgentUPP uagent; + NPN_MemAllocUPP memalloc; + NPN_MemFreeUPP memfree; + NPN_MemFlushUPP memflush; + NPN_ReloadPluginsUPP reloadplugins; + NPN_GetJavaEnvUPP getJavaEnv; + NPN_GetJavaPeerUPP getJavaPeer; + NPN_GetURLNotifyUPP geturlnotify; + NPN_PostURLNotifyUPP posturlnotify; + NPN_GetValueUPP getvalue; + NPN_SetValueUPP setvalue; + NPN_InvalidateRectUPP invalidaterect; + NPN_InvalidateRegionUPP invalidateregion; + NPN_ForceRedrawUPP forceredraw; +} NPNetscapeFuncs; + +#ifdef XP_MAC +#if PRAGMA_ALIGN_SUPPORTED +#pragma options align=reset +#endif +#endif + + +#ifdef XP_MAC +/****************************************************************************************** + * Mac platform-specific plugin glue stuff + *******************************************************************************************/ + +/* + * Main entry point of the plugin. + * This routine will be called when the plugin is loaded. The function + * tables are passed in and the plugin fills in the NPPluginFuncs table + * and NPPShutdownUPP for Netscape's use. + */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_MainEntryUPP; +enum { + uppNPP_MainEntryProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPNetscapeFuncs*))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPluginFuncs*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPP_ShutdownUPP*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_MainEntryProc(FUNC) \ + (NPP_MainEntryUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_MainEntryProcInfo, GetCurrentArchitecture()) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + CallUniversalProc((UniversalProcPtr)(FUNC), (ProcInfoType)uppNPP_MainEntryProcInfo, (netscapeFunc), (pluginFunc), (shutdownUPP)) + +#else + +typedef NPError (* NP_LOADDS NPP_MainEntryUPP)(NPNetscapeFuncs*, NPPluginFuncs*, NPP_ShutdownUPP*); +#define NewNPP_MainEntryProc(FUNC) \ + ((NPP_MainEntryUPP) (FUNC)) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + (*(FUNC))((netscapeFunc), (pluginFunc), (shutdownUPP)) + +#endif +#endif /* MAC */ + +#if defined(_WINDOWS) +#define OSCALL WINAPI +#else +#if defined(__OS2__) +#define OSCALL _System +#else +#define OSCALL +#endif +#endif + +#if defined( _WINDOWS ) || defined (__OS2__) + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ +#if defined(__OS2__) + +typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */ + char *pMimeTypes; + char *pFileExtents; + char *pFileOpenTemplate; + char *pProductName; + char *pProductDescription; + unsigned long dwProductVersionMS; + unsigned long dwProductVersionLS; +} NPPluginData; + +NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData); + +#endif + +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs); + +NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs); + +NPError OSCALL NP_Shutdown(); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINDOWS || __OS2__ */ + +#if defined(__OS2__) +#pragma pack() +#endif + +#ifdef XP_UNIX + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ + +char* NP_GetMIMEDescription(void); +NPError NP_Initialize(NPNetscapeFuncs*, NPPluginFuncs*); +NPError NP_Shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* XP_UNIX */ + +#endif /* _NPUPP_H_ */ diff --git a/mozilla/js/macbuild/LiveConnect.Prefix b/mozilla/js/macbuild/LiveConnect.Prefix new file mode 100644 index 00000000000..5c4fd8b20a1 --- /dev/null +++ b/mozilla/js/macbuild/LiveConnect.Prefix @@ -0,0 +1,31 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +// +// JavaScript.Prefix +// +// Global prefix file for the JavaScriptPPC project. +// +// + +#include "MacPrefix.h" +#include "JavaScriptConfig.h" + +#define JSFILE 1 +#define LIVECONNECT 1 +// #define JS_THREADSAFE 1 diff --git a/mozilla/js/macbuild/LiveConnect.mcp b/mozilla/js/macbuild/LiveConnect.mcp new file mode 100644 index 0000000000000000000000000000000000000000..169b6d2e6b633317c75d945d70444bd531171528 GIT binary patch literal 61196 zcmeHw4RjpUmFBDNmMlxMEo0gILmM31U|F_h8yoQ_TR*mB$!gT{4
    T5YN2R(HF* zWo$5@U@!(8LI_D9$!6HioLOd)GYf2XLUwjGEW>PaW^?v1vuq||GINqiW|$B*$C=C_ zlbp$TzwfXNMxZ1t6H-COtFy8YgL_x)78`iZ7e2_b}E2xFxX{}2%3?It1S zd>^tw!)JgfXip8t_Czw7cq$VNWm03YXwFQU9kj|2XU>>KJ#)q&aQ7-j$UgU+5VxJ- zpD@JS>b_Jm5=}9|2?AoJs5M^mOca8ybRrhq8jGci(r3x8A&iO>5K~)y zSNY=pFNnK@(ex8x+%Q+yzu8RZVc(}^mw=*GOZX7BXxS24v8~d42(()BQP4S>KMY!< z`IDgL@B9wrDX?_>z zBF&G3HfsJj=wi*Iy@@57{}SlMnrD7ket_|Ru(?#S!uSE`Wt#sv=;ey{(Fa#(p1N0R zz6JCu&2Ix`UID&4unCd_KZeax$qL^w&}%gRH0ZUO|2@!Untuh9^#SnxIX25BD}3Jp zU7`8Ypy-VWe%9M{k`;dD{d&!>1zn~2Hc<511pkMzSuI)NzYnxo^Us2=(LD3O;{pC} zW3x`O!cU*D%zyxWzh1H;z~eS(J_Nc^^9Mn1(EOvIn>5ezZr1#tf!?V3?}0M@0D}ZqfX=K(}iCUC?&LS2LD7G*4f4 zYM!z#&3^=xbquIJg3Wfxit0~+c5D7+&>qb*&Ua}3UqE{mKZo(id;{jtA3G&0=IjRT z*F1+#`VlaP_HUQ0m_z#mntu~CtohTRgNm=22f9o1tY_K<)bKa=NLJLuK=*2X5|r@@ zsQCgmcS=^&{0S&y1yJ)AHY`7&hGn@+vSKdV!rhu@{p`~`)Awus0nmu%KLxRqIvptRP%>G4U7~1#%~H5Vfb1D8(@Yb?t^FeQ&YA9%o7c3 zM5YQ4GC`%PQSMq67nl`(A19eoFR!d6EYtHS>$mmL_?&19hX3N#?W0Cu>x!#y7RJu6 zL8A^xxVSfdIM$v@CNXdChz(7QG>0;=192UsN~drur?>nq{Bjz|I%9o5k3Q>q^b^#6 zLWEE8Hok^Cv>Z!@^s)fz?M*`SN?jSqj%fh=)w3f z&pY;nL+xS?Gj(pTZ(lYS5!__XGLPr>`vsApW^Mk)uUfOK+Nz%LK>AZuCz8X7m|axN&w+r|JQr9CtO8a88B^?; z<^kE-*~$s*O|Aj5ZV(}I=C=ZL8IV2whk)!QmjfGs3xO8_7XjId76X?6F9u!$ycBpD zkj>$8;8Nffz$<}Q0apR91_psiAbUdg>WtJlFagW}S$fv-D3HE72xJe=o|`>38^KW^ zduH~??1|X}v*%@xI|=+K@FC!F;KM-H3VY5+fGxoFzzx8Sz}3LDz#D*@fSZ9$z;(bi zz#Di~@&&G2j7UFYsC52=FBE3E(N< z$AFIl9|t}O{5bF_;3t4j13w9T2KXu9r-6?FKLflL=myLOzVaxmV-WFywESTzyPocSPh&5tO3pi z)&c8*W59X9`M?Fh9^idI`g{_|x}pDA53D1`8tbLF4()Zi#lQrR zumqR{UJSehXttSg@Ed`w$LoNsZ^k(5crWlUkag$--T+(IB*MaE0FQC7T6B#0CobqfZKr0!0o`xfmZ;p z1YQNa8W;pJMwbGw0j>si14n?%fHwly0B0Nwlo!|pTn%gnt^uwEt^>9J*8?{IHv%^S z$AAZc31AYK0?LsSlrhIRVT=$UlD_wY27skvi*d*JV%;;Q%y?joF(%AdUAWzHjLYfg#fPJO(idRL0{k^)W~C(bs0o}N0JVr@lc+WoOsXnD4x?hr&Tx0I zH$Ie!Wa1bt`yx@>o=j|CwW>K3YHx;;7|TY|@#ZLLCKEZTxLj&nGDEnaDw$|9cO)md z;Ycnf8MQYwVjdnFk1LG>6G@pi5|t#L%*8Tk$tF_KgOVAKR!S3;NDw7Ms^I~fxkw~SI!R@g`TJ-G+wy!~*$Q0~^A}D4;?hVB570}<3 z9T$7s`@6dAHbR{RyM5u_V7rwyxo4|p?iXgB5}na}EF2lmsQN_I^oN-R#7^>HEF;<{ zvWSY{j@Z$AQkmhb*bKLI)-kusy;~4ymbObKWCzYYW5Pl*VONj1)V1F83jo%9`?IG(Z zy>A`HeDfmzwpfzx3wFe_oH~vV@h5DBA`3T4k+~268QiUZ75;}Iowu>93evHC`KB_q zFUnadA_b}YqN(Iz6>r=-5RWB>bxKdHR}oiLePmk?6t5hzfHY z5-v~}kL5;Frg;SJVK&TBnT?5DJfX9MpMlVJ!qhw-O^akKhY(B0_KhK3HK4rt0(H@v zz{wWM#gnb(u}B8(W*jR4FrQ8fmLiNWh^Nphx!)H_BEuO5zWq0OTvt4kWr&Q7$C5eG z8fi}9gv!<|ZrHp-^o91A5iWPlhM{+KHFM7v{M-%8P5?0$i%#TH8PU_RL!T`)-y25@ z8|bm`_Jli+L}Q31WSbrkmTUDMV&TY9GievRY4T_=$q1rI?W3*I1EOckfX+6;ixRWZ zC_a)LnSfVR3Qi-_D7Z{9LykKgsi?IUWp`b6G=WaURT2!3#u5p;!?lD#sC&Dfa8Gke z>)j1H>G#OxnWd?N@R`-l5xB`)i#Z&y+TU`GG)#tve~prcSa7!MTEh>`tkn=hM=kuK35z;`;$p}1eFz1O6 zgXesYa0Z1k@j-In zdH%6fvck9xl=D-7!E-439bkm9;qd^2KKzhmg+ae9*F4WXR%rea(3P5h2J|}3e-89| z&Hn-DD$Rctv`O=?gED^r<1ew{`3b=IHa7ZP!}uHUYbk~Nr`Yg(31Ivhn-<9mAM19# z=IIB<4Zug+8zn1zZJ;baz_$aNO_CKpp7U(hd;*l`IRM{LY4=(!T&7%hg5>{P(cgB3a>MU2oO=FG1TC@1G0Wp?Stmr{?MV zF3r;i+ceMo@|+Ifr*5}og?|8)^$PIs!-i!B_+!}gN>=y}f%a*hb-GjYPk^#r0sJg) zNV3Aun7>`~tVjL^!2eBb7&id_Ti6UrR`^-QU7CLnbhqLI0nj~~XAHC50s@y}bBAO_ z;5tyAO9KKd--jhD0<_IK0|Z!>yCf?DEX&=R|0pQS3&8^2k5Zo-vH%r00Mu5%>l`Zz)wI&H2*8mQN>r)g2pw^vW#hdCFnuTv%VN- zfGXDExMW2Y%azppe$bTW)1X8^)e&r1PC(To*kmLtsy+dl)%@>(<}}YTPH6rW(8HQ% zechw^?}E}Upo-->Dp^s*KIdM=SF?`p(>&YPG0iUpW!wO&+14JAtf*%Dcu@0ALp49w5fdl1qU9`x83KI%b_ed9wO^w@76_n^l<^~Ej&pvS)WzPz603W&|i zW0LV&-VeGS$E}n3@;b(W*K%;&JmJCKOzYi^-}O>&A80+C4HZ-X$^@vhb>vDi%eH8Q zzv1<9ecwRgFjwBobL48jJWAfFunM);1Y8Yl2Cf0F1+D|O0M`RI05<|R0mpy`feBy= zmM3wn6~uku|7DUc6x_6XtSE|pTAE4mv4C?xcR>n9?-^J zp4xDu=`Q0bW3ErnotdOdwg}v2-DYpp*DqT2HI19Jw{F(gK5o&++^Vlz+@_3+HZ9+x z=~i8V?fUo*ZNF2ecWL|E^zUug_Pe!ykECQBMC(p`6!9lcV38s1! zNyem=J~NCpqt(7EX%&INaCM(m7c`ENW-7vp2V6ZM7wK9%hvRbbfOjjkcBQaPq2+4n zO6};2_U3w)5*DwHDQUqPnGzMOg((r%FRaC?yrf{sDlgWnae0BYh9EOtw3?>Wiq_P$ zu&a*?Cu*l)aZQOhu2~BbO4Jt_iARI&k#tZFc=?5~;^cx%=8r1OYVjJLGE%&fr=_;_ zyu74@i)?Fqc|ET1+4l4UKb9oF+NVSXYko>Jh;{I;3<9DvIjmO(Rl=Tla)3*XdWBF4 zk8Hl7s6r_za0&&5?kHYDRi+9TQq9nl(%yL1j89ot=E9PU11Z_vr;Du?bJcB(YBg0^ zms-8n@|1O?eJx69%B2(As;$nQwK}WzSt@H~jcdbPxV6oYv1*oSEp95s=>?6ZII-AE z#p#9qDo!nEe8q{yMJ!IYH`7vS1<_baK?gvoBr_C>(~6pN>11owdrGou;>F@FtJaEB z3c7*f#KK@HnW{suWSUbEY1STZ#RpG~-C~X6j>I9|(M{|#%$o(K99w+zKq&=>iZyR8 zD0PUFHwtb(C_b>DV=7K8+xECr>)QCFf@ABGscy|rDmb@4ne5mAWvW{XlnPEw&`NY{ zgO)~#y0X$rRfX@<7+k^!dDr#3_>FWnMll4Dbpsm^UNpIo9b<`W%@>ed|P;qL8G zs<<^syMnXBoSLLM+O17m8cr2ms#RJCIl9HMUCKip8>UPx*D}@38g5NfYdEz{o$S&$ zwT5Hs)ag#mQzyH$Pp#q5Ky9f`E!3tmwdQPzC2B~gIyce+g;GIhDokmnI-z7c)oD%* zRVO>PRD1f=rfN@hF0xBw)dpN!tJZO8u7w&du5)Ox=J75q)~4cE@g>@uj92>h$$Em^FRGgdD6s1z}VN-Hy zDK-_?aJA_hnoQjr{p#X%(k1wB^D*##DHf&~d%w zQAw?z&%*$D~^jJDlWQyJUd-d zDK$KRu#hW#lD_oX+(l>3eDj)O&oHq9v)ltUD1Sh%2G?TUdOlV)jn>v|CfYj7{W6P- z&xP$X0FY`K53|@8m7=TLR&+ensQ#gK7;Aj3(L@|i%R{0coYJ5DE zYz<8eC2;pfcQTro7>;Et9f{qw=Ou5(1NsLY5AvD)@I;!g8ED0|)a|jza4b`)>+`aD zr=4jt9@==VLiP^@@t}GJyb+|*^r!9G^YQ>&Jorn*L#1;#FKhMeGi}BL#*2dUi|j;l z^%(BLs`LwI@7we7NLxJ2<8upY@s&%OdPVenEL0`W6%U-H2THEapQWwy@-SYLJ})y~ z$@GkRph_5v%QS|*{yXpF&5bkqyIzbLwkOqmcxwuu598k~hsG7{{T-bvf-5?<3~m7l zb+-?$m`y&(ug=e=Qdi14lOCwdfoIa26de!22ScY@Ta%B#DPVT#44!#h+ z%29b^O{s9i*-b-nH^(<9+28|mcB9sDZ259wc?NX(Kz~2qacF^m+rTdM<{8|4R+q@X z$Qc^*y1IKianveJn>1amX|twlG+nFdI!#+NU9af|O*d+~Nz;ri50}*M4C@tYzL_57 zvn5_S*L=VCFj4|M9CuD;G)-xm*7T6=$jhtbqY~y(DAXZpfhIMTM`J&2JL=*F^;MaI z4Egl|W11e+G_ikv`dF-`@t824dGP_^J2osrFI>gfG+x&DBB=Vgitp(3DZWF+OzLlH zb*gt_HbNvi56ZXfTv|DQr#C8~-??OS1cIpo=jZ|XZLr_cXTfyVE7#}Fu?{PT&l(Rb z*6%s2JTziexf})f{6s{4%fpgan5iD%>n3})?A}6LV7ot5zJ?%t%|P%vW9^GC7;6u- z?dlH>Y#$ZNf?;m+U)j8@y5Z^`F%sM*-%h{%?Ms5olA@;S_`FH=YrZ$Cj$i(ix?6qw zb$ChsbydgbzERb^=ar@Np>c)(UUB*8aAE}f--QPUuEjG_Kke(>xeM>9zKRd74Qb z&>-ITCKmXTU5Nu<(4eX_#vw{~Pwc&9Pm`#*W+3=}1d;%p_TzV9H6CO*v(kgo?d zn#GMl5%{lE!WSaCApaTpz$m|0;s5WFkMsKwfh);lirfS~qU5w+#rMFAz?kH3lKer* zt9SDw4|tE{Davu|?ciV4Jl-EY=XK2=$Iav4)I4gf{#%;=eVhR{X#O?u&yWwqX>DX<0T?3ijni$U_yEOre2`*$;2S?W9eDY@ zSFispL|5R;9d$B(ePT$(uQ(y&+9#e?aV7p}AU@m+-PcqciT|zQNW7)uNBo0|H}Ov@ z-o(GDcrt2LJQ>#@CM*cV<@ZwdQ4koD-!S>2Oq`V8CxOq9R~cu9eD^BiY-LawsDH>; z^IIIoN%CS+w1IzF^YB&OA4*<*I|8qP#tS(0VAB`w?$l`&GD|%$n#-kI*R0`WF&p0}$DLbq91rJB?ZpS@C-tD9v^TLE_*l{)F*$zJT>6#%AiPF!u zQMJ?|jgQT4@xq%)13N6RxrS0JJmoDJlPSmwz<;pc_l`A^x7KxtiOnK>jVIlE; zqe4N6J?ZDH7@GifDnluhwvOn$6PWh4466Om;Q$D0xkg9et&`p#OPfN5P+8I3J zKdpmGDASIYd+ltW#B>bAEIzVW;wK73UhMFIW;m(fz-jJ;psz+;zBbU|p7Zm4#6{6c zyJeaquCtvP8gcu#_5@4kG%qdsJZnC|#+}zAx1*QM8Gu`VX&Wia+Hr333fZ4t+EeBQCyJu)Zb8cbhtl zxbtMoaqpn==L9gsoRtD)$77FK){bijHI4k>E9EX=^>pR(lNPCH;=MOS;P&r`#Vu=b zt?pp;_psmiPVmf`z+JkspZ>_q57M!}A?Vxt!*|;t?CWdaZl;|Jl~=1+6)yR)dC=+$ z^Z9wRhQBZ8&NE;~&Uwq&DK+OU&X1=aQ-9LT&3{&p>Ea)&hqAnbt5sHgDgP)tQL$=9 z>?GW;TA*BsNH&}Q2u@)MC$X#Ylb)gcpa-9ca-mri=5+ddvRvnQ7TjR^$Mu>{`Mgjc@)eHpV{IV(m_yUa4Zudb|;_KjjyxK4W`H@!%X26bYfw;ae!J%Bm*Y``6OWGODjVFZ1k#h0z z*ZG_Imh;1Rxi9T-4UIbv`SIdsX(uCG&!Tu;l@;bzU%Veg@V1$Atao{KHUsq~uZPZn z9lF;H=X3G1v;+6J%`v^y*UnTjMq7?x^!0_xoNYTEYbCUSQ&&vox7;jw0W;@=wnjPA zR|E@6TeMTq){D~2UEQ|K-ICPHn#KEhZNFqDi-bB(J5o`HQ~Ub%{!<5w4w|x?w=yNk z63EfS+AGa?vEwB&%GJbv{JgADa}+3@9pO1L=;`-)MLD;yfIbRZ{>}t7g(TIiu1mEz>n95 z;YWAiVPXOwDVB`hSUb>bf~?nr-fHOedC=oC=Q};<@k!Nw4|;2%7xJLD4tlqH&})I- zfCs(x&KNh z%gbF1<&4pec^8A*y;=o#F*rN}EA2$xe-W$M>TXF#@96wQJwCrt){c9Iyyu4eg0GG&mcP$mBR@QSV4u&i{UY~d?XQ#~Fzh&ZZ(#ns==TaQ9W7#Ql z4_>*uPLLht=gPC{bj1|d4@u=&^(k(dhJYUYExjGacISLyhAYpi7y84#w;wydm66-A zwx&69m$l<@O z%CqWb_)MXELfGMXK&4xGR=vn)#n0eZo>g~$CxDtmRi0Hh!>BlZD7T(cJcoAzNIR8h z)lD~BbU(P6x?(!hYk5{COE3j%c_q>*(rwEjRf)ZTF#l-J^vqcr?9HjA!w!n*!jsY358q&U<-mFduKi z_fgJ!nryHbe2uo_|Hpg+KWk&!vCA8t&D*idjg>f{S$-p>@1dQEO8%vG z@IFc*e;#bDl3&UD5dD;b`~fzNN`8#rpuw&1gn1{h2`KsR^ZuiSltTVEHd_7?J$4bL zkUxpd<4S-1JKz^liZ95#hu`f`^0(iDKz+YQH2o|1WlBEp4)FM14PkW<8=cQLe**q$ zAYk?N*gUQDm;DHQ5C~ZP->}i;eekp3mr{z~{Wdni@m!YmqJ2X-kF7c~o|9jcu*nzk z%LSqFT!Qz~+2nP%V!r|U^nqReN7!G9`lZ|kU5JywhVk48e%D@KJ%|He(|9@yeY-sK zE0~=O^=5OTFYq5=Xqhrr&+=;fcKtLpU%@X9UV=_f$ro7kxOTKIGaczqSN zsSf;nrT^UP;CW9Wp!xTZ?P?`|o8N5G?dcx0BjYV4|MABmpP;r7M-l)27AaqN9N(uB zhox8?`*Y|wDEZAf$c`v^6Z56?8-6es{81&pAF)>zQu_1$0 z@}_?ex>?EB{T%%LTK-+oc}iYg1O5ReU&DB~OvyLn)un>%2T->Y8zuL@`Bm^IDaGx* zpGDJoUh4Z_ru;D}7W-O-sIHgtz{x$3J+9;@ZWiJi)s6xaPe4Wl)G;2EKLg|c8T=_q zA^%%!T9ut+EbqrCg`D-N?EC*8?LSE=!OHlZ&;}T{67pEb3Mv6tO z3-kr0e{&=FPbqohB&h25{9oSy{?kex`zhj9=fC42$UdXwBfqlxpFqp6AwxV7mQ7+~ z_7A!*ghYHD@oV)DHu<7|Mxxp7Z1Ot#+w31~@}^56H~SNtyzvhq*YR-r>)>|)0WVBi z@ep{3ztu}Az7LH4$Bc))4G{E6v3MQr(Ts;ve-GJCC9h-L>3Fy?3cg>-mpu=vfu|7jVpxhrhW(oDE>chy4V5$ literal 0 HcmV?d00001 diff --git a/mozilla/js/macbuild/LiveConnectClasses.mcp b/mozilla/js/macbuild/LiveConnectClasses.mcp new file mode 100644 index 0000000000000000000000000000000000000000..c2f1157b624351a87fba85cb7d3d53feea804924 GIT binary patch literal 92447 zcmeIb2Y?mT`Tjq1@6x*h7Eo6O!M0%6wb2CxK|n!lEXx85%kH|nD0X5`F}4_!sEIX} z#Mm`zOzbAcXw;~Qn#69@G)*y4Bmd7c=e_sN%$=ECfAY;=;~stPeC9o8&OPOQ&z(Cn z+^ubDYVbTS?|J@6&p%|1=N~r0^LqXZ+e$y@vvFyB)1tb$H7zamO)Zr(Tbh>D)wUI~ zJ}29X9XzjMjOR6M<9W^WS^Hk4=N)+o+hJ^9WV<7}4c+5;y-)VM{$Q}bE8DG5UL&2; z9s`bQkt*wrCMu6K$?G0$_wl*~+sR%o*iP}f1ly^>k)Ai*wu|hzI@>O`YL>qU9667w(V})9=7de+n$eK{^A~&G}rBV<*G%;4H@Z;S>5G~ z$(}!Yk9(S%c73R|@wg$Qt&KsCH5wWzS{IB+*Fxt1@m8}@sW(Nv)PfV&=pD;mD}3M6 z|H@?OeUh7OGkFOOc7=nZgh@vQwFK36bM>nr>ZP|K^`2f+JGriAQC&-G)lz3_=heBJ zD-<-+$}_kdd_QLa*|L!J>dVnw%ozq;f%*uzEw255UU%_uOyBeq*OkteQA)Vsf!D zGHa^!V%r1!v;7{qV`a3Yb}^UzrsDMD8){lx>sqUhsaH6srH_9^g*v6fyb`(E10%RD zDvar-a6Ui%kW1K(L>0M9rryAI7u3b;GDA!KBvkOg*|1w=JZ}Nqy`i30&uc_I0`j~T zwmpr%z_#FT=fYaHl)i)daQJGrx1+vD=@HcLqZhqJY+phB7cLWe|3L%14W3}*>;2b3 zB!2^5*7eq`A+UTcmjj!E1N<@YAVl(K@G>|+KCjrW=Wzh`W$^mm=}imaBj62!HOTW% zf;U7Y{~TV11nBvfvK`t`Q_CXeUk`8Od3!E_e*|wl*z3>u`VYXHtj`PlEH9P35pDF} zgc)o9Y=p_%43TpEdD+~%dl>ed-e=gFHGh8*-VPp)NI8xF7HvrX6%A5gjiN?SevfWBP2CJQ0J0Hv42XBK&xo3FUHb5_@wpCF-W19OA9_8XEuQ?gL zQt#sBX}hO3k@7q8vVDMFUTxdK_#n2*BjuO#veVd^GpE5Pz&r0VuNGULetNsi9M7wl zzlxV#bC+mX^LOyF8>)nV&bAtn^1tI{ckk}uH^6^`_h5V&?+W?Ao`_VTdESfm_lM;J zd%K{nQ2rQ1s#wU&*Z{qXlh}?kzJ+bj8p`N>Cz$;OwifCYe}vUfQpLY{*(X4+i~N1E zF+Sx@F&@TtsZ%x0 zTS;9veT^5rAF1m_J=s|E zd5W>d=2T;~@ib$-|LMkhAFVs2?y|{8N!`!kqdy`=7M^Kx#0UibIeo@e|K+pjt9q4_=Ecq6u7H{OEn1;(1| zZx~mzmCuoS?8(cw0`z*!VypF()MGv`7X|3`IGpXp#+uu28>{ShjIU&SiSc!8FE!R& z%O^-Z?&jt40KFd1u+08&77dHj#SCPk#`g*Gu(WZ~Oq;8;svzD}N>RmX9e8NxiFhxj8_u_YAhT z7%yOZtFhukeg6M5DK>XTyCC_Id^LwgpsmrCs1j|C6gTpLz0f!$pOP=h7v-B8bB(pe zSmUX2)EJ+Djzq^J#mpW^zA4{sLyBYhnEd9;=p>~1)Ec8Pl5bsxH1G0*n^8Sdob8Rq zps`5vFaO*OX`R#DY0flPnj_7P;_U0_baV=m&mV^5w+(11YC)Rs(P&4sJ(4e;fhMAn zXdAQ@>WPLS`H<2&XgKPEMxhmGGMb9^Mdu>7%U!=INK*ykJ)DLZlc0;|< z5Yz{4j0T`hP**evEkNDSVAO>6Lo-khv;mrl_D8eOY%~Y$iq=C1pzi2E^d)o&It`tQ zR-=Q_A?Q#v7afF7MoZ9qbOgE(ZHIP3JD^GEQnWtmSfZs}YO0#txm?E%iI>`&K{F@S4{_0}>T7n99V*80|%eilNpQsKy82`_;TTlF}ZTm-1ZI9`7 zElcVuXZ*iTcyY4zwY*}&G@ZQHFVa=KxwAQW@9V}Ipe z$G(updlughzWaOr^rn`Dbt_w|XHVF-wR-xjsg*$G_En>+wyT^tc8BVza zk{i)!{mhO49>10@zqB7aEcqYf;*35NI@9NR1g6iPGI79^#>Yc1~sT#p|@$@7rFkwZGkS%rUA+r{Q|B zZTY!h=d!91`dp{ZW%YAC{cEZ79a>U5wD4v(D95D;T_E}7Y3(kg?h=VEKj>0P_Z#o) ze$JXTKmIV@OkK&)^Fl+!8R_3ru+#~Y{)Qn7X_*4lML2g>PE?2R2Lr&ao<4wTcS z=$qRsN14vlIRc#{@V`C+UE05WQoLdw+_ngAU5w!_)jj{`L*qwoq$Isv`&T{VSKiy( z*Q%TgJ`=i((fZGodfij&OrPHo(1$ip;jLk#hbjH)>eiOp>d-Tx)wS+<$4*E2TsTR{ zA1ZXlSUqu7TU}#oeN&^miC27bT(|V>QP^rvkCI0WpNp~jJan?)4`cNGffb^28TdTR zdU_v2{=jnq@p8)TOrLB74nMrLt)`{zlU4G`j`qE7?mP4+p3hG~XA*|O*Od{JN8M0& z)C2WIy@K;&cb1%RXql<~vvdaWzxEu&+PS^RFsz+K*FSwNYJbMoPUk;6wRGONO`5Au zm*;-Wr8p=azaD_+|JPQcPM=Ehsn37=h4D=-`Km zf?uopOtgG0HBz_Z*HTrT)qFNbAUL(^9^8`nY<6HRwYulj*|SzQHr6a`sMD_?eD2bO zNz>-^n_kz}(sWc^%ktJrof~}ILHLCK+VSJQU1#}E;Rvkcshv+@v;MnH%H_P8=H`Yu z6KCreKRQ$A2z=g0;D6_FkN@TCZ2!xBp_f9SYPMipYah`+Sb-wJ!;f4E*w;~u57HTZCWv^xut2*%G$QpQOg!BAGKZ8cB2+G z)wYhRX|C5VL;jB?Zk_6`OWHq%F7}pkS^pS1TuzU;T~oZHV_*e}_e7~r|LpGC4wTbB zhW=g$%IP0NU)OZ}30SzuCv&^XcHT^6TG*_+1b` zDXG6$;j?=Ctjs>EuFs0<^Q*%?zc}pc*NOkZwjbhGi~RwJU*yUE5Z!_9M0cT^(QW8Q z=x+35bQ8KA-HLvK?m_pW`_TR90rVhx2tAB`ihhP3K|e>2qF?4?ad!LP#oC)Y1h{rIdmV0zP$aBdj9&OUW*l+W!0uM5()+%kCJF?Hjc z;4i|18tT=y+;#9^E06DZ>$Q!aL;G{D!|S&-99Y8;bb&XhZyZnC^26Z`$G0`$>-mZB zkcO3YJ>Vtq(1sqfsWX2XywRMxR+Ya3-grVw4f*n2Z<9GKHMQ{5aAj{YV8z*{^kX$c zJP_WDpZ;A0?*wmNuWG!CIlK(ZU2^e@a0{$t zsFELi=*e~~MCzjL*11bAAU?Z{gSYXzE@J$;EP%H~q%Ozv!djx#MZefR%K1Z=Tj0^o zAG$mXZ|D4>i`J6uoj-JC?ecbT{?K)2ct__CUFX3&Ie+M?&h6~{q3fCOF3umiUJLK) z{GluH?d|6Lp{wSl+WAAbuJG>8AG&Q0@8SHR+urb=&L6rR0`KMKx10L1xATW?>dP4C z58YUM^b7PF|8CF2$xbTr?D3!FJxh zbw?Ak!Cz!J2tUG4dTL(gPg&7S9QAw%K6vKb$|>+G@FDwp<7xZdv@$0n^UNEV03h&cvHOz4u|6Uiv3!VS>`Uza?{J)pxWzn3P7UHOv ze2l-xRXKqrV|{q>?7Fr#So5-^k{wuMv$Sq@&0?7KCHRX2W8g2t%MhveHM}ej(Cd94 z+Xmy;*sA}eKJu}~w-5lgBopM+0>Ti#}{;0xi_ zvHQ(teER$lZlmkGU!P~-m5eRxSf9VcM^35Ky3|+ma@6wbv9++~W!2JF`DI_m(L1`S zp{^2E+mGQld70O~XTrz2`uko7ALr`t`%C!v=H`0(-S-{%1mcK!?1vwCCyrZLPe1#O zhF5zW49|hTfJptcwx|!Je&_IVa)4gHo7tXXthMV@Jv_?ODcJ8_zaAfUVj}8nB9&a|84S ze1q+I#&@y(n(+&4&o};%?bjWzGlcC0##%#kJZYUnc~M(Q>m0|+w*vIm`8He4F=?H9 zc)3UfKgWywn6%FOyr>*$-A#D;PJrIJdzfdV{uN zd%f{wwl^3rVSA&o=J_UL)h)jv4SJB5TLSb3y~g%d$Af#az0G)AwznJ4WUH7V4Q}G) zjsU&En$J6p^`4qn(%?sV`B8x0;J4YzpGfQV;)QccrS-PvMQaLay{Ww1BZ8Ola&Lg% zdZ)6z&sbx5zwtwCA25EEt@=Y+KhKNuNb7ILi^h?(zUKF*0eb7pe|~0sBHKrdDF()!Qy@{0hy_2oa0Io@DHwvQXj|9@$$_YEA0iFW`@9~YH`HhQhVkZX|6n|k z?VHB6Y~M0g{qhyk(93!GV}RaJ`Ocq=)j#!tG*ol(mjJzuHemZ#<7&3=7|&z-uJKB? ze=|Oht;U+P(XG7vBS3E>&B;HFwSCVqe|XP*FJrUuPQ3iv?6cXb9i)w$dHEnfZ{x4B z{m@u(@gL*I*nVWJ{;hGmNuS^}BG}oa3f9<>HrWTx883$O#;3p)#*CG|11fF8Sn0c9 zz|5h(6Dn15TyWkm9uD^i%wFYqxTmq|SA3ExPln|m;)`M07w}zhUt|1E-zNh*4@eoC9o zgohY6!b6SEfj2V#0lcyCqwpri_?KVlcys#aZ)!XO);dDkd=k95@gjJbvBruqRoYx* zwT1D$Fvlxx{t7(O@i68}*9eq`QJ=0A1g!eCCX$BL!rK@h4{vLHAzWpACp^lS^+4AZ zl!m4uW?#`?2sI#;S8q;|Jiqj8*5}jz@Hd#~9OZf2{EgSZg%ahP@l{0@A8 z8-E`@*!UOlA;y1(4|TjX>w$lmvD$yQF=Od3FqZGt7|Zt-8ea;Nr?mC`@FL^a;5x_K z`czCHXZSm`k+~|1QL2#2Xe(g6KGnPJM zq_k}t++zH77#~vF_BNQjfS-m}8vhN(CzPrN!$%pb{#C~N!$%uaw@>^iRhQx#|Tl_B@Ukrc6_)hpt<6p!0oYH8`#aWKG+Ymn6cxU(=<9RT# zs-KZLI_R)4QG{uBH?$2(TQ_>j_$>%-R>kA{C>JO#eqSnqp-F}~*CXw10!HyPgs z-)#H~m~mIy@iq8X$2)0#pq$c9Tfny)Pljo?(oRcZ#x7v|%f~+grceG|#t*|kGS)oa z?RaO^|6}9f@K202hW8jRf$ue54c}+1F}&ZH_X(~)vb*#1@PlUmH~f&}T{LdALur?4 z_@~D5`JWlDh95Czo_%6TX_tFod_rlLS763VX;9@Ds*I z!cQ9G%l=cwjJN+Q;}_tkjn)2V9PhRs{H(Fs|7+v<@NbMY*UuTtw;2ni-56t^dINq5 z{;gxG@%-Nz4}*ViJPv-*xCZ7JrE0~_%f|S)&sZo`GjG8)U$NSc4=GiD2*2)l_l@8; zjQ4>5V0;Mtrtyg|{-Lxx@#Md4%)I%3G?xDm8%lfhfd6c~E&Lbbec`_vFNWVSJ{5k~ zSndCt@q_T+jcKF*5663Uh5u<>1;1xJ4gQz$a+rBi+EewvZ+sE_fiW@UGZspF;xGPx zj9-I4GF}5CrM(6Pm;4+P<2gS-Z?B1P&iG(BZ`=m6MkwudCfvmsAIQ-MrM-yzTsLF< zJ=fisxy><-N_)}2Tu;Y)_l0{IkA!<0Pk{Rv9|luSY425VKjW{${f)1I2N?etUdNdD z$gOLPkK_g#Gd4N;uQUc*Zm==)niaOzueBoyTiK}&xUt3UIFiBdxj~XSK(>K@4?d@PwWowXS^Xi!F#2n@hGiD5O zhZ|$dEihI)Ym85Y7aD&9t~I_EUS#|exX$>O@M2@l^%CQM!b=_R(+#dS9s(~j))=z3 zD(!FzpWbT=)oMjc1GTkKtD1r{Ff@Kfo)E6&FW3 zp4<;U%9wQ`x5}8f%pGlvU+0c7o&g_g%=qPwGp6p`@y4gY_^8t4OW+d&^d{c`uQt9H z{(`aQ`XuAG;FBH8eRHQ64}_T~r70s|-XmbO?Q~&DDO?gC@l zp2Po?rhW(hrm@EDTgIB-3ysybi;UH_i;d-n^i65sUNCh9yb*kfv0~&>V+J~RneoB! z<;G3$6~?RKD~;(>?z_fpbNHXqzPH0y8~+@>#`t;oTI0XM-!onVf8X)6e(-h1o54RY z-U+_mcnr)~C{5cBzR~z__$FgwBF9`RO~b!(w-_@&xm%6Z=G%;a1k-M%X&TQT8f$I5 z!}#y;osOq#uJ1BlALe+a>BHc=jdz5ZC#C5V;hz{E2;XB|4-*4Q(}}a(ea33%{l?5s z?g3-^ntRX~Tkav_U%?L>zXAW$_+RkP9Pig1e#CeP%-ksLw-x-T@m}yRjHkhm8Ot9Y zH(miVMoRmg2tQ%`MfgeMufwc6O8aS?XgV@%oHyN>to2LH`i{)z7@?Y|BD599IhKaDlN?-?Hf<2OqCp8@~dn6)AIzA=8C z`@opF%6(|e`{(}Scvg3q`BR#;In1~Oyle2dfa9sKZ}tUn&iE)eZ~Rrb!uTqE3?68VujL0BGv|5yLuoeSnqSZH9NLv<&XneC1aDxxExe)eUNHSp znxi%kHC_sHjMALr;Ej#XhBq<31g44QR{Zu;OJh;mE3V4+9E%0dLhvDsv ziO2l*#&5wp7~{+N9UUJif7r>Gan0{+Ok4817?YpJN0km72k&OAajrI&Z|rW|0`Fmb z61=DJ`7r%gI`CR}Z{xe+F~%C_vBtlLc|WBC{|1kDJlBUO7~`k;iN^BhNycjbKE|{w zKiODgKE?PDc&c$5ysxp^Jk9tVm}8XYUJ37Kd>cH&_z`%f@eA<&#(#ntBc*w2^K9b* z@El|OC4Ydi#`!>F`jnq*JP$@n^OnO086OGHH$DYE*jVFC-<0NE1>;)*-wq#U{8RXF zW3_pK@w;%1#-^QRf}p83;_zYL#Y{B`(?#`5Pc8LR!2 zQ#$xTn7Ij9V}7Rb>+n~NKZ4J4e2Ch7w($^{F;Y5YG<>e{IQTr{x$xJFCF_}j)qVSG;MQ2E9s0eXjy zg)cQGcJsWq(xLc!p7{=#`OjZrOuzGtV_?^Ke%JU;_$uR{!&e)>1YcwP4t%Y##`AlQ z59 z;oFSgf^Rog+ZcDH!w1247>|VMr_$kL;JX6!4%fK-$hZ!^+nD&!Gv!K$YkrB7fSHH< zJ;wAy&zCD5{s4TRvF7)F<3GaWDJ?+x2SxCD@I%J(y@!o8R``n2g2UjS86N>ZVoXfv zd3B`)_>rDl4_IUM3uF4B=hy@L6Y%54ufe}`T;s#!Db;KQKWV%({FJfA=U2uJFypRN zb1M9d@ul#y#*BCV*T&@M84INv`T28>7j}W4H?D+VFy0;ht?_>F?~LWozc)S}e$kki z%fDodf8}2`R;;~Z{3?u;YI89C4|rpkH6q|@_zh$A_YcNR@SDb`!T6a{?YH2!jc7xBZw~+4cpUt`@nZM`<5S=djW37)WBefekuhVFU*mW&K2zb)Tf8aEzS3gq zuV8!wu7PPsz+ZsvfW=q9j74C_uPeG5Gkz7_953kycQ@V|?qNI??rGcz_cHzp+}rpn zxR3Eea9`usVd_;{%6nGyHy#NOFy04V$G8q&*O>9C7-+2av!*C5y%!#A{1Qw&D=lT5 zD%N*gKNQ};cvqOYSE@e<9%9@EQ%?}|;0u~lql zya&wOD=pJ|4KqF(9&UUgyoK>y@Cf7QVa7#i8Gcu>rQ_v{S;bby+ri9@((-BWHpYwK zZH-sMRmK;?qm1u_M;reJrY@!B_;tnhjvMq|J2?I{zv?+7Jzu2fiu62@o>S6uNP3<~ z&k^bQAw9>W=alsPkUs{EMZ}7p5Ar9ViD(kS|Mc9Cp7+snK6<`K&-LheCq2`nXLg|4aS z+K8^3=o*HuUFe#Hu2tw7g|1ELnuM-J=o*BsJ?NT)t~KZyL!JrOH3eNu&~+GHN6_^H zT{qD6g5WyA2^2aJtwvu!$DrfUN$6yB3OX7chfYO5Mn6IKpwrOl=nV8l^dsX?ZGduULo@^pMH``UXgr#LCZfI2STqUkgC?Ur(HJxZO-1{n zX=pmy56wU`(f()_nvLe51JHqJZ!{OpLkFSxbnhdy#x+Uz@%5~Lo(0f-{2YDMeS1Ai zpl1U757=jXbkAP*>UED^_vUp^Uiad44?f3u=$^aowd)?c?yc*ddXDkXJ#;;Pp!?^# zZ?600x=*hAkYcjpz8~|hM{W|y1t<63c8-4YaF^(q3amBrl4yHx`v=@2fAjU zYX!PSkY9lC9bF5^<2!kLCXdhPyS~2T>$|yuQEdd%Lbn>3Wo|L+SdH zu5sxamaaePx|6Oq=^B`>W$8MXt~u#ilddu8+LEp*=~|MmA?ezYt{LUWAm&onhICCx z*Mf8nNY{RJ-AvbgbiGH{d31e8*L8A~%~3W-*&JncPdZ0EIgZIuUiXJ}&pJoFx-YGJ z#JV@Ed&0UGtb4$^_p5upy4S0Fyt=omd%C)pt9!V*cbj8ub+1RzYraq8Zt z?rG{?rtV?t-lgtY>RzSpQR?1gZUH(L9fyubC!iAv!S&GwXhSpv4Mgjqp=cwtF6(+SHR&3Yu6ybF zm9A~+I+Lz1>AI4xC+Rv;el_|6ItiVOPC=)l)6nVY4D?0xCDe?*jJ|@-L|;W`v6j#d zpLY1P!>1iS<$T`LryV}+@M(un+kDFVw9nTuw8f_mpZ55)$EQ91*@!mzw8^JUK5g=8 zlTVv`+T_zFpEmil$)`U)?eb}te-5HuKJD^0rcD~Jeu%NsJq6vj(0vKrQ_#Hx-9ylQ z4c(v6y$jt((ES75H_-h8-6zof0o@nS{Q%tu(Di>^_s>_NP0?m(b2JPwU-{u^3p4_a zL|YOskD#BUN6|0PgXpK|G4we4C3*n;3_XmVKu@Bl(67+b=o$1Z`Zf9udJa90UO>M^ zzeB%AFQSLgOXy|v3VId2hOS1}pli|h(B z72SqzM?XY&pgYlB=tt;o^kZ}d`U$!R-HYx+_ao*{&lc#J0zFHh=N0rkf}SPNGX#2e zAh#NwicUuOhn^eI^8$KKK+gy0xd1&6pyvQ||6lk0b-!Qt`E`F^_w{u@U-$9#4216C z>)yTY+2<}nm*OY1*{97uZT4xiPrrQn@#M1wo}h^>RC=b!>MOC^{l0yvDCAbdZtp( zZTifw{~~$`y^NTDJ)fy(H~m-8tB5)EUq^4CKcF|!Tj*`{NAxH3XY?2JSM&~g7vV#C zmQl|z>e)p-v#4hkea6mb?0m+~XY72&*JoUP#?WW{e8$gb+v<2D_ZGtvJBhW~+CE5yYjkZDCqAD~BjYiv{?a>ZsN3;{#84X3dpk2{!s2c4~ z?9z8#L)NupT{G5oXTeYl4o3W{a4q0b-h>D zd3AkP*L8J0SJ!cM{Z`j)b-h;Cy7P>UuF>k+tgguh*J7XZJnwmgpLqC*_bbF4de0(! z#=~d47tvGb8HA5`_>G6(c(0&W5x(NRj^04{iifXw_=<^iT9} z_A&T5lt&e)3+jrxq3);$>WO-x-lz}i%d!7p+Yj|e1JF9m!4J_L=uUJOx*6SueuVBu zKSnp9+tID)C+Hq@FS-xij~+k|qKDAK=%?ss=n?dD^eFlTdJNry9;Yq;52^Ec1UG22 z@hN?#E6pAQGsjA^XTi*Mz_qaEoHY9=n0XKQbeQ=M_#zlT2>5$2{t&SI0Dliyb4E-A z{1S{02mD8vcnBCD)_H|e=ko||96FyzaO2SVJc1jCc}Ef>^Nmk|4>mp@KE(Jc_)uf5 zw}%;PJw4p`1$cq+yKs%;&gT)_ILtqZF$8 z3C4edPc;4zUhTN^c?35OhiIHHFun}_hOy2qzG*BU{+97?;0uj4wih|>d>+A#!(rz! zCY*;U9d<3uIa9zo7sGc0ej4UHE#S9c){B5Yf*E(E&gT)_I4pRAF|l*b1+T%sboS5q z>!h`H? zOlpF%C)Bsrw6@l*;E!pwq?NJ1JDJc4)iATAX&JvymUQs=QRBDXnii~RrYDKjyApG2 zS{l>(IDXP}{h(UHn@^clIitC)entH;$#n;RGjqnuw&si*1`+u(Tz*GWolEzQRlDw-)p=#7cTBm3*4wr+h^T4$k-dmN@k4dlA*}-G z0j=E3a8`kgU{-c|C@VKLkPDgVK2Ru;G*E@S!Z4K&N=5+d;H>Zs@)Lqr_VmzIZff8b zGgBL!7_>U9osdmrztH^3rClQX)z-yNG&rZM3tK!pvuh( zPvxfuXCX7qNr$IR zlk&>KuuyI4a8Mv640ULF7%Dd_43(c6hK05lRN{3+>~KfcDAdRN~C#FP$JRQm6PS_ z%5T@zRj3_T4;9I3q&zXj)q@(^arHu(^np%s^}>M}bCBigIy}qObplg<`dW;XVs^^g z7xRl(VIzkoo{~jMl%JH9WhW1r-Z|sMj4{dTS1~)KU&Z|Lekm)vUn-H&uR?ZmzY4i2 z4byyP%vUkHy~E4rzv5`&A%oy0{CF1hK-6CFG z{Spee6}mhlvOt$-hdnhVH@(?~ug2vEmM{C|W#X%TYKe?)6N`ALJH1IbKEC897fGEo z)vj}!v8l@t!nWzs`3&U@vRE7<69-N z;#>I{@f~ER#&=M8T6`-rJ-!RM8Sz~xk~px1%w&g9ZtNVad|Wf*JE$QkzLk*?-^xyp z?_zFxvyDUKc#NQ!S|WW=|!)8o6Co8Ii?_|}2##kb02$9JeiMz?Y3 zl+W+rcyimBG*yr~Y04~*??TP#s@mw9~0V(5F;U9{DK+3D?~~)k!2#KOl+-4DHUEYGKyq(x_s$qf7J+=NLVn!*~x1~xJ1%25zbFoA;Q_} zcyw`y=O(NR@gk8Sif2aWJe-@j5R?~)IeDZ&IQ+vI36USpE)V*$-1KHgLp^+8T9k*& zBnNmxiHvTShjrxm zEzgJqX?b=yNKbX&(1R@Q{$<3XBSBz4kMTqohlhoz4T zRKvYFea3k zG-sw=r7mxnYM;`mwCa$Wjx2v zjQGkC&Wo-Y;he~75zdGYLO3tHhQ#fW)gzv16BaiYTr6yltrg{2#c+va*_ZUtfR*Md zTrjd;gfpVfQI=!>(4x$q)P=YwgbylTIl{T|H6tM}vHSAI!a5N-CcZ+%GZQ98bp>C| zLt`1(>?!P66{VFRoDo?A!WpsX4`+qrK5owp8y%R?k?>*=s;_b+|7vH;tXQ)WX%T1H z8F6PNQlroE(_+xFGa}JSq{L$=H!UhdMaoAml$qe(mYW`@kpfBXS}0H!vzCzm9GAEn z*uiOQf@P<#3|1gzeF)`dtrDSPsU1&UF*Nh-EE%py`kLYLGZzh4BxBWZ1=5!dm!G+A zxFV?wM=3jfZ-A~^)CM8fjna#Ge0mzlnRxO}}<7Ecl*pBte9 zNlQp5JEQ9=6+TT&c!zdY5%)fs%Sfb1)*z-XBvwP_N>VD5?g)u%N$J3hfl6OZ+~MiV ziObJgPh5%A1*Mdoy`q%Lr4K-OO>vPsHsMUaloMG&O6K^&QOb#~7bUwR``6PYb9{9u z<%Ac7s5P<{M6;~pQDb3NOV(Jx$1{p98p?3tT{4uSx@3z4bIGiEDaCNiZlN2qmN!|I zgafs7KzV$Y^5S7xmXpxca1e&d$73&=RW|U2NQ)LL?^h(QN`)igR5Hh+sFV>7o~X4f zW}?|;4G%|%TMg$lHKlzS4zeOK5;`OvB%!Qml!P)|<19=<_IR9xvciE9Ge;sNmKRwg zf_|u?!UTm1$AYCSr|3fAobab%P-Vqp=d0B2f}p;_(p}!;w)mL}H?7wLTR03u7G^Vi6Fs72Uwu zoYx0j^7mjj;^~1U>ff6fwPR6L;$x`NbGRFK)rl{Y^Qs#Fu zM*OZ|i27Z@T4;S?zc_+2#Qm;hD@|WuGrtpu{7$=3zmp~AcSTdd?}~;K@=&Mm{!S8YFCrQC@3MVCNjmw8^~;mBf%a1#=IE@Ac4p$Yz0utl01^R;U2 zmko@Jp@Gq^?u7*JBer`WwqLs1DMQ@9;%lDD#C$8*Px7oFBh-+nS0y-A+@}&;s?4L} z4wc|fF?UMxrl>Q;e5u@($~~#%ND)7ZyHS}J#hl3PmS!l}4}XDgU7F}Y1!pP#QWxdS zr$YV{xJ%&{n@W^>Phcy~S+M7P$6?WRv>W!ExZ{-jP0Vf5ye8^2!CqlF_E=Q6xQ5^M z+pElVN;#3w%91(0HkERspP40lWSuIR`NN&lSl@ak{8KNFs zv=q(}3nju$i2JJ!D)&@b<31X)MVc!&EBIwlrfjuUWf(&PqupS=wXARp$t!uDDvbD? z3^8w$DePy3{W1?LWP}E+d#M3opJ{DsDPM{LW5jO)OWbn;W7Ky7Q^b1$OWc0~W7va=hKLUpt=9J9 zeqqc4L(G#xw&FB7o1Gx3$0dIXvLYT8SfV~vG8ImeR7p@K(v-Mo1;>^9R$z{MSJ)VB zc-X^Ssko07t>J+x_*pSC($t8r1w|s>7Fc5b7TCfbS2UFQTrnryps?SqY;0(%DL->E zbHw+|7WY0gNBz%?5f3z5+y~7Z_QH@U;)fx-^(SO0jH;Pp-WahKr?p^p9%*|epEN_n zE6o=5%dpWrGi-`AE$*FGwA?=}BkrM5bG$QQFD;ae`)SA?9ms;Oh6=6;b0TgS&WQVBI4|swaeKro1czM-j&!@clPvDH4D6<+k?_JrPr z7y3}~@eTSz9pxvf2}RNZu~0=uJQj+ihGn5ZT67ljQvxxZofePbGUekF&P|x`LUwwP zMoT0)Yq3OG$QE+aVziK-8mf^35`% zCAg|WxjjEnnRGu$SPa7NoiT`MOGDxCv=yR|pC0ms5-E`%&Q9-GcpYfqBe>Rm1XnGq zX({^{j^{^KfOuv+{Nwr2*pKH%0zaM^j{2m$$W$j4u;EC`D$Ha&FBa*^*+us)%XTpy zH%9_Io*9kq#9RyQ#JseQ#DhA1aCt<>OT@!DB|mjAih*2qU?_@{@-pW&6u(Kw>Y8+- z-R_Shf$1@`_8_$ddY&<(0tx0()z8Q|w&-h=1>ui4K2y~7>Yy={IqbT_Mf8M0} zmR9}kz9lQ_8r!_;nyM!L#@w{}g_ToQG;?jMl8-@e`pmiE-ElPy4Nd&O>*TtIW^el3 zO82Q16r9VybPxVkoc8p+f)z1*XruxBG_gk=4NY^KS{fEr)q2xsPpceXr4QaoH6wSd zKYZ6kTUODOz&>kbBYz;Tj!b9bj}ekpEITS(mVfk{REz%9T~&kCH+#yA1LmnzP+g>5 zEb?A;+!7xb6)N`KcC7E(L#*uHyzw(86$c=&m&PMFNIj;taIvT3i+fWV+v-{t*VNVp zgW!4`9*po&u0I7!wD}Bl(ELcB_?0uS+Wp}_KH*~>CbRsA#A@`8a+&F|2`NsVHH9sGNgnf9q!!F8TRbuu1V*TOJ*?q`Qv>Y7`c^ye&_ zTD)=YXAZ-r>c~&M1kPV>i4{__qJ@HnMonr|xkc_<{^N0;Glzbzru^qALa{P(`}$It z6kNY#EX_;NRvn4D>T&gr)j{Zm9I<39dSf+S*izF{&lh)h`o>dKE1DXsBVL+T$lSvV z;@rGY)RC^T@xr&_&yc?SZCH*+DRl_I%$lYB)We(GF#6`vzktwUem~r zpR{Q4h~zX!c3Z-GVRrwDI%?5*{gz&JsJh5bW#Q|fmPVEJrjDIu>pvmrzHHPtE-!N7 z2U>z0`=SwW;fsZK!VmU^-kEQYyg|4vW|=x+Uu#FzG4;(XayJ=-hZC$J|@9&P*Ka?ueB(7SvD)B&<7qmO*rq!x{ zZ{Zp*@~YiFRn+l7JiELGHO6`t>sX|r?ijsOiL9cUmcl!TXsN!3>$z9D9H}EP1w%KD zdo*<|h4H1ZX1VOYm03N431_A_o2A37c38>gaedTx12u)-H;c zs9j_Q1RC_fK)*sY(>orjh#gl`sF|#w=IQ`cMetq$1fisA8(O1>H?-Q@3dq-eu4oBa ztW0>S_g`6GyL>izV;hzd8#V($n}^BbT>4jwL6;~TG&yO-FvNU*2!D- zoTc^rD(TFcmbRlSXPd1xaOBqN84LBdj%PP>dQn~5w4%Bx*l!K?mn~^k^STA+G+FQHPoF-sC96P3 z^2Sgo_$aa~jfuysH+JUCX^A->!?=L5W1E{fTl-{b0f&#D@s;K6)lxXK%_=v(p|v$D zUwIv=XX>(+#Z{=iy0Y^72k$k0LROiMO5OY^79tZc7LNBT9t zzIoExsAo}A?aKD*X)k{P1zK8LYTGN_N;}t2>P|Gxo$~Ddpg`NeW%Yz9qE_5c%;j0DIZUpeA+&l zrca+XE~C>y78iQL*V+?{PoFuh-AL|GJ#*L2C(4X*Q!5i28ZyRiKZJ5hICEOl!qVRV z8!h0lPvs|EJ8K;tU%Ca8()HjIrFQGBQ?dhd$Lq;%P{-@Z4CK=76#_M_-L7BFnH6=o zJ$0)x>q%=v*dDYe`^2W*e)Xrqpq_SGL%%|I+rq6Vv8$&h^K7)^_0(qeti5qwUF=uw z(kxHxcsyV4xDKPEJnLyY+PR95cD1VtdxYCyG1Aq=OlWR_M92%%q3XG7FGd z_TXB=0iW@6)#M4IpC9vFHMJfM*?;R?wIlNtwC7WFuF5m)J8WO6XUdE@f8C>6YS5exnC%Zw#Pl9&q$^1b182#$t)sObt!_S5#jortw1>>A~ zjiCK;{`j9v=^YE&)7;TdruORT;3rc`HLDp&*Paf3GPPSzM?aa8D=N09om(mRbMTK% zviuB2Gb&qaD`o@FJ!YiPRqo^gvSX`wFe;-Oj|XoGSKU+VVGMOM zd;)(mE_tcz{W0!5Q%ib#KE|Er%z8TV9i_eNVhd%To-wMY<9BFN>rs0;a@C@}el1W%qz>K@&1_FlPsi@~wNuYs+j?HJx1zNzb|${; z-=4RF?6HRkF2+7U_Qs$y#TS1hI1+n((IoJC;UJt83Z10ObZ}o@m z{!EUw`os23ul2m#HY=K2dEc;o^JlORUD39L_J{4h+HlXzX{~Ku{!ibBH*sz1as=C| z<`zEf^N-#E({81qJp52G#o6x~i=iqodtLNxqQcp4JRTn9?3J{~8|Lh5wuGyly~}sl z_H_2=XTZBVd*x$n&kgJqJ3a^R;q03(U^~^7zgmwp?CI=-UtnwP{P}^f-2+;$XQ`cy z>tUbf$`6^%*4p_az1MWJ&t+@vJnLPi5=cnLqRI@O)<zr$qtUL>)`LcFipihdUWyLqn=cRiv&i<{J z!T7gQ{$gHw2lm|fbK&=8rHOa*;>zcy^GWJ&5SYD+2iaQrMO;DmH+1&=;idB1XbgX2 zcHQ*1@>hNUKWFxH*t&7p@6ZdV=R{}s)sOBg_%~*5zwqjx0xeom6Mxcc_`8gex1ueu zR}@MU6Ia8lvFofPWUtU1Rjz1jRsA7*ekA+-DX;kp*>~y9KJnF{y9FWp;5*shEEu=F`nrx8F|0eyBX9C&tvcA>=o~@b@lhT0zc1pclLEpVC(AdbL&v- zTR8i`$!uNyecr=2^CO&n*+y(#{e4HTk6kfO8r;l_tH1AvGqGK}B+jo2-| zb}!XGxRNy>Z}BznwPO8)z7FRVC!~WEPp?>zCQO z@fp03Hsr`tns_`fuKj~n{|o!2f!Uj&II#M^L5$=sbM~!oVC(Al2F>Apzhd?$*}D3@ zGc|6EsnVSn@)Fd4;+kh4!G2a?_U3EdbM<>WUxHn04Qa}kd9nKMZo&S8!0b)joNZA5 ziEG~YH}>nD{mve2UHiSA=~tdHRa&NetN)DeVZSLbd+V0Qr|UoP{oG))Yy4dMyNzPL za_c$!F0Zn6^>;h-4eT2@`@|jCy864Fe-ZW#oqga^*sVY7Zh+6{nH!}^2f^D1@wM)k zD3kx4vsYZsc0*^cdJy}cojuPOn!R@gb5t?V*|#C?y3Y*C_nz?|?1P+r%5|RC)vZ^( zyW^7;u3!G{+cKQ*yYlsqVYhzeXK`HDz}{;O-=HhjclG33*{<)(Z#omZ^*4VF_MXmu z<#_DY-~7$k`#Sr{w54K*t7iaq-__sya$>rISXIg^UaDRBU(Lp@_$1}E##;M#JP-TE zf!W)UcKXk`@{>-+zKOF}P-mh1>wU0SI{R+jDZh>@zYQ^3v8k0`m#rKB-c>WOZ|3YX z?qD6Z@qBFAW}uAaGSKY2>)Uc$>lXP^2$_TjR!eljoKuFk&sHrQ=ls+fqq zPhju$*IlrWP-)LQ0Kd&!JL|AjjCA%2&C5Vn&vgs1Z)tX2<*@PJstvoXS3C1w-Xm83 zvDmkE<*S(=f3UOvWh!=+BW?9AFIT(zZ+a6u{-Lys-rt=M^uFmd>{Wr;8~Ypl+2&=- z-(nx-?7JMu*2QV>@sqKScJ_hQY+XBhy@Rh+Z0GE|EB{>gzHe!Mw|DkkR $@ +endif + +ifdef JAVA_OR_OJI +$(OBJDIR)/stubs.o: \ + $(JRI_GEN_DIR)/netscape_javascript_JSObject.c \ + $(JRI_GEN_DIR)/netscape_javascript_JSException.c \ + $(NULL) +else +$(OBJDIR)/stubs.o: +endif + +export:: install + +ifndef REGENERATE + +export:: jsj10.jar + $(INSTALL) -m 444 jsj10.jar $(JAVA_DESTPATH) + set tmpwd=`pwd`; cd $(JAVA_DESTPATH) ; unzip -o jsj10.jar ; cd $$tempwd + +endif diff --git a/mozilla/js/src/liveconnect/classes/Makefile b/mozilla/js/src/liveconnect/classes/Makefile new file mode 100644 index 00000000000..9a6d6d0a8cc --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/Makefile @@ -0,0 +1,65 @@ +#!gmake +# +# 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. + + + +DEPTH = ../../../.. + +MODULE = java + +# +# the idea is that the install phase for those modules will +# make their own signed jar files +# there are some exceptions here that we deal with +# stuff in modules and in ns/js/jsj +# +JMODS = netscape/javascript netscape/javascript/adapters + +# +# JDIRS is dependant on JAVA_DESTPATH in config/rules.m[a]k. +# Be sure to touch that directory if you add a new directory to +# JDIRS, or else it will not build. FIXME +# +JDIRS = $(JMODS) + +JAR_JSJ = jsj10.jar +JAR_JSJ_CLASSES = $(JMODS) + +# +# jars to build at install time +# +JARS = $(JAR_JSJ) + +include $(DEPTH)/config/rules.mk + +JAVA_SOURCEPATH = $(DEPTH)/js/src/liveconnect/classes + +doc:: + $(JAVADOC) -d $(DIST)/doc netscape.javascript + +natives_list:: FORCE + rm -rf $@ + find . -name "*.class" -print | sed 's@\./\(.*\)\.class$$@\1@' | \ + sed 's@/@.@g' | xargs $(JVH) -natives | sort > $@ + +check_natives:: natives_list + rm -f found_natives + nm -B ../$(OBJDIR)/*.o \ + | egrep "Java.*_stub" | awk '{ print $$3; }' | sort > found_natives + diff found_natives natives_list + +FORCE: diff --git a/mozilla/js/src/liveconnect/classes/makefile.win b/mozilla/js/src/liveconnect/classes/makefile.win new file mode 100644 index 00000000000..4171e46a326 --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/makefile.win @@ -0,0 +1,74 @@ +#!gmake +# +# 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. + +IGNORE_MANIFEST=1 +# + +#//------------------------------------------------------------------------ +#// +#// Makefile to build the JavaScript-Java tree +#// +#//------------------------------------------------------------------------ + +DEPTH = ..\..\..\.. + +JAVA_SOURCEPATH=$(DEPTH)\js\src\liveconnect\classes + +#//------------------------------------------------------------------------ +#// +#// Define the files necessary to build the target (ie. OBJS) +#// +#//------------------------------------------------------------------------ +include <$(DEPTH)\config\config.mak> + +JMOZ = \ + netscape/javascript \ + $(NULL) + + +all:: + +MODULE=java +JMODS=netscape/javascript +JDIRS=$(JMODS) +JAR_JSJ=jsj10.jar +JAR_JSJ_CLASSES=$(JMODS) +JARS=$(JAR_JSJ) + + +include <$(DEPTH)\config\rules.mak> + +$(JAR_JSJ): + cd $(JAVA_DESTPATH) + @echo +++ building/updating $@ + $(ZIP_PROG) -$(COMP_LEVEL)qu $@ META-INF\build + -for %i in ($(JAR_JSJ_CLASSES:/=\)) do @$(ZIP_PROG) -$(COMP_LEVEL)qu $@ %i\*.class + cd $(MAKEDIR) + +jars: $(JARS) + +install:: jars + + +javadoc: + -mkdir $(XPDIST)\javadoc 2> NUL + echo $(JAVADOC) -sourcepath . -d $(XPDIST)\javadoc $(JDIRS:/=.) + $(JAVADOC) -sourcepath . -d $(XPDIST)\javadoc $(JDIRS:/=.) + + + + diff --git a/mozilla/js/src/liveconnect/classes/netscape/javascript/JSException.java b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSException.java new file mode 100644 index 00000000000..4ae02ffcb77 --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSException.java @@ -0,0 +1,56 @@ +/* Insert copyright and license here 19** */ + +package netscape.javascript; + +/** + * JSException is an exception which is thrown when JavaScript code + * returns an error. + */ + +public +class JSException extends Exception { + String filename; + int lineno; + String source; + int tokenIndex; + + /** + * Constructs a JSException without a detail message. + * A detail message is a String that describes this particular exception. + */ + public JSException() { + super(); + filename = "unknown"; + lineno = 0; + source = ""; + tokenIndex = 0; + } + + /** + * Constructs a JSException with a detail message. + * A detail message is a String that describes this particular exception. + * @param s the detail message + */ + public JSException(String s) { + super(s); + filename = "unknown"; + lineno = 0; + source = ""; + tokenIndex = 0; + } + + /** + * Constructs a JSException with a detail message and all the + * other info that usually comes with a JavaScript error. + * @param s the detail message + */ + public JSException(String s, String filename, int lineno, + String source, int tokenIndex) { + super(s); + this.filename = filename; + this.lineno = lineno; + this.source = source; + this.tokenIndex = tokenIndex; + } +} + diff --git a/mozilla/js/src/liveconnect/classes/netscape/javascript/JSObject.java b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSObject.java new file mode 100644 index 00000000000..883ada8a947 --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSObject.java @@ -0,0 +1,150 @@ +/* -*- Mode: C; tab-width: 4; -*- */ + +/* Insert copyright and license here 19** */ + +/* more doc todo: + * threads + * gc + * + * + */ + +package netscape.javascript; + +import java.applet.Applet; + +/** + * JSObject allows Java to manipulate objects that are + * defined in JavaScript. + * Values passed from Java to JavaScript are converted as + * follows:
      + *
    • JSObject is converted to the original JavaScript object + *
    • Any other Java object is converted to a JavaScript wrapper, + * which can be used to access methods and fields of the java object. + * Converting this wrapper to a string will call the toString method + * on the original object, converting to a number will call the + * floatValue method if possible and fail otherwise. Converting + * to a boolean will try to call the booleanValue method in the + * same way. + *
    • Java arrays are wrapped with a JavaScript object that understands + * array.length and array[index] + *
    • A Java boolean is converted to a JavaScript boolean + *
    • Java byte, char, short, int, long, float, and double are converted + * to JavaScript numbers + *
    + * Values passed from JavaScript to Java are converted as follows:
      + *
    • objects which are wrappers around java objects are unwrapped + *
    • other objects are wrapped with a JSObject + *
    • strings, numbers and booleans are converted to String, Float, + * and Boolean objects respectively + *
    + * This means that all JavaScript values show up as some kind + * of java.lang.Object in Java. In order to make much use of them, + * you will have to cast them to the appropriate subclass of Object, + * e.g. (String) window.getMember("name"); or + * (JSObject) window.getMember("document");. + */ +public final class JSObject { + /* the internal object data */ + private int internal; + + /** + * initialize + */ + private static native void initClass(); + static { + // On MRJ, this property won't exist, because the library is preloaded. + String liveConnectLibrary = System.getProperty("netscape.jsj.dll", null); + if (liveConnectLibrary != null) { + System.loadLibrary(liveConnectLibrary); + initClass(); + } + } + + /** + * it is illegal to construct a JSObject manually + */ + private JSObject(int jsobj_addr) { + internal = jsobj_addr; + } + + /** + * Retrieves a named member of a JavaScript object. + * Equivalent to "this.name" in JavaScript. + */ + public native Object getMember(String name); + + /** + * Retrieves an indexed member of a JavaScript object. + * Equivalent to "this[index]" in JavaScript. + */ +// public Object getMember(int index) { return getSlot(index); } + public native Object getSlot(int index); + + /** + * Sets a named member of a JavaScript object. + * Equivalent to "this.name = value" in JavaScript. + */ + public native void setMember(String name, Object value); + + /** + * Sets an indexed member of a JavaScript object. + * Equivalent to "this[index] = value" in JavaScript. + */ +// public void setMember(int index, Object value) { +// setSlot(index, value); +// } + public native void setSlot(int index, Object value); + + /** + * Removes a named member of a JavaScript object. + */ + public native void removeMember(String name); + + /** + * Calls a JavaScript method. + * Equivalent to "this.methodName(args[0], args[1], ...)" in JavaScript. + */ + public native Object call(String methodName, Object args[]); + + /** + * Evaluates a JavaScript expression. The expression is a string + * of JavaScript source code which will be evaluated in the context + * given by "this". + */ + public native Object eval(String s); + + /** + * Converts a JSObject to a String. + */ + public native String toString(); + + // should use some sort of identifier rather than String + // is "property" the right word? + // native String[] listProperties(); + + + /** + * get a JSObject for the window containing the given applet + */ + public static native JSObject getWindow(Applet applet); + + /** + * Finalization decrements the reference count on the corresponding + * JavaScript object. + */ + protected native void finalize(); + + /** + * Override java.lang.Object.equals() because identity is not preserved + * with instances of JSObject. + */ + public boolean equals(Object obj) { + JSObject jsobj; + + if (!(obj instanceof JSObject)) + return false; + jsobj = (JSObject)obj; + return (internal == jsobj.internal); + } +} diff --git a/mozilla/js/src/liveconnect/classes/netscape/javascript/JSProxy.java b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSProxy.java new file mode 100644 index 00000000000..ee266c4a538 --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSProxy.java @@ -0,0 +1,37 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ +/* ** */ +/** + * The JSProxy interface allows applets and plugins to + * share javascript contexts. + */ + +package netscape.javascript; +import java.applet.Applet; + +public interface JSProxy { + Object getMember(JSObject jso, String name); + Object getSlot(JSObject jso, int index); + void setMember(JSObject jso, String name, Object value); + void setSlot(JSObject jso, int index, Object value); + void removeMember(JSObject jso, String name); + Object call(JSObject jso, String methodName, Object args[]); + Object eval(JSObject jso, String s); + String toString(JSObject jso); + JSObject getWindow(Applet applet); +} diff --git a/mozilla/js/src/liveconnect/classes/netscape/javascript/JSRunnable.java b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSRunnable.java new file mode 100644 index 00000000000..d9dae63a2e8 --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSRunnable.java @@ -0,0 +1,31 @@ +package netscape.javascript; + +/** + * Runs a JavaScript object with a run() method in a separate thread. + */ +public class JSRunnable implements Runnable { + private JSObject runnable; + + public JSRunnable(JSObject runnable) { + this.runnable = runnable; + synchronized(this) { + new Thread(this).start(); + try { + this.wait(); + } catch (InterruptedException ie) { + } + } + } + + public void run() { + try { + runnable.call("run", null); + synchronized(this) { + notifyAll(); + } + } catch (Throwable t) { + System.err.println(t); + t.printStackTrace(System.err); + } + } +} diff --git a/mozilla/js/src/liveconnect/classes/netscape/javascript/JSUtil.java b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSUtil.java new file mode 100644 index 00000000000..6d3cab84048 --- /dev/null +++ b/mozilla/js/src/liveconnect/classes/netscape/javascript/JSUtil.java @@ -0,0 +1,38 @@ +/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ +/* ** */ + +package netscape.javascript; +import java.io.*; + +public class JSUtil { + + /* Return the stack trace of an exception or error as a String */ + public static String getStackTrace(Throwable t) { + ByteArrayOutputStream captureStream; + PrintStream p; + + captureStream = new ByteArrayOutputStream(); + p = new PrintStream(captureStream); + + t.printStackTrace(p); + p.flush(); + + return captureStream.toString(); + } +} diff --git a/mozilla/js/src/liveconnect/jsj.c b/mozilla/js/src/liveconnect/jsj.c new file mode 100644 index 00000000000..75fc8f075dc --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj.c @@ -0,0 +1,801 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the top-level initialization code and the implementation of the + * public API. + * + */ + +#include +#include +#include "prtypes.h" +#include "prlog.h" +#include "prprf.h" + +#ifdef XP_MAC +#include "prosdep.h" +#endif + +#include "jsj_private.h" /* LiveConnect internals */ +#include "jsjava.h" /* LiveConnect external API */ + +/* + * At certain times during initialization, there may be no JavaScript context + * available to direct error reports to, in which case the error messages + * are sent to this function. The caller is responsible for free'ing + * the js_error_msg argument. + */ +static void +report_java_initialization_error(JNIEnv *jEnv, const char *js_error_msg) +{ + const char *error_msg, *java_error_msg; + + java_error_msg = NULL; + + if (jEnv) { + java_error_msg = jsj_GetJavaErrorMessage(jEnv); + (*jEnv)->ExceptionClear(jEnv); + } + + if (java_error_msg) { + error_msg = PR_smprintf("initialization error: %s (%s)\n", + js_error_msg, java_error_msg); + free((void*)java_error_msg); + } else { + error_msg = PR_smprintf("initialization error: %s\n", + js_error_msg); + } + + jsj_LogError(error_msg); +} + +/* + * Opaque JVM handles to Java classes and methods required for Java reflection. + * These are computed and cached during initialization. + */ + +jclass jlObject; /* java.lang.Object */ +jclass jlrMethod; /* java.lang.reflect.Method */ +jclass jlrField; /* java.lang.reflect.Field */ +jclass jlVoid; /* java.lang.Void */ +jclass jlrConstructor; /* java.lang.reflect.Constructor */ +jclass jlThrowable; /* java.lang.Throwable */ +jclass jlSystem; /* java.lang.System */ +jclass jlClass; /* java.lang.Class */ +jclass jlBoolean; /* java.lang.Boolean */ +jclass jlDouble; /* java.lang.Double */ +jclass jlString; /* java.lang.String */ +jclass njJSObject; /* netscape.javascript.JSObject */ +jclass njJSException; /* netscape.javascript.JSException */ +jclass njJSUtil; /* netscape.javascript.JSUtil */ + +jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */ +jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */ +jmethodID jlClass_getFields; /* java.lang.Class.getFields() */ +jmethodID jlClass_getName; /* java.lang.Class.getName() */ +jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */ +jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */ +jmethodID jlClass_isArray; /* java.lang.Class.isArray() */ + +jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */ +jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */ +jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */ +jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */ + +jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */ +jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */ + +jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */ +jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */ +jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */ + +jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */ +jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */ +jmethodID jlDouble_Double; /* java.lang.Double constructor */ +jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */ + +jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */ +jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */ + +jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */ + +jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */ + +jmethodID njJSException_JSException; /* netscape.javascript.JSexception constructor */ +jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */ +jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */ +jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */ +jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */ +jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */ +jfieldID njJSException_source; /* netscape.javascript.JSException.source */ +jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */ + +/* Obtain a reference to a Java class */ +#define LOAD_CLASS(qualified_name, class) \ + { \ + jclass _##class = (*jEnv)->FindClass(jEnv, #qualified_name); \ + if (_##class == 0) { \ + report_java_initialization_error(jEnv, \ + "Can't load class " #qualified_name); \ + return JS_FALSE; \ + } \ + class = (*jEnv)->NewGlobalRef(jEnv, _##class); \ + } + +/* Obtain a methodID reference to a Java method or constructor */ +#define _LOAD_METHOD(qualified_class, method, mvar, signature, class, is_static)\ + if (is_static) { \ + class##_##mvar = \ + (*jEnv)->GetStaticMethodID(jEnv, class, #method, signature); \ + } else { \ + class##_##mvar = \ + (*jEnv)->GetMethodID(jEnv, class, #method, signature); \ + } \ + if (class##_##mvar == 0) { \ + report_java_initialization_error(jEnv, \ + "Can't get mid for " #qualified_class "." #method "()"); \ + return JS_FALSE; \ + } + +/* Obtain a methodID reference to a Java instance method */ +#define LOAD_METHOD(qualified_class, method, signature, class) \ + _LOAD_METHOD(qualified_class, method, method, signature, class, JS_FALSE) + +/* Obtain a methodID reference to a Java static method */ +#define LOAD_STATIC_METHOD(qualified_class, method, signature, class) \ + _LOAD_METHOD(qualified_class, method, method, signature, class, JS_TRUE) + +/* Obtain a methodID reference to a Java constructor */ +#define LOAD_CONSTRUCTOR(qualified_class, method, signature, class) \ + _LOAD_METHOD(qualified_class,, method, signature, class, JS_FALSE) + +/* Obtain a fieldID reference to a Java instance or static field */ +#define _LOAD_FIELDID(qualified_class, field, signature, class, is_static) \ + if (is_static) { \ + class##_##field = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\ + } else { \ + class##_##field = (*jEnv)->GetFieldID(jEnv, class, #field, signature);\ + } \ + if (class##_##field == 0) { \ + report_java_initialization_error(jEnv, \ + "Can't get fid for " #qualified_class "." #field); \ + return JS_FALSE; \ + } + +/* Obtain a fieldID reference to a Java instance field */ +#define LOAD_FIELDID(qualified_class, field, signature, class) \ + _LOAD_FIELDID(qualified_class, field, signature, class, JS_FALSE) + +/* Obtain the value of a static field in a Java class */ +#define LOAD_FIELD_VAL(qualified_class, field, signature, class, type) \ + { \ + jfieldID field_id; \ + field_id = (*jEnv)->GetStaticFieldID(jEnv, class, #field, signature);\ + if (field_id == 0) { \ + report_java_initialization_error(jEnv, \ + "Can't get fid for " #qualified_class "." #field); \ + return JS_FALSE; \ + } \ + class##_##field = \ + (*jEnv)->GetStatic##type##Field(jEnv, class, field_id); \ + if (class##_##field == 0) { \ + report_java_initialization_error(jEnv, \ + "Can't read static field " #qualified_class "." #field); \ + return JS_FALSE; \ + } \ + } + +/* Obtain the value of a static field in a Java class, which is known to + contain an object value. */ +#define LOAD_FIELD_OBJ(qualified_class, field, signature, class) \ + LOAD_FIELD_VAL(qualified_class, field, signature, class, Object); \ + class##_##field = (*jEnv)->NewGlobalRef(jEnv, class##_##field); + +/* + * Load the Java classes, and the method and field descriptors required for Java reflection. + * Returns JS_TRUE on success, JS_FALSE on failure. + */ +static JSBool +init_java_VM_reflection(JSJavaVM *jsjava_vm, JNIEnv *jEnv) +{ + /* Load Java system classes and method, including java.lang.reflect classes */ + LOAD_CLASS(java/lang/Object, jlObject); + LOAD_CLASS(java/lang/Class, jlClass); + LOAD_CLASS(java/lang/reflect/Method, jlrMethod); + LOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor); + LOAD_CLASS(java/lang/reflect/Field, jlrField); + LOAD_CLASS(java/lang/Throwable, jlThrowable); + LOAD_CLASS(java/lang/System, jlSystem); + LOAD_CLASS(java/lang/Boolean, jlBoolean); + LOAD_CLASS(java/lang/Double, jlDouble); + LOAD_CLASS(java/lang/String, jlString); + LOAD_CLASS(java/lang/Void, jlVoid); + + LOAD_METHOD(java.lang.Class, getMethods, "()[Ljava/lang/reflect/Method;",jlClass); + LOAD_METHOD(java.lang.Class, getConstructors, "()[Ljava/lang/reflect/Constructor;",jlClass); + LOAD_METHOD(java.lang.Class, getFields, "()[Ljava/lang/reflect/Field;", jlClass); + LOAD_METHOD(java.lang.Class, getName, "()Ljava/lang/String;", jlClass); + LOAD_METHOD(java.lang.Class, isArray, "()Z", jlClass); + LOAD_METHOD(java.lang.Class, getComponentType, "()Ljava/lang/Class;", jlClass); + LOAD_METHOD(java.lang.Class, getModifiers, "()I", jlClass); + + LOAD_METHOD(java.lang.reflect.Method, getName, "()Ljava/lang/String;", jlrMethod); + LOAD_METHOD(java.lang.reflect.Method, getParameterTypes, "()[Ljava/lang/Class;", jlrMethod); + LOAD_METHOD(java.lang.reflect.Method, getReturnType, "()Ljava/lang/Class;", jlrMethod); + LOAD_METHOD(java.lang.reflect.Method, getModifiers, "()I", jlrMethod); + + LOAD_METHOD(java.lang.reflect.Constructor, getParameterTypes, "()[Ljava/lang/Class;", jlrConstructor); + LOAD_METHOD(java.lang.reflect.Constructor, getModifiers, "()I", jlrConstructor); + + LOAD_METHOD(java.lang.reflect.Field, getName, "()Ljava/lang/String;", jlrField); + LOAD_METHOD(java.lang.reflect.Field, getType, "()Ljava/lang/Class;", jlrField); + LOAD_METHOD(java.lang.reflect.Field, getModifiers, "()I", jlrField); + + LOAD_METHOD(java.lang.Throwable, toString, "()Ljava/lang/String;", jlThrowable); + LOAD_METHOD(java.lang.Throwable, getMessage, "()Ljava/lang/String;", jlThrowable); + + LOAD_METHOD(java.lang.Double, doubleValue, "()D", jlDouble); + + LOAD_METHOD(java.lang.Boolean, booleanValue, "()Z", jlBoolean); + + LOAD_STATIC_METHOD(java.lang.System, identityHashCode, "(Ljava/lang/Object;)I", jlSystem); + + LOAD_CONSTRUCTOR(java.lang.Boolean, Boolean, "(Z)V", jlBoolean); + LOAD_CONSTRUCTOR(java.lang.Double, Double, "(D)V", jlDouble); + + LOAD_FIELD_OBJ(java.lang.Void, TYPE, "Ljava/lang/Class;", jlVoid); + + return JS_TRUE; +} + +#if XP_MAC + +/** + * Workaround for the fact that MRJ loads a different instance of the shared library. + */ + +#include "netscape_javascript_JSObject.h" + +static JSObject_RegisterNativeMethods(JNIEnv* jEnv) +{ + // Manually load the required native methods. + static JNINativeMethod nativeMethods[] = { + "initClass", "()V", (void*)&Java_netscape_javascript_JSObject_initClass, + "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, + }; + (*jEnv)->RegisterNatives(jEnv, njJSObject, nativeMethods, sizeof(nativeMethods) / sizeof(JNINativeMethod)); + + // call the initClass method, since we nailed the static initializer for testing. + Java_netscape_javascript_JSObject_initClass(jEnv, njJSObject); +} + +#endif + +/* Load Netscape-specific Java extension classes, methods, and fields */ +static JSBool +init_netscape_java_classes(JSJavaVM *jsjava_vm, JNIEnv *jEnv) +{ + LOAD_CLASS(netscape/javascript/JSObject, njJSObject); + LOAD_CLASS(netscape/javascript/JSException, njJSException); + LOAD_CLASS(netscape/javascript/JSUtil, njJSUtil); + +#if XP_MAC + JSObject_RegisterNativeMethods(jEnv); +#endif + + LOAD_CONSTRUCTOR(netscape.javascript.JSObject, + JSObject, "(I)V", njJSObject); + LOAD_CONSTRUCTOR(netscape.javascript.JSException, + JSException, "(Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;I)V", + njJSException); + LOAD_FIELDID(netscape.javascript.JSObject, + internal, "I", njJSObject); + LOAD_FIELDID(netscape.javascript.JSException, + lineno, "I", njJSException); + LOAD_FIELDID(netscape.javascript.JSException, + tokenIndex, "I", njJSException); + LOAD_FIELDID(netscape.javascript.JSException, + source, "Ljava/lang/String;", njJSException); + LOAD_FIELDID(netscape.javascript.JSException, + filename, "Ljava/lang/String;", njJSException); + + LOAD_STATIC_METHOD(netscape.javascript.JSUtil, + getStackTrace, "(Ljava/lang/Throwable;)Ljava/lang/String;", + njJSUtil); + + return JS_TRUE; +} + +JSJavaVM *jsjava_vm_list = NULL; + +/* + * Called once per Java VM, this function initializes the classes, fields, and + * methods required for Java reflection. If java_vm is NULL, a new Java VM is + * created, using the provided classpath in addition to any default classpath. + * The classpath argument is ignored, however, if java_vm_arg is non-NULL. + */ +JSJavaVM * +JSJ_ConnectToJavaVM(JavaVM *java_vm_arg, const char *user_classpath) +{ + JavaVM *java_vm; + JSJavaVM *jsjava_vm; + JNIEnv *jEnv; + + jsjava_vm = (JSJavaVM*)malloc(sizeof(JSJavaVM)); + if (!jsjava_vm) + return NULL; + memset(jsjava_vm, 0, sizeof(JSJavaVM)); + + java_vm = java_vm_arg; + + /* If a Java VM was passed in, try to attach to it on the current thread. */ + if (java_vm) { + if ((*java_vm)->AttachCurrentThread(java_vm, &jEnv, NULL) < 0) { + jsj_LogError("Failed to attach to Java VM thread\n"); + free(jsjava_vm); + return NULL; + } + } else if ( JSJ_callbacks->get_java_vm != NULL ) { + char* err_msg = NULL; + java_vm = JSJ_callbacks->get_java_vm(&err_msg); + PR_ASSERT( java_vm ); + if (java_vm && (*java_vm)->AttachCurrentThread(java_vm, &jEnv, NULL) < 0) { + jsj_LogError("Failed to attach to Java VM thread\n"); + free(jsjava_vm); + return NULL; + } + } +#ifndef OJI + else { + /* No Java VM supplied, so create our own */ + JDK1_1InitArgs vm_args; + + /* Magic constant indicates JRE version 1.1 */ + vm_args.version = 0x00010001; + JNI_GetDefaultJavaVMInitArgs(&vm_args); + + /* Prepend the classpath argument to the default JVM classpath */ + if (user_classpath) { + const char *full_classpath = PR_smprintf("%s;%s", user_classpath, vm_args.classpath); + if (!full_classpath) { + free(jsjava_vm); + return NULL; + } + vm_args.classpath = (char*)full_classpath; + } + + /* Attempt to create our own VM */ + if (JNI_CreateJavaVM(&java_vm, &jEnv, &vm_args) < 0) { + jsj_LogError("Failed to create Java VM\n"); + free(jsjava_vm); + return NULL; + } + + /* Remember that we created the VM so that we know to destroy it later */ + jsjava_vm->jsj_created_java_vm = JS_TRUE; + } +#endif /* !OJI */ + jsjava_vm->java_vm = java_vm; + jsjava_vm->main_thread_env = jEnv; + + /* Load the Java classes, and the method and field descriptors required for + Java reflection. */ + if (!init_java_VM_reflection(jsjava_vm, jEnv)) { + JSJ_DisconnectFromJavaVM(jsjava_vm); + return NULL; + } + + /* + * JVM initialization for netscape.javascript.JSObject is performed + * independently of the other classes that are initialized in + * init_java_VM_reflection, because we allow it to fail. In the case + * of failure, LiveConnect is still operative, but only when calling + * from JS to Java and not vice-versa. + */ + init_netscape_java_classes(jsjava_vm, jEnv); + + /* Put this VM on the list of all created VMs */ + jsjava_vm->next = jsjava_vm_list; + jsjava_vm_list = jsjava_vm; + + return jsjava_vm; +} + +JSJCallbacks *JSJ_callbacks = NULL; + +/* Called once to set up callbacks for all instances of LiveConnect */ +void +JSJ_Init(JSJCallbacks *callbacks) +{ + PR_ASSERT(callbacks); + JSJ_callbacks = callbacks; +} + +/* + * Initialize the provided JSContext by setting up the JS classes necessary for + * reflection and by defining JavaPackage objects for the default Java packages + * as properties of global_obj. Additional packages may be pre-defined by + * setting the predefined_packages argument. (Pre-defining a Java package at + * initialization time is not necessary, but it will make package lookup faster + * and, more importantly, will avoid unnecessary network accesses if classes + * are being loaded over the network.) + */ +JSBool +JSJ_InitJSContext(JSContext *cx, JSObject *global_obj, + JavaPackageDef *predefined_packages) +{ + /* Initialize the JavaScript classes used for reflection */ + if (!jsj_init_JavaObject(cx, global_obj)) + return JS_FALSE; + +/* if (!jsj_init_JavaMember(cx, global_obj)) + return JS_FALSE; */ + + if (!jsj_init_JavaPackage(cx, global_obj, predefined_packages)) + return JS_FALSE; + + if (!jsj_init_JavaClass(cx, global_obj)) + return JS_FALSE; + + if (!jsj_init_JavaArray(cx, global_obj)) + return JS_FALSE; + + return JS_TRUE; +} + +/* Eliminate a reference to a Java class */ +#define UNLOAD_CLASS(qualified_name, class) \ + if (class) { \ + (*jEnv)->DeleteGlobalRef(jEnv, class); \ + class = NULL; \ + } + +/* + * This routine severs the connection to a Java VM, freeing all related resources. + * It shouldn't be called until the global scope has been cleared in all related + * JSContexts (so that all LiveConnect objects are finalized) and a JavaScript + * GC is performed. Otherwise, accessed to free'ed memory could result. + */ +void +JSJ_DisconnectFromJavaVM(JSJavaVM *jsjava_vm) +{ + JNIEnv *jEnv; + JavaVM *java_vm; + + java_vm = jsjava_vm->java_vm; + (*java_vm)->AttachCurrentThread(java_vm, &jEnv, NULL); + + /* Drop all references to Java objects and classes */ + jsj_DiscardJavaObjReflections(jEnv); + jsj_DiscardJavaClassReflections(jEnv); + + if (jsjava_vm->jsj_created_java_vm) { + (*java_vm)->DestroyJavaVM(java_vm); + } else { + UNLOAD_CLASS(java/lang/Object, jlObject); + UNLOAD_CLASS(java/lang/Class, jlClass); + UNLOAD_CLASS(java/lang/reflect/Method, jlrMethod); + UNLOAD_CLASS(java/lang/reflect/Constructor, jlrConstructor); + UNLOAD_CLASS(java/lang/reflect/Field, jlrField); + UNLOAD_CLASS(java/lang/Throwable, jlThrowable); + UNLOAD_CLASS(java/lang/System, jlSystem); + UNLOAD_CLASS(java/lang/Boolean, jlBoolean); + UNLOAD_CLASS(java/lang/Double, jlDouble); + UNLOAD_CLASS(java/lang/String, jlString); + UNLOAD_CLASS(java/lang/Void, jlVoid); + UNLOAD_CLASS(netscape/javascript/JSObject, njJSObject); + UNLOAD_CLASS(netscape/javascript/JSException, njJSException); + UNLOAD_CLASS(netscape/javascript/JSUtil, njJSUtil); + } +} + +static JSJavaThreadState *thread_list = NULL; + +static JSJavaThreadState * +new_jsjava_thread_state(JSJavaVM *jsjava_vm, const char *thread_name, JNIEnv *jEnv) +{ + JSJavaThreadState *jsj_env; + + jsj_env = (JSJavaThreadState *)malloc(sizeof(JSJavaThreadState)); + if (!jsj_env) + return NULL; + memset(jsj_env, 0, sizeof(JSJavaThreadState)); + + jsj_env->jEnv = jEnv; + jsj_env->jsjava_vm = jsjava_vm; + if (thread_name) + jsj_env->name = strdup(thread_name); + + /* THREADSAFETY - need to protect against races */ + jsj_env->next = thread_list; + thread_list = jsj_env; + + return jsj_env; +} + +static JSJavaThreadState * +find_jsjava_thread(JNIEnv *jEnv) +{ + JSJavaThreadState *e, **p, *jsj_env; + jsj_env = NULL; + + /* THREADSAFETY - need to protect against races in manipulating the thread list */ + + /* Search for the thread state among the list of all created + LiveConnect threads */ + for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) { + if (e->jEnv == jEnv) { + jsj_env = e; + *p = jsj_env->next; + break; + } + } + + /* Move a found thread to head of list for faster search next time. */ + if (jsj_env) + thread_list = jsj_env; + + return jsj_env; +} + +PR_IMPLEMENT(JSJavaThreadState *) +JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *name, JNIEnv **java_envp) +{ + JNIEnv *jEnv; + JavaVM *java_vm; + JSJavaThreadState *jsj_env; + + /* Try to attach a Java thread to the current native thread */ + java_vm = jsjava_vm->java_vm; + if ((*java_vm)->AttachCurrentThread(java_vm, &jEnv, NULL) < 0) + return NULL; + + /* If we found an existing thread state, just return it. */ + jsj_env = find_jsjava_thread(jEnv); + if (jsj_env) + return jsj_env; + + /* Create a new wrapper around the thread/VM state */ + jsj_env = new_jsjava_thread_state(jsjava_vm, name, jEnv); + + if (java_envp) + *java_envp = jEnv; + return jsj_env; +} + +static JSJavaVM * +map_java_vm_to_jsjava_vm(JavaVM *java_vm) +{ + JSJavaVM *v; + for (v = jsjava_vm_list; v; v = v->next) { + if (v->java_vm == java_vm) + return v; + } + return NULL; +} + +/* + * Unfortunately, there's no standard means to associate any private data with + * a JNI thread environment, so we need to use the Java environment pointer as + * the key in a lookup table that maps it to a JSJavaThreadState structure, + * where we store all our per-thread private data. If no existing thread state + * is found, a new one is created. + * + * If an error occurs, returns NULL and sets the errp argument to an error + * message, which the caller is responsible for free'ing. + */ +JSJavaThreadState * +jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp) +{ + JSJavaThreadState *jsj_env; + JavaVM *java_vm; + JSJavaVM *jsjava_vm; + + /* If we found an existing thread state, just return it. */ + jsj_env = find_jsjava_thread(jEnv); + if (jsj_env) + return jsj_env; + + /* No one set up a LiveConnect thread state for a given Java thread. + Invoke the callback to create one on-the-fly. */ + + /* First, figure out which Java VM is calling us */ + if ((*jEnv)->GetJavaVM(jEnv, &java_vm) < 0) + return NULL; + + /* Get our private JavaVM data */ + jsjava_vm = map_java_vm_to_jsjava_vm(java_vm); + if (!jsjava_vm) { + *errp = PR_smprintf("Total weirdness: No JSJavaVM wrapper ever created " + "for JavaVM 0x%08x", java_vm); + return NULL; + } + + jsj_env = new_jsjava_thread_state(jsjava_vm, NULL, jEnv); + if (!jsj_env) + return NULL; + + return jsj_env; +} + +/* + * This function is used to specify a particular JSContext as *the* JavaScript + * execution environment to be used when LiveConnect is accessed from the given + * Java thread, i.e. by using one of the methods of netscape.javascript.JSObject. + * (There can only be one such JS context for a given Java thread. To + * multiplex JSContexts among a single thread, this function must be called + * before Java is invoked on that thread.) The return value is the previous + * context associated with the given Java thread. + */ +PR_IMPLEMENT(JSContext *) +JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env) +{ + JSContext *old_context; + old_context = jsj_env->cx; + jsj_env->cx = cx; + return old_context; +} + +PR_IMPLEMENT(JSBool) +JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env) +{ + JavaVM *java_vm; + JSJavaThreadState *e, **p; + + /* Disassociate the current native thread from its corresponding Java thread */ + java_vm = jsj_env->jsjava_vm->java_vm; + if ((*java_vm)->DetachCurrentThread(java_vm) < 0) + return JS_FALSE; + + /* Destroy the LiveConnect execution environment passed in */ + jsj_ClearPendingJSErrors(jsj_env); + + /* THREADSAFETY - need to protect against races */ + for (p = &thread_list; (e = *p) != NULL; p = &(e->next)) { + if (e == jsj_env) { + *p = jsj_env->next; + break; + } + } + + free(jsj_env); + return JS_TRUE; +} + +JSBool +JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp) +{ + JNIEnv *jEnv; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, vp); + return JS_TRUE; +} + +/*===========================================================================*/ + +#ifndef MOZILLA_CLIENT + +/* The convenience functions below present a complete, but simplified + LiveConnect API which is designed to handle the special case of a single + Java-VM, single-threaded operation, and use of only one JSContext. */ + +/* We can get away with global variables in our single-threaded, + single-JSContext case. */ +static JSJavaVM * the_jsj_vm = NULL; +static JSContext * the_cx = NULL; +static JSJavaThreadState * the_jsj_thread = NULL; +static JSObject * the_global_js_obj = NULL; + +/* Trivial implementation of callback function */ +static JSJavaThreadState * +default_map_js_context_to_jsj_thread(JSContext *cx, char **errp) +{ + return the_jsj_thread; +} + +/* Trivial implementation of callback function */ +static JSContext * +default_map_jsj_thread_to_js_context(JNIEnv *jEnv, char **errp) +{ + return the_cx; +} + +/* Trivial implementation of callback function */ +static JSObject * +default_map_java_object_to_js_object(JNIEnv *jEnv, jobject hint, char **errp) +{ + return the_global_js_obj; +} + +/* Trivial implementations of callback functions */ +JSJCallbacks jsj_default_callbacks = { + default_map_jsj_thread_to_js_context, + default_map_js_context_to_jsj_thread, + default_map_java_object_to_js_object +}; + +/* + * Initialize the provided JSContext by setting up the JS classes necessary for + * reflection and by defining JavaPackage objects for the default Java packages + * as properties of global_obj. If java_vm is NULL, a new Java VM is + * created, using the provided classpath in addition to any default classpath. + * The classpath argument is ignored, however, if java_vm is non-NULL. + */ +JSBool +JSJ_SimpleInit(JSContext *cx, JSObject *global_obj, JavaVM *java_vm, const char *classpath) +{ + JNIEnv *jEnv; + + PR_ASSERT(!the_jsj_vm); + the_jsj_vm = JSJ_ConnectToJavaVM(java_vm, classpath); + if (!the_jsj_vm) + return JS_FALSE; + + JSJ_Init(&jsj_default_callbacks); + + if (!JSJ_InitJSContext(cx, global_obj, NULL)) + goto error; + the_cx = cx; + the_global_js_obj = global_obj; + + the_jsj_thread = JSJ_AttachCurrentThreadToJava(the_jsj_vm, "main thread", &jEnv); + if (!the_jsj_thread) + goto error; + + return JS_TRUE; + +error: + JSJ_SimpleShutdown(); + return JS_FALSE; +} + +/* + * Free up all LiveConnect resources. Destroy the Java VM if it was + * created by LiveConnect. + */ +PR_IMPLEMENT(void) +JSJ_SimpleShutdown() +{ + PR_ASSERT(the_jsj_vm); + JSJ_DisconnectFromJavaVM(the_jsj_vm); + the_jsj_vm = NULL; + the_cx = NULL; + the_global_js_obj = NULL; + the_jsj_thread = NULL; +} + +#endif /* MOZILLA_CLIENT */ diff --git a/mozilla/js/src/liveconnect/jsj1640.rc b/mozilla/js/src/liveconnect/jsj1640.rc new file mode 100644 index 00000000000..49e732e1873 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj1640.rc @@ -0,0 +1,76 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +// Version stamp for this .DLL + +#include + +#include + + + +VS_VERSION_INFO VERSIONINFO + + FILEVERSION 4 // major, minor, release (alpha 1), build # + + PRODUCTVERSION 4 + + FILEFLAGSMASK 0 + + FILEFLAGS 0 // final version + + FILEOS VOS_DOS_WINDOWS16 + + FILETYPE VFT_DLL + + FILESUBTYPE 0 // not used + +BEGIN + + BLOCK "StringFileInfo" + + BEGIN + + BLOCK "040904E4" // Lang=US English, CharSet=Windows Multilingual + + BEGIN + + VALUE "CompanyName", "Netscape Communications Corporation\0" + + VALUE "FileDescription", "Netscape 16-bit JavaScript-Java Module\0" + + VALUE "FileVersion", "4.0\0" + + VALUE "InternalName", "JSJ1640\0" + + VALUE "LegalCopyright", "Copyright Netscape Communications. 1994-96\0" + + VALUE "LegalTrademarks", "Netscape, Mozilla\0" + + VALUE "OriginalFilename","JSJ1640.DLL\0" + + VALUE "ProductName", "NETSCAPE\0" + + VALUE "ProductVersion", "4.0\0" + + END + + END + +END + diff --git a/mozilla/js/src/liveconnect/jsj_JSObject.c b/mozilla/js/src/liveconnect/jsj_JSObject.c new file mode 100644 index 00000000000..c5ea30bdcb3 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_JSObject.c @@ -0,0 +1,1137 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the implementation of the native methods for the + * netscape.javascript.JSObject Java class, which are used for calling into + * JavaScript from Java. It also contains the code that handles propagation + * of exceptions both into and out of Java. + * + */ + +#include +#include +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#ifdef XP_MAC +#include "prosdep.h" +#endif + +#include "jsj_private.h" +#include "jsjava.h" + +#include "jscntxt.h" /* For js_ReportErrorAgain(). + TODO - get rid of private header */ + +#include "netscape_javascript_JSObject.h" /* javah-generated headers */ + + +/* A captured JavaScript error, created when JS_ReportError() is called while + running JavaScript code that is itself called from Java. */ +struct CapturedJSError { + char * message; + JSErrorReport report; /* Line # of error, etc. */ + jthrowable java_exception; /* Java exception, error, or null */ + CapturedJSError * next; /* Next oldest captured JS error */ +}; + + +/*********************** Reflection of JSObjects ****************************/ + +/* + * This is a hash table that maps from JS objects to Java objects. + * It is used to ensure that the same Java object results when a JS + * object is reflected more than once, so that Java object equality + * tests work in the expected manner. + * + * The entry keys are JSObject pointers and the entry values are Java objects + * (of type jobject). When the corresponding Java instance is finalized, + * the entry is removed from the table, and a JavaScript GC root for the JS + * object is removed. + */ +static PRHashTable *js_obj_reflections = NULL; + +#ifdef JS_THREADSAFE +/* + * Used to protect the js_obj_reflections hashtable from simultaneous + * read/write or * write/write access. + */ +static PRMonitor *js_obj_reflections_monitor = NULL; +#endif + +static JSBool +init_js_obj_reflections_table() +{ + js_obj_reflections = PR_NewHashTable(128, NULL, PR_CompareValues, + PR_CompareValues, NULL, NULL); + if (!js_obj_reflections) + return JS_FALSE; + +#ifdef JS_THREADSAFE + js_obj_reflections_monitor = PR_NewNamedMonitor("js_obj_reflections"); + if (!js_obj_reflections_monitor) { + PR_HashTableDestroy(js_obj_reflections); + return JS_FALSE; + } +#endif + + return JS_TRUE; +} + +/* + * Return a Java object that "wraps" a given JS object by storing the address + * of the JS object in a private field of the Java object. A hash table is + * used to ensure that the mapping of JS objects to Java objects is done on + * one-to-one basis. + * + * If an error occurs, returns NULL and reports an error. + */ +jobject +jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj) +{ + jobject java_wrapper_obj; + PRHashEntry *he, **hep; + + java_wrapper_obj = NULL; + +#ifdef JS_THREADSAFE + PR_EnterMonitor(js_obj_reflections_monitor); +#endif + + /* First, look in the hash table for an existing reflection of the same + JavaScript object. If one is found, return it. */ + hep = PR_HashTableRawLookup(js_obj_reflections, (PRHashNumber)js_obj, js_obj); + +#ifdef PRESERVE_JSOBJECT_IDENTITY + /* If the same JSObject is reflected into Java more than once then we should + return the same Java object, both for efficiency and so that the '==' + operator works as expected in Java when comparing two JSObjects. + However, it is not possible to hold a reference to a Java object without + inhibiting GC of that object, at least not in a way that is portable + to all vendor's JVM, i.e. a weak reference. So, for now, JSObject identity + is broken. */ + + he = *hep; + if (he) { + java_wrapper_obj = (jobject)he->value; + PR_ASSERT(java_wrapper_obj); + if (java_wrapper_obj) + goto done; + } +#endif /* PRESERVE_JSOBJECT_IDENTITY */ + + /* No existing reflection found, so create a new Java object that wraps + the JavaScript object by storing its address in a private integer field. */ + java_wrapper_obj = + (*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (jint)js_obj); + if (!java_wrapper_obj) { + jsj_UnexpectedJavaError(cx, jEnv, "Couldn't create new instance of " + "netscape.javascript.JSObject"); + goto done; + } + + /* Add the new reflection to the hash table. */ + he = PR_HashTableRawAdd(js_obj_reflections, hep, (PRHashNumber)js_obj, + js_obj, java_wrapper_obj); + if (he) { + /* Tell the JavaScript GC about this object since the only reference + to it may be in Java-land. */ + JS_AddRoot(cx, (void*)&he->key); + } else { + JS_ReportOutOfMemory(cx); + /* No need to delete java_wrapper_obj because Java GC will reclaim it */ + java_wrapper_obj = NULL; + } + + /* + * Release local reference to wrapper object, since some JVMs seem reticent + * about collecting it otherwise. + */ + /* FIXME -- beard: this seems to make calls into Java with JSObject's fail. */ + /* (*jEnv)->DeleteLocalRef(jEnv, java_wrapper_obj); */ + +done: +#ifdef JS_THREADSAFE + PR_ExitMonitor(js_obj_reflections_monitor); +#endif + + return java_wrapper_obj; +} + +/* + * Remove the mapping of a JS object from the hash table that maps JS objects + * to Java objects. This is called from the finalizer of an instance of + * netscape.javascript.JSObject. + */ +static JSBool +remove_js_obj_reflection_from_hashtable(JSContext *cx, JSObject *js_obj) +{ + PRHashEntry *he, **hep; + JSBool success = JS_FALSE; + +#ifdef JS_THREADSAFE + PR_EnterMonitor(js_obj_reflections_monitor); +#endif + + /* Get the hash-table entry for this wrapper object */ + hep = PR_HashTableRawLookup(js_obj_reflections, (PRHashNumber)js_obj, js_obj); + he = *hep; + + PR_ASSERT(he); + if (he) { + /* Tell the JS GC that Java no longer keeps a reference to this + JS object. */ + success = JS_RemoveRoot(cx, (void *)&he->key); + + PR_HashTableRawRemove(js_obj_reflections, hep, he); + } + +#ifdef JS_THREADSAFE + PR_ExitMonitor(js_obj_reflections_monitor); +#endif + + return success; +} + +/*************** Handling of Java exceptions in JavaScript ******************/ + +/* + * Free up a JavaScript error that has been stored by the + * capture_js_error_reports_for_java() function. + */ +static CapturedJSError * +destroy_saved_js_error(JNIEnv *jEnv, CapturedJSError *error) +{ + CapturedJSError *next_error; + if (!error) + return NULL; + next_error = error->next; + + if (error->java_exception) + (*jEnv)->DeleteGlobalRef(jEnv, error->java_exception); + if (error->message) + free((char*)error->message); + if (error->report.filename) + free((char*)error->report.filename); + if (error->report.linebuf) + free((char*)error->report.linebuf); + free(error); + + return next_error; +} + +/* + * Capture a JS error that has been reported using JS_ReportError() by JS code + * that has itself been called from Java. A copy of the JS error data is made + * and hung off the JSJ environment. When JS completes and returns to its Java + * caller, this data is used to synthesize an instance of + * netscape.javascript.JSException. If the resulting JSException is not caught + * within Java, it may be propagated up the stack beyond the Java caller back + * into JavaScript, in which case the error will be re-reported as a JavaScript + * error. + */ +PR_STATIC_CALLBACK(void) +capture_js_error_reports_for_java(JSContext *cx, const char *message, + JSErrorReport *report) +{ + CapturedJSError *new_error; + JSJavaThreadState *jsj_env; + jthrowable java_exception; + JNIEnv *jEnv; + + /* Create an empty struct to hold the saved JS error state */ + new_error = malloc(sizeof(CapturedJSError)); + if (!new_error) + goto out_of_memory; + memset(new_error, 0, sizeof(CapturedJSError)); + + /* Copy all the error info out of the original report into a private copy */ + if (message) { + new_error->message = strdup(message); + if (!new_error->message) + goto out_of_memory; + } + if (report) { + new_error->report.lineno = report->lineno; + + if (report->filename) { + new_error->report.filename = strdup(report->filename); + if (!new_error->report.filename) + goto out_of_memory; + } + + if (report->linebuf) { + new_error->report.linebuf = strdup(report->linebuf); + if (!new_error->report.linebuf) + goto out_of_memory; + new_error->report.tokenptr = + new_error->report.linebuf + (report->tokenptr - report->linebuf); + } + } + + /* Get the head of the list of pending JS errors */ + jsj_env = jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jsj_env) + goto abort; + + /* If there's a Java exception associated with this error, save it too. */ + java_exception = (*jEnv)->ExceptionOccurred(jEnv); + if (java_exception) { + (*jEnv)->ExceptionClear(jEnv); + java_exception = (*jEnv)->NewGlobalRef(jEnv, java_exception); + new_error->java_exception = java_exception; + } + + /* Push this error onto the list of pending JS errors */ + new_error->next = jsj_env->pending_js_errors; + jsj_env->pending_js_errors = new_error; + return; + +abort: +out_of_memory: + /* No recovery action possible */ + PR_ASSERT(0); + destroy_saved_js_error(jEnv, new_error); + return; +} + +void +jsj_ClearPendingJSErrors(JSJavaThreadState *jsj_env) +{ + while (jsj_env->pending_js_errors) + jsj_env->pending_js_errors = destroy_saved_js_error(jsj_env->jEnv, jsj_env->pending_js_errors); +} + +/* + * This is called upon returning from JS back into Java. Any JS errors + * reported during that time will be converted into Java exceptions. It's + * possible that a JS error was actually triggered by Java at some point, in + * which case the original Java exception is thrown. + */ +static void +throw_any_pending_js_error_as_a_java_exception(JSJavaThreadState *jsj_env) +{ + CapturedJSError *error; + JNIEnv *jEnv; + jstring message_jstr, linebuf_jstr, filename_jstr; + jint index, lineno; + JSErrorReport *report; + jthrowable java_exception; + + /* Get the Java JNI environment */ + jEnv = jsj_env->jEnv; + + if (!jsj_env->pending_js_errors) { +#ifdef DEBUG + /* Any exception should be cleared as soon as it's detected, so there + shouldn't be any pending. */ + if ((*jEnv)->ExceptionOccurred(jEnv)) { + /* A Java exception occurred, but nobody in JS-land noticed. */ + PR_ASSERT(0); + (*jEnv)->ExceptionClear(jEnv); + } +#endif + return; + } + + /* Get the deepest (oldest) saved JS error */ + /* XXX - What's the right thing to do about newer errors ? + For now we just throw them away */ + error = jsj_env->pending_js_errors; + while (error->next) + error = error->next; + + /* + * If the JS error was originally the result of a Java exception, rethrow + * the original exception. + */ + if (error->java_exception) { + (*jEnv)->Throw(jEnv, error->java_exception); + goto done; + } + + /* Propagate any JS errors that did not originate as Java exceptions into + Java as an instance of netscape.javascript.JSException */ + + /* First, marshall the arguments to the JSException constructor */ + message_jstr = NULL; + if (error->message) { + message_jstr = (*jEnv)->NewStringUTF(jEnv, error->message); + if (!message_jstr) + goto out_of_memory; + } + + report = &error->report; + + filename_jstr = NULL; + if (report->filename) { + filename_jstr = (*jEnv)->NewStringUTF(jEnv, report->filename); + if (!filename_jstr) + goto out_of_memory; + } + + linebuf_jstr = NULL; + if (report->linebuf) { + linebuf_jstr = (*jEnv)->NewStringUTF(jEnv, report->linebuf); + if (!linebuf_jstr) + goto out_of_memory; + } + + lineno = report->lineno; + index = report->linebuf ? report->tokenptr - report->linebuf : 0; + + /* Call the JSException constructor */ + java_exception = (*jEnv)->NewObject(jEnv, njJSException, njJSException_JSException, + message_jstr, filename_jstr, lineno, linebuf_jstr, index); + if (!java_exception) + goto out_of_memory; + + /* Throw the newly-created JSException */ + if ((*jEnv)->Throw(jEnv, java_exception) < 0) { + PR_ASSERT(0); + jsj_LogError("Couldn't throw JSException\n"); + goto done; + } + + /* + * Release local references to Java objects, since some JVMs seem reticent + * about collecting them otherwise. + */ + (*jEnv)->DeleteLocalRef(jEnv, message_jstr); + (*jEnv)->DeleteLocalRef(jEnv, filename_jstr); + (*jEnv)->DeleteLocalRef(jEnv, linebuf_jstr); + (*jEnv)->DeleteLocalRef(jEnv, java_exception); + + goto done; + +out_of_memory: + /* No recovery possible */ + PR_ASSERT(0); + jsj_LogError("Out of memory while attempting to throw JSException\n"); + +done: + jsj_ClearPendingJSErrors(jsj_env); +} + +/* + * This function is called up returning from Java back into JS as a result of + * a thrown netscape.javascript.JSException, which itself must have been caused + * by a JS error when Java called into JS. The original JS error is + * reconstituted from the JSException and re-reported as a JS error. + * + * Returns JS_FALSE if an internal error occurs, JS_TRUE otherwise. + */ +JSBool +jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception) +{ + JSBool success; + JSErrorReport report; + const char *linebuf, *filename, *message, *tokenptr; + jint lineno, token_index; + jstring linebuf_jstr, filename_jstr, message_jstr; + + /* Initialize everything to NULL */ + memset(&report, 0, sizeof(JSErrorReport)); + success = JS_FALSE; + filename_jstr = linebuf_jstr = NULL; + filename = message = linebuf = tokenptr = NULL; + + lineno = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno); + report.lineno = lineno; + + filename_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_filename); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, "Unable to access filename field of a JSException"); + goto done; + } + if (filename_jstr) + filename = (*jEnv)->GetStringUTFChars(jEnv, filename_jstr, 0); + report.filename = filename; + + linebuf_jstr = (*jEnv)->GetObjectField(jEnv, java_exception, njJSException_source); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, "Unable to access source field of a JSException"); + goto done; + } + if (linebuf_jstr) + linebuf = (*jEnv)->GetStringUTFChars(jEnv, linebuf_jstr, 0); + report.linebuf = linebuf; + + token_index = (*jEnv)->GetIntField(jEnv, java_exception, njJSException_lineno); + report.tokenptr = linebuf + token_index; + + message_jstr = (*jEnv)->CallObjectMethod(jEnv, java_exception, jlThrowable_getMessage); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, "Unable to access message of a JSException"); + goto done; + } + if (message_jstr) + message = (*jEnv)->GetStringUTFChars(jEnv, message_jstr, 0); + + js_ReportErrorAgain(cx, message, &report); + + success = JS_TRUE; + +done: + + if (filename_jstr && filename) + (*jEnv)->ReleaseStringUTFChars(jEnv, filename_jstr, filename); + if (linebuf_jstr && linebuf) + (*jEnv)->ReleaseStringUTFChars(jEnv, linebuf_jstr, linebuf); + if (message_jstr && message) + (*jEnv)->ReleaseStringUTFChars(jEnv, message_jstr, message); + return success; +} + + + +/*************** Utilities for calling JavaScript from Java *****************/ + +/* + * This routine is called just prior to invoking any JS API function from + * Java. It performs a common set of chores, such as obtaining the LiveConnect + * state for the invoking Java thread and determining the JSContext to be + * used for this thread. + * + * Returns NULL on failure. + */ + +struct JavaToJSSavedState { + JSErrorReporter error_reporter; + JSJavaThreadState* java_jsj_env; +}; +typedef struct JavaToJSSavedState JavaToJSSavedState; + +static JSJavaThreadState * +enter_js(JNIEnv *jEnv, jobject java_wrapper_obj, + JSContext **cxp, JSObject **js_objp, JavaToJSSavedState* saved_state) +{ + JSContext *cx; + char *err_msg; + JSObject *js_obj; + JSJavaThreadState *jsj_env; + + cx = NULL; + err_msg = NULL; + + /* Invoke callback, presumably used to implement concurrency constraints */ + if (JSJ_callbacks->enter_js_from_java) { + if (!JSJ_callbacks->enter_js_from_java(&err_msg)) + goto entry_failure; + } + + /* Check the JSObject pointer in the wrapper object for null while holding + the JS lock to deal with shutdown issues. */ + if (js_objp) { + js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, njJSObject_internal)); + PR_ASSERT(js_obj); + if (!js_obj) + goto error; + *js_objp = js_obj; + } + + /* Get the per-thread state corresponding to the current Java thread */ + jsj_env = jsj_MapJavaThreadToJSJavaThreadState(jEnv, &err_msg); + if (!jsj_env) + goto error; + + /* Get the JSContext that we're supposed to use for this Java thread */ + cx = jsj_env->cx; + if (!cx) { + /* We called spontaneously into JS from Java, rather than from JS into + Java and back into JS. Invoke a callback to obtain/create a + JSContext for us to use. */ + if (JSJ_callbacks->map_jsj_thread_to_js_context) { + cx = JSJ_callbacks->map_jsj_thread_to_js_context(jsj_env->jEnv, &err_msg); + if (!cx) + goto error; + } else { + err_msg = PR_smprintf("Unable to find/create JavaScript execution " + "context for JNI thread 0x%08x", jEnv); + goto error; + } + } + *cxp = cx; + + /* + * Capture all JS error reports so that they can be thrown into the Java + * caller as an instance of netscape.javascript.JSException. + */ + saved_state->error_reporter = JS_SetErrorReporter(cx, capture_js_error_reports_for_java); + saved_state->java_jsj_env = jsj_SetJavaJSJEnv(jsj_env); + + return jsj_env; + +error: + /* Invoke callback, presumably used to implement concurrency constraints */ + if (JSJ_callbacks->exit_js) + JSJ_callbacks->exit_js(); + +entry_failure: + if (err_msg) { + if (cx) + JS_ReportError(cx, err_msg); + else + jsj_LogError(err_msg); + free(err_msg); + } + + return NULL; +} + +/* + * This utility function is called just prior to returning into Java from JS. + */ +static JSBool +exit_js(JSContext *cx, JSJavaThreadState *jsj_env, JavaToJSSavedState* original_state) +{ + JNIEnv *jEnv; + + /* Restore the JS error reporter */ + JS_SetErrorReporter(cx, original_state->error_reporter); + jsj_SetJavaJSJEnv(original_state->java_jsj_env); + + jEnv = jsj_env->jEnv; + +#ifdef DEBUG + /* Any Java exceptions should have been noticed and reported already */ + if ((*jEnv)->ExceptionOccurred(jEnv)) { + PR_ASSERT(0); + jsj_LogError("Unhandled Java exception detected"); + return JS_FALSE; + } +#endif + + /* + * Convert reported JS errors to JSExceptions, unless the errors were + * themselves the result of Java exceptions, in which case the original + * Java exception is simply propagated. + */ + throw_any_pending_js_error_as_a_java_exception(jsj_env); + + /* Invoke callback, presumably used to implement concurrency constraints */ + if (JSJ_callbacks->exit_js) + JSJ_callbacks->exit_js(); + + return JS_TRUE; +} + + +/* Get the JavaClassDescriptor that corresponds to java.lang.Object */ +static JavaClassDescriptor * +get_jlObject_descriptor(JSContext *cx, JNIEnv *jEnv) +{ + /* The JavaClassDescriptor for java.lang.Object */ + static JavaClassDescriptor *jlObject_descriptor = NULL; + + if (!jlObject_descriptor) + jlObject_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, jlObject); + return jlObject_descriptor; +} + +/****************** Implementation of methods of JSObject *******************/ + +#ifdef XP_MAC +#pragma export on +#endif + +/* + * Class: netscape_javascript_JSObject + * Method: initClass + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_netscape_javascript_JSObject_initClass(JNIEnv *jEnv, jclass java_class) +{ + init_js_obj_reflections_table(); +} + +/* + * Class: netscape_javascript_JSObject + * Method: getMember + * Signature: (Ljava/lang/String;)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_netscape_javascript_JSObject_getMember(JNIEnv *jEnv, + jobject java_wrapper_obj, + jstring property_name_jstr) +{ + JSContext *cx; + JSObject *js_obj; + jsval js_val; + int dummy_cost; + JSBool dummy_bool; + const jchar *property_name_ucs2; + jsize property_name_len; + JavaToJSSavedState saved_state; + jobject member; + jboolean is_copy; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return NULL; + + property_name_ucs2 = NULL; + if (!property_name_jstr) { + JS_ReportError(cx, "illegal null member name"); + member = NULL; + goto done; + } + + /* Get the Unicode string for the JS property name */ + property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); + if (!property_name_ucs2) { + PR_ASSERT(0); + goto done; + } + property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); + + if (!JS_GetUCProperty(cx, js_obj, property_name_ucs2, property_name_len, &js_val)) + goto done; + + jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv), + &dummy_cost, &member, &dummy_bool); + +done: + if (property_name_ucs2) + (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); + if (!exit_js(cx, jsj_env, &saved_state)) + return NULL; + + return member; +} + +/* + * Class: netscape_javascript_JSObject + * Method: getSlot + * Signature: (I)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_netscape_javascript_JSObject_getSlot(JNIEnv *jEnv, + jobject java_wrapper_obj, + jint slot) +{ + JSContext *cx; + JSObject *js_obj; + jsval js_val; + int dummy_cost; + JSBool dummy_bool; + JavaToJSSavedState saved_state; + jobject member; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return NULL; + + + if (!JS_GetElement(cx, js_obj, slot, &js_val)) + goto done; + if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv), + &dummy_cost, &member, &dummy_bool)) + goto done; + +done: + if (!exit_js(cx, jsj_env, &saved_state)) + return NULL; + + 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 *jEnv, + jobject java_wrapper_obj, + jstring property_name_jstr, + jobject java_obj) +{ + JSContext *cx; + JSObject *js_obj; + jsval js_val; + const jchar *property_name_ucs2; + jsize property_name_len; + JavaToJSSavedState saved_state; + jboolean is_copy; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return; + + property_name_ucs2 = NULL; + if (!property_name_jstr) { + JS_ReportError(cx, "illegal null member name"); + goto done; + } + + /* Get the Unicode string for the JS property name */ + property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); + if (!property_name_ucs2) { + PR_ASSERT(0); + goto done; + } + property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); + + if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) + goto done; + + JS_SetUCProperty(cx, js_obj, property_name_ucs2, property_name_len, &js_val); + +done: + if (property_name_ucs2) + (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); + exit_js(cx, jsj_env, &saved_state); +} + +/* + * Class: netscape_javascript_JSObject + * Method: setSlot + * Signature: (ILjava/lang/Object;)V + */ +JNIEXPORT void JNICALL +Java_netscape_javascript_JSObject_setSlot(JNIEnv *jEnv, + jobject java_wrapper_obj, + jint slot, + jobject java_obj) +{ + JSContext *cx; + JSObject *js_obj; + jsval js_val; + JavaToJSSavedState saved_state; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return; + + if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_obj, &js_val)) + goto done; + JS_SetElement(cx, js_obj, slot, &js_val); + +done: + exit_js(cx, jsj_env, &saved_state); +} + +/* + * Class: netscape_javascript_JSObject + * Method: removeMember + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL +Java_netscape_javascript_JSObject_removeMember(JNIEnv *jEnv, + jobject java_wrapper_obj, + jstring property_name_jstr) +{ + JSContext *cx; + JSObject *js_obj; + jsval js_val; + const jchar *property_name_ucs2; + jsize property_name_len; + JavaToJSSavedState saved_state; + jboolean is_copy; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return; + + if (!property_name_jstr) { + JS_ReportError(cx, "illegal null member name"); + goto done; + } + /* Get the Unicode string for the JS property name */ + property_name_ucs2 = (*jEnv)->GetStringChars(jEnv, property_name_jstr, &is_copy); + if (!property_name_ucs2) { + PR_ASSERT(0); + goto done; + } + property_name_len = (*jEnv)->GetStringLength(jEnv, property_name_jstr); + + JS_DeleteUCProperty2(cx, js_obj, property_name_ucs2, property_name_len, &js_val); + + (*jEnv)->ReleaseStringChars(jEnv, property_name_jstr, property_name_ucs2); + +done: + exit_js(cx, jsj_env, &saved_state); + return; +} + +/* + * 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 *jEnv, jobject java_wrapper_obj, + jstring function_name_jstr, jobjectArray java_args) +{ + int i, argc, arg_num; + jsval *argv; + JSContext *cx; + JSObject *js_obj; + jsval js_val, function_val; + int dummy_cost; + JSBool dummy_bool; + const jchar *function_name_ucs2; + jsize function_name_len; + JavaToJSSavedState saved_state; + jboolean is_copy; + jobject result; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return NULL; + + function_name_ucs2 = NULL; + result = NULL; + if (!function_name_jstr) { + JS_ReportError(cx, "illegal null JavaScript function name"); + goto done; + } + + /* Get the function name to eval as raw Unicode characters */ + function_name_ucs2 = (*jEnv)->GetStringChars(jEnv, function_name_jstr, &is_copy); + if (!function_name_ucs2) { + PR_ASSERT(0); + goto done; + } + function_name_len = (*jEnv)->GetStringLength(jEnv, function_name_jstr); + + /* FIXME: What about security stuff ? Don't principals need to be set here ? */ + + /* Allocate space for JS arguments */ + if (java_args) { + argc = (*jEnv)->GetArrayLength(jEnv, java_args); + argv = (jsval*)JS_malloc(cx, argc * sizeof(jsval)); + } else { + argc = 0; + argv = 0; + } + + /* Convert arguments from Java to JS values */ + for (arg_num = 0; arg_num < argc; arg_num++) { + jobject arg = (*jEnv)->GetObjectArrayElement(jEnv, java_args, arg_num); + + if (!jsj_ConvertJavaObjectToJSValue(cx, jEnv, arg, &argv[arg_num])) + goto cleanup_argv; + JS_AddRoot(cx, &argv[arg_num]); + } + + if (!JS_GetUCProperty(cx, js_obj, function_name_ucs2, function_name_len, + &function_val)) + goto cleanup_argv; + + if (!JS_CallFunctionValue(cx, js_obj, function_val, argc, argv, &js_val)) + goto cleanup_argv; + + jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv), + &dummy_cost, &result, &dummy_bool); + +cleanup_argv: + if (argv) { + for (i = 0; i < arg_num; i++) + JS_RemoveRoot(cx, &argv[i]); + JS_free(cx, argv); + } + +done: + if (function_name_ucs2) + (*jEnv)->ReleaseStringChars(jEnv, function_name_jstr, function_name_ucs2); + if (!exit_js(cx, jsj_env, &saved_state)) + return NULL; + + return result; +} + +/* + * Class: netscape_javascript_JSObject + * Method: eval + * Signature: (Ljava/lang/String;)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL +Java_netscape_javascript_JSObject_eval(JNIEnv *jEnv, + jobject java_wrapper_obj, + jstring eval_jstr) +{ + const char *codebase; + JSPrincipals *principals; + JSContext *cx; + JSBool eval_succeeded; + JSObject *js_obj; + jsval js_val; + int dummy_cost; + JSBool dummy_bool; + const jchar *eval_ucs2; + jsize eval_len; + JavaToJSSavedState saved_state; + jboolean is_copy; + jobject result; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return NULL; + + result = NULL; + eval_ucs2 = NULL; + if (!eval_jstr) { + JS_ReportError(cx, "illegal null string eval argument"); + goto done; + } + + /* Get the string to eval as raw Unicode characters */ + eval_ucs2 = (*jEnv)->GetStringChars(jEnv, eval_jstr, &is_copy); + if (!eval_ucs2) { + PR_ASSERT(0); + goto done; + } + eval_len = (*jEnv)->GetStringLength(jEnv, eval_jstr); + + /* Set up security stuff */ + principals = NULL; + if (JSJ_callbacks->get_JSPrincipals_from_java_caller) + principals = JSJ_callbacks->get_JSPrincipals_from_java_caller(jEnv); + codebase = principals ? principals->codebase : NULL; + + /* Have the JS engine evaluate the unicode string */ + eval_succeeded = JS_EvaluateUCScriptForPrincipals(cx, js_obj, principals, + eval_ucs2, eval_len, + codebase, 0, &js_val); + if (!eval_succeeded) + goto done; + + /* Convert result to a subclass of java.lang.Object */ + jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv), + &dummy_cost, &result, &dummy_bool); + +done: + if (eval_ucs2) + (*jEnv)->ReleaseStringChars(jEnv, eval_jstr, eval_ucs2); + if (!exit_js(cx, jsj_env, &saved_state)) + return NULL; + + return result; +} + +/* + * Class: netscape_javascript_JSObject + * Method: toString + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL +Java_netscape_javascript_JSObject_toString(JNIEnv *jEnv, + jobject java_wrapper_obj) +{ + jstring result; + JSContext *cx; + JSObject *js_obj; + JSString *jsstr; + JavaToJSSavedState saved_state; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) + return NULL; + + result = NULL; + jsstr = JS_ValueToString(cx, OBJECT_TO_JSVAL(js_obj)); + if (jsstr) + result = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr); + if (!result) + result = (*jEnv)->NewStringUTF(jEnv, "*JavaObject*"); + + if (!exit_js(cx, jsj_env, &saved_state)) + return NULL; + + return result; +} + +/* + * Class: netscape_javascript_JSObject + * Method: getWindow + * Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject; + */ +JNIEXPORT jobject JNICALL +Java_netscape_javascript_JSObject_getWindow(JNIEnv *jEnv, + jclass js_object_class, + jobject java_applet_obj) +{ + char *err_msg; + JSContext *cx; + JSObject *js_obj; + jsval js_val; + int dummy_cost; + JSBool dummy_bool; + JavaToJSSavedState saved_state; + jobject java_obj; + JSJavaThreadState *jsj_env; + + jsj_env = enter_js(jEnv, NULL, &cx, NULL, &saved_state); + if (!jsj_env) + return NULL; + + err_msg = NULL; + java_obj = NULL; + js_obj = JSJ_callbacks->map_java_object_to_js_object(jEnv, java_applet_obj, &err_msg); + if (!js_obj) { + if (err_msg) { + JS_ReportError(cx, err_msg); + free(err_msg); + } + goto done; + } + js_val = OBJECT_TO_JSVAL(js_obj); + jsj_ConvertJSValueToJavaObject(cx, jEnv, js_val, get_jlObject_descriptor(cx, jEnv), + &dummy_cost, &java_obj, &dummy_bool); +done: + if (!exit_js(cx, jsj_env, &saved_state)) + return NULL; + + return java_obj; +} + +/* + * Class: netscape_javascript_JSObject + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL +Java_netscape_javascript_JSObject_finalize(JNIEnv *jEnv, jobject java_wrapper_obj) +{ + JSContext *cx; + JavaToJSSavedState saved_state; + JSJavaThreadState *jsj_env; + JSObject *js_obj; + + jsj_env = enter_js(jEnv, java_wrapper_obj, &cx, &js_obj, &saved_state); + if (!jsj_env) /* Note: memory leak if we exit here */ + return; + remove_js_obj_reflection_from_hashtable(cx, js_obj); + exit_js(cx, jsj_env, &saved_state); +} + diff --git a/mozilla/js/src/liveconnect/jsj_JavaArray.c b/mozilla/js/src/liveconnect/jsj_JavaArray.c new file mode 100644 index 00000000000..1720a7415dd --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_JavaArray.c @@ -0,0 +1,404 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the definition of the JavaScript JavaArray class. + * Instances of JavaArray are used to reflect Java arrays. + */ + +#include +#include +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ + +/* Shorthands for ASCII (7-bit) decimal and hex conversion. */ +#define JS7_ISDEC(c) (((c) >= '0') && ((c) <= '9')) +#define JS7_UNDEC(c) ((c) - '0') + +/* + * Convert any jsval v to an integer jsval if ToString(v) + * contains a base-10 integer that fits into 31 bits. + * Otherwise return v. + */ +static jsval +try_convert_to_jsint(JSContext *cx, jsval idval) +{ + const jschar *cp; + JSString *jsstr; + + jsstr = JS_ValueToString(cx, idval); + if (!jsstr) + return idval; + + cp = JS_GetStringChars(jsstr); + if (JS7_ISDEC(*cp)) { + jsuint index = JS7_UNDEC(*cp++); + jsuint oldIndex = 0; + jsuint c; + if (index != 0) { + while (JS7_ISDEC(*cp)) { + oldIndex = index; + c = JS7_UNDEC(*cp); + index = 10*index + c; + cp++; + } + } + if (*cp == 0 && + (oldIndex < (JSVAL_INT_MAX / 10) || + (oldIndex == (JSVAL_INT_MAX / 10) && c < (JSVAL_INT_MAX % 10)))) { + return INT_TO_JSVAL(index); + } + } + return idval; +} + + +static JSBool +access_java_array_element(JSContext *cx, + JNIEnv *jEnv, + JSObject *obj, + jsid id, + jsval *vp, + JSBool do_assignment) +{ + jsval idval; + jarray java_array; + JavaClassDescriptor *class_descriptor; + JavaObjectWrapper *java_wrapper; + jsize array_length, index; + JavaSignature *array_component_signature; + + /* printf("In JavaArray_getProperty\n"); */ + + java_wrapper = JS_GetPrivate(cx, obj); + if (!java_wrapper) { + const char *property_name; + if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && + (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) { + if (!strcmp(property_name, "constructor")) { + *vp = JSVAL_VOID; + return JS_TRUE; + } + } + JS_ReportError(cx, "illegal operation on JavaArray prototype object"); + return JS_FALSE; + } + class_descriptor = java_wrapper->class_descriptor; + java_array = java_wrapper->java_obj; + + PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_ARRAY); + + JS_IdToValue(cx, id, &idval); + + if (!JSVAL_IS_INT(idval)) + idval = try_convert_to_jsint(cx, idval); + + if (!JSVAL_IS_INT(idval)) { + /* + * Usually, properties of JavaArray objects are indexed by integers, but + * Java arrays also inherit all the methods of java.lang.Object, so a + * string-valued property is also possible. + */ + if (JSVAL_IS_STRING(idval)) { + const char *member_name; + + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + + if (do_assignment) { + JSVersion version = JS_GetVersion(cx); + + if (!JSVERSION_IS_ECMA(version)) { + + JS_ReportError(cx, "Attempt to write to invalid Java array " + "element \"%s\"", member_name); + return JS_FALSE; + } else { + *vp = JSVAL_VOID; + return JS_TRUE; + } + } else { + if (!strcmp(member_name, "length")) { + array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array); + if (array_length < 0) + return JS_FALSE; + if (vp) + *vp = INT_TO_JSVAL(array_length); + return JS_TRUE; + } + + /* Check to see if we're reflecting a Java array method */ + return JavaObject_getPropertyById(cx, obj, id, vp); + } + } + + JS_ReportError(cx, "invalid Java array index expression"); + return JS_FALSE; + } + + index = JSVAL_TO_INT(idval); + +#if 0 + array_length = jsj_GetJavaArrayLength(cx, jEnv, java_array); + if (array_length < 0) + return JS_FALSE; + + /* Just let Java throw an exception instead of checking array bounds here */ + if (index < 0 || index >= array_length) { + JS_ReportError(cx, "Java array index %d out of range", index); + return JS_FALSE; + } +#endif + + array_component_signature = class_descriptor->array_component_signature; + + if (!vp) + return JS_TRUE; + + if (do_assignment) { + return jsj_SetJavaArrayElement(cx, jEnv, java_array, index, + array_component_signature, *vp); + } else { + return jsj_GetJavaArrayElement(cx, jEnv, java_array, index, + array_component_signature, vp); + } +} + +PR_STATIC_CALLBACK(JSBool) +JavaArray_getPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + JNIEnv *jEnv; + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + return access_java_array_element(cx, jEnv, obj, id, vp, JS_FALSE); +} + +PR_STATIC_CALLBACK(JSBool) +JavaArray_setPropertyById(JSContext *cx, JSObject *obj, jsval id, jsval *vp) +{ + JNIEnv *jEnv; + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + return access_java_array_element(cx, jEnv, obj, id, vp, JS_TRUE); +} + +static JSBool +JavaArray_lookupProperty(JSContext *cx, JSObject *obj, jsid id, + JSObject **objp, JSProperty **propp +#if defined JS_THREADSAFE && defined DEBUG + , const char *file, uintN line +#endif + ) +{ + JNIEnv *jEnv; + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + return access_java_array_element(cx, jEnv, obj, id, NULL, JS_FALSE); +} + +static JSBool +JavaArray_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, + JSPropertyOp getter, JSPropertyOp setter, + uintN attrs, JSProperty **propp) +{ + JS_ReportError(cx, "Cannot define a new property in a JavaArray"); + return JS_FALSE; +} + +static JSBool +JavaArray_getAttributes(JSContext *cx, JSObject *obj, jsid id, + JSProperty *prop, uintN *attrsp) +{ + /* We don't maintain JS property attributes for Java class members */ + *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE; + return JS_FALSE; +} + +static JSBool +JavaArray_setAttributes(JSContext *cx, JSObject *obj, jsid id, + JSProperty *prop, uintN *attrsp) +{ + /* We don't maintain JS property attributes for Java class members */ + if (*attrsp != JSPROP_PERMANENT|JSPROP_ENUMERATE) { + PR_ASSERT(0); + return JS_FALSE; + } + + /* Silently ignore all setAttribute attempts */ + return JS_TRUE; +} + +static JSBool +JavaArray_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + JSVersion version = JS_GetVersion(cx); + + *vp = JSVAL_FALSE; + + if (!JSVERSION_IS_ECMA(version)) { + JS_ReportError(cx, "Properties of JavaArray objects may not be deleted"); + return JS_FALSE; + } else { + /* Attempts to delete permanent properties are silently ignored + by ECMAScript. */ + return JS_TRUE; + } +} + +static JSBool +JavaArray_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + /* printf("In JavaArray_defaultValue()\n"); */ + return JavaObject_convert(cx, obj, JSTYPE_STRING, vp); +} + +static JSBool +JavaArray_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, + jsval *statep, jsid *idp) +{ + JavaObjectWrapper *java_wrapper; + JNIEnv *jEnv; + jsize array_length, index; + + java_wrapper = JS_GetPrivate(cx, obj); + /* Check for prototype object */ + if (!java_wrapper) { + *statep = JSVAL_NULL; + if (idp) + *idp = INT_TO_JSVAL(0); + return JS_TRUE; + } + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + array_length = jsj_GetJavaArrayLength(cx, jEnv, java_wrapper->java_obj); + if (array_length < 0) + return JS_FALSE; + + switch(enum_op) { + case JSENUMERATE_INIT: + *statep = INT_TO_JSVAL(0); + + if (idp) + *idp = INT_TO_JSVAL(array_length); + return JS_TRUE; + + case JSENUMERATE_NEXT: + index = JSVAL_TO_INT(*statep); + if (index < array_length) { + JS_ValueToId(cx, INT_TO_JSVAL(index), idp); + index++; + *statep = INT_TO_JSVAL(index); + return JS_TRUE; + } + + /* Fall through ... */ + + case JSENUMERATE_DESTROY: + *statep = JSVAL_NULL; + return JS_TRUE; + + default: + PR_ASSERT(0); + return JS_FALSE; + } +} + +static JSBool +JavaArray_checkAccess(JSContext *cx, JSObject *obj, jsid id, + JSAccessMode mode, jsval *vp, uintN *attrsp) +{ + switch (mode) { + case JSACC_WATCH: + JS_ReportError(cx, "Cannot place watchpoints on JavaArray object properties"); + return JS_FALSE; + + case JSACC_IMPORT: + JS_ReportError(cx, "Cannot export a JavaArray object's properties"); + return JS_FALSE; + + default: + return JS_TRUE; + } +} + +JSObjectOps JavaArray_ops = { + /* Mandatory non-null function pointer members. */ + NULL, /* newObjectMap */ + NULL, /* destroyObjectMap */ + JavaArray_lookupProperty, + JavaArray_defineProperty, + JavaArray_getPropertyById, /* getProperty */ + JavaArray_setPropertyById, /* setProperty */ + JavaArray_getAttributes, + JavaArray_setAttributes, + JavaArray_deleteProperty, + JavaArray_defaultValue, + JavaArray_newEnumerate, + JavaArray_checkAccess, + + /* Optionally non-null members start here. */ + NULL, /* thisObject */ + NULL, /* dropProperty */ + NULL, /* call */ + NULL, /* construct */ + NULL, /* xdrObject */ + NULL /* hasInstance */ +}; + +static JSObjectOps * +JavaArray_getObjectOps(JSContext *cx, JSClass *clazz) +{ + return &JavaArray_ops; +} + +JSClass JavaArray_class = { + "JavaArray", JSCLASS_HAS_PRIVATE, + NULL, NULL, NULL, NULL, + NULL, NULL, JavaObject_convert, JavaObject_finalize, + JavaArray_getObjectOps, +}; + +extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps; + + +/* Initialize the JS JavaArray class */ +JSBool +jsj_init_JavaArray(JSContext *cx, JSObject *global_obj) +{ + JavaArray_ops.newObjectMap = js_ObjectOps.newObjectMap; + JavaArray_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap; + + if (!JS_InitClass(cx, global_obj, + 0, &JavaArray_class, 0, 0, + 0, 0, 0, 0)) + return JS_FALSE; + + return JS_TRUE; +} + diff --git a/mozilla/js/src/liveconnect/jsj_JavaClass.c b/mozilla/js/src/liveconnect/jsj_JavaClass.c new file mode 100644 index 00000000000..5a46df1d79b --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_JavaClass.c @@ -0,0 +1,584 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the native code implementation of JS's JavaClass class. + * + * A JavaClass is JavaScript's representation of a Java class. + * Its parent JS object is always a JavaPackage object. A JavaClass is not an + * exact reflection of Java's corresponding java.lang.Class object. Rather, + * the properties of a JavaClass are the static methods and properties of the + * corresponding Java class. + * + * Note that there is no runtime equivalent to the JavaClass class in Java. + * (Although there are instances of java.lang.String and there are static + * methods of java.lang.String that can be invoked, there's no such thing as + * a first-class object that can be referenced simply as "java.lang.String".) + */ + +#include +#include + +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ + +static JSBool +JavaClass_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + char *name; + JSString *str; + + JavaClassDescriptor *class_descriptor; + + class_descriptor = JS_GetPrivate(cx, obj); + if (!class_descriptor) + return JS_FALSE; + + switch(type) { + + + case JSTYPE_STRING: + /* Convert '/' to '.' so that it looks like Java language syntax. */ + if (!class_descriptor->name) + break; + name = PR_smprintf("[JavaClass %s]", class_descriptor->name); + if (!name) { + JS_ReportOutOfMemory(cx); + return JS_FALSE; + } + + str = JS_NewString(cx, name, strlen(name)); + if (!str) { + free(name); + /* It's not necessary to call JS_ReportOutOfMemory(), as + JS_NewString() will do so on failure. */ + return JS_FALSE; + } + + *vp = STRING_TO_JSVAL(str); + return JS_TRUE; + + default: + break; + } + return JS_TRUE; +} + +static JSBool +lookup_static_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj, + JavaClassDescriptor **class_descriptorp, + jsid id, JavaMemberDescriptor **memberp) +{ + jsval idval; + JavaMemberDescriptor *member_descriptor; + const char *member_name; + JavaClassDescriptor *class_descriptor; + + class_descriptor = JS_GetPrivate(cx, obj); + if (!class_descriptor) { + *class_descriptorp = NULL; + *memberp = NULL; + return JS_TRUE; + } + + if (class_descriptorp) + *class_descriptorp = class_descriptor; + + member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); + if (!member_descriptor) { + JS_IdToValue(cx, id, &idval); + if (!JSVAL_IS_STRING(idval)) { + JS_ReportError(cx, "invalid JavaClass property expression. " + "(methods and fields of a JavaClass object can only be identified by their name)"); + return JS_FALSE; + } + + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + + /* Why do we have to do this ? */ + if (!strcmp(member_name, "prototype")) { + *memberp = NULL; + return JS_TRUE; + } + + JS_ReportError(cx, "Java class %s has no public static field or method named \"%s\"", + class_descriptor->name, member_name); + return JS_FALSE; + } + if (memberp) + *memberp = member_descriptor; + return JS_TRUE; +} + +PR_STATIC_CALLBACK(JSBool) +JavaClass_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + jsval idval; + jclass java_class; + const char *member_name; + JavaClassDescriptor *class_descriptor; + JavaMemberDescriptor *member_descriptor; + JNIEnv *jEnv; + + /* printf("In JavaClass_getProperty\n"); */ + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) + return JS_FALSE; + if (!member_descriptor) { + *vp = JSVAL_VOID; + return JS_TRUE; + } + + java_class = class_descriptor->java_class; + + if (member_descriptor->field) { + if (!member_descriptor->methods) { + return jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, vp); + } else { + PR_ASSERT(0); + return JS_FALSE; + } + } else { + JSFunction *function; + + /* TODO - eliminate JSFUN_BOUND_METHOD */ + JS_IdToValue(cx, id, &idval); + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + function = JS_NewFunction(cx, jsj_JavaStaticMethodWrapper, 0, + JSFUN_BOUND_METHOD, obj, member_name); + if (!function) + return JS_FALSE; + + *vp = OBJECT_TO_JSVAL(JS_GetFunctionObject(function)); + return JS_TRUE; + } +} + +PR_STATIC_CALLBACK(JSBool) +JavaClass_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + jclass java_class; + const char *member_name; + JavaClassDescriptor *class_descriptor; + JavaMemberDescriptor *member_descriptor; + jsval idval; + JNIEnv *jEnv; + + /* printf("In JavaClass_setProperty\n"); */ + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (!lookup_static_member_by_id(cx, jEnv, obj, &class_descriptor, id, &member_descriptor)) + return JS_FALSE; + + /* Check for the case where there is a method with the given name, but no field + with that name */ + if (!member_descriptor->field) + goto no_such_field; + + /* Silently fail if field value is final (immutable), as required by ECMA spec */ + if (member_descriptor->field->modifiers & ACC_FINAL) + return JS_TRUE; + + java_class = class_descriptor->java_class; + return jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_class, *vp); + +no_such_field: + JS_IdToValue(cx, id, &idval); + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + JS_ReportError(cx, "No static field named \"%s\" in Java class %s", + member_name, class_descriptor->name); + return JS_FALSE; +} + +/* + * Free the private native data associated with the JavaPackage object. + */ +PR_STATIC_CALLBACK(void) +JavaClass_finalize(JSContext *cx, JSObject *obj) +{ + JNIEnv *jEnv; + + JavaClassDescriptor *class_descriptor = JS_GetPrivate(cx, obj); + if (!class_descriptor) + return; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return; + + printf("Finalizing %s\n", class_descriptor->name); + jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); +} + + +static JSBool +JavaClass_lookupProperty(JSContext *cx, JSObject *obj, jsid id, + JSObject **objp, JSProperty **propp +#if defined JS_THREADSAFE && defined DEBUG + , const char *file, uintN line +#endif + ) +{ + JNIEnv *jEnv; + + /* printf("In JavaClass_lookupProperty()\n"); */ + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (!lookup_static_member_by_id(cx, jEnv, obj, NULL, id, NULL)) + return JS_FALSE; + *objp = obj; + *propp = (JSProperty*)1; + return JS_TRUE; +} + +static JSBool +JavaClass_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, + JSPropertyOp getter, JSPropertyOp setter, + uintN attrs, JSProperty **propp) +{ + JS_ReportError(cx, "Cannot define a new property in a JavaClass"); + return JS_FALSE; +} + +static JSBool +JavaClass_getAttributes(JSContext *cx, JSObject *obj, jsid id, + JSProperty *prop, uintN *attrsp) +{ + /* We don't maintain JS property attributes for Java class members */ + *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE; + return JS_FALSE; +} + +static JSBool +JavaClass_setAttributes(JSContext *cx, JSObject *obj, jsid id, + JSProperty *prop, uintN *attrsp) +{ + /* We don't maintain JS property attributes for Java class members */ + if (*attrsp != JSPROP_PERMANENT|JSPROP_ENUMERATE) { + PR_ASSERT(0); + return JS_FALSE; + } + + /* Silently ignore all setAttribute attempts */ + return JS_TRUE; +} + +static JSBool +JavaClass_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + JSVersion version = JS_GetVersion(cx); + + *vp = JSVAL_FALSE; + + if (!JSVERSION_IS_ECMA(version)) { + JS_ReportError(cx, "Properties of JavaClass objects may not be deleted"); + return JS_FALSE; + } else { + /* Attempts to delete permanent properties are silently ignored + by ECMAScript. */ + return JS_TRUE; + } +} + +static JSBool +JavaClass_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + /* printf("In JavaClass_defaultValue()\n"); */ + return JavaClass_convert(cx, obj, JSTYPE_STRING, vp); +} + +static JSBool +JavaClass_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, + jsval *statep, jsid *idp) +{ + JavaMemberDescriptor *member_descriptor; + JavaClassDescriptor *class_descriptor; + JNIEnv *jEnv; + + class_descriptor = JS_GetPrivate(cx, obj); + + /* Check for prototype JavaClass object */ + if (!class_descriptor) { + *statep = JSVAL_NULL; + if (idp) + *idp = INT_TO_JSVAL(0); + return JS_TRUE; + } + + switch(enum_op) { + case JSENUMERATE_INIT: + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor); + *statep = PRIVATE_TO_JSVAL(member_descriptor); + if (idp) + *idp = INT_TO_JSVAL(class_descriptor->num_instance_members); + return JS_TRUE; + + case JSENUMERATE_NEXT: + member_descriptor = JSVAL_TO_PRIVATE(*statep); + if (member_descriptor) { + *idp = member_descriptor->id; + *statep = PRIVATE_TO_JSVAL(member_descriptor->next); + return JS_TRUE; + } + /* Fall through ... */ + + case JSENUMERATE_DESTROY: + *statep = JSVAL_NULL; + return JS_TRUE; + + default: + PR_ASSERT(0); + return JS_FALSE; + } +} + +static JSBool +JavaClass_checkAccess(JSContext *cx, JSObject *obj, jsid id, + JSAccessMode mode, jsval *vp, uintN *attrsp) +{ + switch (mode) { + case JSACC_WATCH: + JS_ReportError(cx, "Cannot place watchpoints on JavaClass object properties"); + return JS_FALSE; + + case JSACC_IMPORT: + JS_ReportError(cx, "Cannot export a JavaClass object's properties"); + return JS_FALSE; + + default: + return JS_TRUE; + } +} + +/* + * Implement the JavaScript instanceof operator for JavaClass objects by using + * the equivalent Java instanceof operation. + */ +static JSBool +JavaClass_hasInstance(JSContext *cx, JSObject *obj, jsval candidate_jsval, + JSBool *has_instancep) +{ + JavaClassDescriptor *class_descriptor; + JavaObjectWrapper *java_wrapper; + JSClass *js_class; + JSBool has_instance; + JSObject *candidate_obj; + jclass java_class; + jobject java_obj; + JNIEnv *jEnv; + + has_instance = JS_FALSE; + class_descriptor = JS_GetPrivate(cx, obj); + if (!class_descriptor) { + JS_ReportError(cx, "illegal operation on JavaClass prototype object"); + return JS_FALSE; + } + + /* + * Make sure that the thing to the left of the instanceof operator is a + * Java object. + */ + if (!JSVAL_IS_OBJECT(candidate_jsval)) + goto done; + candidate_obj = JSVAL_TO_OBJECT(candidate_jsval); + js_class = JS_GetClass(candidate_obj); + if ((js_class != &JavaObject_class) && (js_class != &JavaArray_class)) + goto done; + + java_class = class_descriptor->java_class; + java_wrapper = JS_GetPrivate(cx, candidate_obj); + if (!java_wrapper) { + JS_ReportError(cx, "illegal operation on prototype object"); + return JS_FALSE; + } + java_obj = java_wrapper->java_obj; + /* Get JNI pointer */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + has_instance = (*jEnv)->IsInstanceOf(jEnv, java_obj, java_class); + +done: + *has_instancep = has_instance; + return JS_TRUE; +} + +JSObjectOps JavaClass_ops = { + /* Mandatory non-null function pointer members. */ + NULL, /* newObjectMap */ + NULL, /* destroyObjectMap */ + JavaClass_lookupProperty, + JavaClass_defineProperty, + JavaClass_getPropertyById, /* getProperty */ + JavaClass_setPropertyById, /* setProperty */ + JavaClass_getAttributes, + JavaClass_setAttributes, + JavaClass_deleteProperty, + JavaClass_defaultValue, + JavaClass_newEnumerate, + JavaClass_checkAccess, + + /* Optionally non-null members start here. */ + NULL, /* thisObject */ + NULL, /* dropProperty */ + jsj_JavaConstructorWrapper, /* call */ + jsj_JavaConstructorWrapper, /* construct */ + NULL, /* xdrObject */ + JavaClass_hasInstance, /* hasInstance */ +}; + +static JSObjectOps * +JavaClass_getObjectOps(JSContext *cx, JSClass *clazz) +{ + return &JavaClass_ops; +} + +JSClass JavaClass_class = { + "JavaClass", JSCLASS_HAS_PRIVATE, + NULL, NULL, NULL, NULL, + NULL, NULL, JavaClass_convert, JavaClass_finalize, + JavaClass_getObjectOps, +}; + +static JSObject * +jsj_new_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj, + JavaClassDescriptor *class_descriptor) +{ + JSObject *JavaClass_obj; + + JavaClass_obj = JS_NewObject(cx, &JavaClass_class, 0, parent_obj); + if (!JavaClass_obj) + return NULL; + + JS_SetPrivate(cx, JavaClass_obj, (void *)class_descriptor); + +#ifdef DEBUG + /* printf("JavaClass \'%s\' created\n", class_descriptor->name); */ +#endif + + return JavaClass_obj; +} + +JSObject * +jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject* parent_obj, + const char *simple_class_name, + jclass java_class) +{ + JavaClassDescriptor *class_descriptor; + JSObject *JavaClass_obj; + + class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); + if (!class_descriptor) + return NULL; + + JavaClass_obj = jsj_new_JavaClass(cx, jEnv, parent_obj, class_descriptor); + if (!JavaClass_obj) + return NULL; + + if (!JS_DefineProperty(cx, parent_obj, simple_class_name, + OBJECT_TO_JSVAL(JavaClass_obj), 0, 0, + JSPROP_PERMANENT|JSPROP_READONLY|JSPROP_ENUMERATE)) + return NULL; + return JavaClass_obj; +} + + +/* + * The getClass() native JS method is defined as a property of the global + * object. Given a JavaObject it returns the corresponding JavaClass. This + * is useful for accessing static methods and fields. + * + * js> getClass(new java.lang.String("foo")) + * [JavaClass java.lang.String] + */ +static JSBool +getClass(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) +{ + JSObject *obj_arg, *JavaClass_obj; + JavaObjectWrapper *java_wrapper; + JavaClassDescriptor *class_descriptor; + JNIEnv *jEnv; + + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (argc != 1 || + !JSVAL_IS_OBJECT(argv[0]) || + !(obj_arg = JSVAL_TO_OBJECT(argv[0])) || + (!JS_InstanceOf(cx, obj_arg, &JavaObject_class, 0) && + !JS_InstanceOf(cx, obj_arg, &JavaArray_class, 0))) { + JS_ReportError(cx, "getClass expects a Java object argument"); + return JS_FALSE; + } + + java_wrapper = JS_GetPrivate(cx, obj_arg); + if (!java_wrapper) { + JS_ReportError(cx, "getClass called on prototype object"); + return JS_FALSE; + } + + class_descriptor = java_wrapper->class_descriptor; + + JavaClass_obj = jsj_new_JavaClass(cx, jEnv, NULL, class_descriptor); + if (!JavaClass_obj) + return JS_FALSE; + *rval = OBJECT_TO_JSVAL(JavaClass_obj); + return JS_TRUE; +} + +extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps; + +JSBool +jsj_init_JavaClass(JSContext *cx, JSObject *global_obj) +{ + JavaClass_ops.newObjectMap = js_ObjectOps.newObjectMap; + JavaClass_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap; + + /* Define JavaClass class */ + if (!JS_InitClass(cx, global_obj, 0, &JavaClass_class, 0, 0, 0, 0, 0, 0)) + return JS_FALSE; + + if (!JS_DefineFunction(cx, global_obj, "getClass", getClass, 0, + JSPROP_READONLY)) + return JS_FALSE; + + return jsj_InitJavaClassReflectionsTable(); +} + diff --git a/mozilla/js/src/liveconnect/jsj_JavaObject.c b/mozilla/js/src/liveconnect/jsj_JavaObject.c new file mode 100644 index 00000000000..04004f84113 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_JavaObject.c @@ -0,0 +1,713 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the native code implementation of JS's JavaObject class. + * + * An instance of JavaObject is the JavaScript reflection of a Java object. + * + */ + +#include +#include +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ +#include "jsj_hash.h" /* Hash table with Java object as key */ + + +/* + * This is a hash table that maps from Java objects to JS objects. + * It is used to ensure that the same JS object is obtained when a Java + * object is reflected more than once, so that JS object equality tests + * work in the expected manner, i.e. the "==" and "===" operators. + * + * The table entry keys are Java objects (of type jobject) and the entry values + * are JSObject pointers. Because the jobject type is an opaque handle and + * not necessarily a pointer, the hashing and key comparison functions must + * invoke the appropriate JVM functions. + * + * When the corresponding JS object instance is finalized, the entry is + * removed from the table, and a Java GC root for the Java object is removed. + */ +static JSJHashTable *java_obj_reflections = NULL; + +#ifdef JS_THREADSAFE +static PRMonitor *java_obj_reflections_monitor = NULL; +#endif + +static JSBool +init_java_obj_reflections_table() +{ + java_obj_reflections = + JSJ_NewHashTable(512, jsj_HashJavaObject, jsj_JavaObjectComparator, + NULL, NULL, NULL); + if (!java_obj_reflections) + return JS_FALSE; + +#ifdef JS_THREADSAFE + java_obj_reflections_monitor = PR_NewNamedMonitor("java_obj_reflections"); + if (!java_obj_reflections_monitor) { + PR_HashTableDestroy(java_obj_reflections); + return JS_FALSE; + } +#endif + + return JS_TRUE; +} + +JSObject * +jsj_WrapJavaObject(JSContext *cx, + JNIEnv *jEnv, + jobject java_obj, + jclass java_class) +{ + JSJHashNumber hash_code; + JSClass *js_class; + JSObject *js_wrapper_obj; + JavaObjectWrapper *java_wrapper; + JavaClassDescriptor *class_descriptor; + JSJHashEntry *he, **hep; + + js_wrapper_obj = NULL; + + hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv); + +#ifdef JS_THREADSAFE + PR_EnterMonitor(java_obj_reflections_monitor); +#endif + + hep = JSJ_HashTableRawLookup(java_obj_reflections, + hash_code, java_obj, (void*)jEnv); + he = *hep; + if (he) { + js_wrapper_obj = (JSObject *)he->value; + if (js_wrapper_obj) + goto done; + } + + /* No existing reflection found. Construct a new one */ + class_descriptor = jsj_GetJavaClassDescriptor(cx, jEnv, java_class); + if (!class_descriptor) + goto done; + if (class_descriptor->type == JAVA_SIGNATURE_ARRAY) { + js_class = &JavaArray_class; + } else { + PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_CLASS); + js_class = &JavaObject_class; + } + + /* Create new JS object to reflect Java object */ + js_wrapper_obj = JS_NewObject(cx, js_class, NULL, NULL); + if (!js_wrapper_obj) + goto done; + + /* Create private, native portion of JavaObject */ + java_wrapper = + (JavaObjectWrapper *)JS_malloc(cx, sizeof(JavaObjectWrapper)); + if (!java_wrapper) { + jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor); + goto done; + } + JS_SetPrivate(cx, js_wrapper_obj, java_wrapper); + java_wrapper->class_descriptor = class_descriptor; + java_wrapper->members = NULL; + + java_obj = (*jEnv)->NewGlobalRef(jEnv, java_obj); + java_wrapper->java_obj = java_obj; + if (!java_obj) + goto out_of_memory; + + + /* Add the JavaObject to the hash table */ + he = JSJ_HashTableRawAdd(java_obj_reflections, hep, hash_code, + java_obj, js_wrapper_obj, (void*)jEnv); + if (!he) { + (*jEnv)->DeleteGlobalRef(jEnv, java_obj); + goto out_of_memory; + } + +done: +#ifdef JS_THREADSAFE + PR_ExitMonitor(java_obj_reflections_monitor); +#endif + + return js_wrapper_obj; + +out_of_memory: + /* No need to free js_wrapper_obj, as it will be finalized by GC. */ + JS_ReportOutOfMemory(cx); + js_wrapper_obj = NULL; + goto done; +} + +static void +remove_java_obj_reflection_from_hashtable(jobject java_obj, JNIEnv *jEnv) +{ + JSJHashNumber hash_code; + JSJHashEntry *he, **hep; + + hash_code = jsj_HashJavaObject((void*)java_obj, (void*)jEnv); + +#ifdef JS_THREADSAFE + PR_EnterMonitor(java_obj_reflections_monitor); +#endif + + hep = JSJ_HashTableRawLookup(java_obj_reflections, hash_code, + java_obj, (void*)jEnv); + he = *hep; + + PR_ASSERT(he); + if (he) + JSJ_HashTableRawRemove(java_obj_reflections, hep, he, (void*)jEnv); + +#ifdef JS_THREADSAFE + PR_ExitMonitor(java_obj_reflections_monitor); +#endif +} + +void +JavaObject_finalize(JSContext *cx, JSObject *obj) +{ + JavaObjectWrapper *java_wrapper; + jobject java_obj; + JNIEnv *jEnv; + + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return; + + java_wrapper = JS_GetPrivate(cx, obj); + if (!java_wrapper) + return; + java_obj = java_wrapper->java_obj; + + remove_java_obj_reflection_from_hashtable(java_obj, jEnv); + + (*jEnv)->DeleteGlobalRef(jEnv, java_obj); + jsj_ReleaseJavaClassDescriptor(cx, jEnv, java_wrapper->class_descriptor); + /* FIXME - Delete JavaMemberValues */ + /* if (java_wrapper->invoke_java_method_func_obj) + JS_RemoveRoot(cx, &java_wrapper->invoke_java_method_func_obj); */ + JS_free(cx, java_wrapper); +} + +/* Trivial helper for jsj_DiscardJavaObjReflections(), below */ +static PRIntn +enumerate_remove_java_obj(JSJHashEntry *he, PRIntn i, void *arg) +{ + JNIEnv *jEnv = (JNIEnv*)arg; + jobject java_obj; + + java_obj = (jobject)he->key; + (*jEnv)->DeleteGlobalRef(jEnv, java_obj); + return HT_ENUMERATE_REMOVE; +} + +/* This shutdown routine discards all JNI references to Java objects + that have been reflected into JS, even if there are still references + to them from JS. */ +void +jsj_DiscardJavaObjReflections(JNIEnv *jEnv) +{ + JSJ_HashTableEnumerateEntries(java_obj_reflections, + enumerate_remove_java_obj, + (void*)jEnv); +} + +PR_CALLBACK JSBool +JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + JavaObjectWrapper *java_wrapper; + JavaClassDescriptor *class_descriptor; + jobject java_obj; + JNIEnv *jEnv; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + java_wrapper = JS_GetPrivate(cx, obj); + if (!java_wrapper) { + if (type == JSTYPE_OBJECT) { + *vp = OBJECT_TO_JSVAL(obj); + return JS_TRUE; + } + + JS_ReportError(cx, "illegal operation on JavaObject prototype object"); + return JS_FALSE; + } + + java_obj = java_wrapper->java_obj; + class_descriptor = java_wrapper->class_descriptor; + + switch (type) { + case JSTYPE_OBJECT: + *vp = OBJECT_TO_JSVAL(obj); + return JS_TRUE; + + case JSTYPE_FUNCTION: + JS_ReportError(cx, "can't convert Java object to function"); + return JS_FALSE; + + case JSTYPE_VOID: + case JSTYPE_STRING: + /* Either extract a C-string from the java.lang.String object + or call the Java toString() method */ + return jsj_ConvertJavaObjectToJSString(cx, jEnv, class_descriptor, java_obj, vp); + + case JSTYPE_NUMBER: + /* Call Java doubleValue() method, if applicable */ + return jsj_ConvertJavaObjectToJSNumber(cx, jEnv, java_obj, vp); + + case JSTYPE_BOOLEAN: + /* Call booleanValue() method, if applicable */ + return jsj_ConvertJavaObjectToJSBoolean(cx, jEnv, java_obj, vp); + + default: + PR_ASSERT(0); + return JS_FALSE; + } +} + +static JSBool +lookup_member_by_id(JSContext *cx, JNIEnv *jEnv, JSObject *obj, + JavaObjectWrapper **java_wrapperp, + jsid id, JavaMemberVal **memberp, + JavaMemberDescriptor **member_descriptorp) +{ + jsval idval; + JavaMemberVal *member, **prev_memberp; + JavaObjectWrapper *java_wrapper; + JavaMemberDescriptor *member_descriptor; + const char *member_name, *property_name; + JavaClassDescriptor *class_descriptor; + + java_wrapper = JS_GetPrivate(cx, obj); + if (!java_wrapper) { + if (JS_IdToValue(cx, id, &idval) && JSVAL_IS_STRING(idval) && + (property_name = JS_GetStringBytes(JSVAL_TO_STRING(idval))) != NULL) { + if (!strcmp(property_name, "constructor")) { + *java_wrapperp = NULL; + *member_descriptorp = NULL; + return JS_TRUE; + } + } + JS_ReportError(cx, "illegal operation on JavaObject prototype object"); + return JS_FALSE; + } + + class_descriptor = java_wrapper->class_descriptor; + PR_ASSERT(class_descriptor->type == JAVA_SIGNATURE_CLASS || + class_descriptor->type == JAVA_SIGNATURE_ARRAY); + + /* THREADSAFETY - not thread-safe */ + prev_memberp = &java_wrapper->members; + for (member = *prev_memberp; member; member = member->next) { + member_descriptor = member->descriptor; + if (member_descriptor->id == id) { + *prev_memberp = member->next; + member->next = java_wrapper->members; + break; + } + } + if (!member) { + JSFunction *function; + JSObject *function_obj; + + member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); + if (member_descriptor && member_descriptor->methods) { + member = (JavaMemberVal*)JS_malloc(cx, sizeof(JavaMemberVal)); + if (!member) + return JS_FALSE; + JS_IdToValue(cx, id, &idval); + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + + /* printf("Adding %s\n", member_name); */ + + /* TODO - eliminate JSFUN_BOUND_METHOD */ + /* TODO - Use JS_CloneFunction() to save memory */ + function = JS_NewFunction(cx, jsj_JavaInstanceMethodWrapper, 0, + JSFUN_BOUND_METHOD, obj, member_name); + if (!function) { + JS_free(cx, member); + return JS_FALSE; + } + function_obj = JS_GetFunctionObject(function); + member->invoke_method_func_val = OBJECT_TO_JSVAL(function_obj); + member->descriptor = member_descriptor; + member->next = NULL; + JS_AddRoot(cx, &member->invoke_method_func_val); + } + } + + /* Place member at head of list of members for faster access next time */ + if (member) { + member->next = java_wrapper->members; + java_wrapper->members = member; + } + + if (!member_descriptor) { + JS_IdToValue(cx, id, &idval); + if (!JSVAL_IS_STRING(idval)) { + JS_ReportError(cx, "invalid JavaObject property expression. " + "(methods and field properties of a JavaObject object can only be strings)"); + return JS_FALSE; + } + + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + + JS_ReportError(cx, "Java class %s has no public instance field or " + "method named \"%s\"", + class_descriptor->name, member_name); + return JS_FALSE; + } + + /* Success. Handle the multiple return values */ + if (java_wrapperp) + *java_wrapperp = java_wrapper; + if (memberp) + *memberp = member; + if (member_descriptorp) + *member_descriptorp = member_descriptor; + return JS_TRUE; +} + +PR_CALLBACK JSBool +JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + jobject java_obj; + JavaMemberDescriptor *member_descriptor; + JavaMemberVal *member; + JavaObjectWrapper *java_wrapper; + JNIEnv *jEnv; + + /* printf("In JavaObject_getProperty\n"); */ + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, &member, &member_descriptor)) + return JS_FALSE; + + /* Handle access to "constructor" property of prototype object with + silent failure. */ + if (!member_descriptor) { + *vp = JSVAL_VOID; + return JS_TRUE; + } + + java_obj = java_wrapper->java_obj; + if (member_descriptor->field) { + if (!member_descriptor->methods) { + return jsj_GetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, vp); + } else { + PR_ASSERT(0); + } + } else { + *vp = member->invoke_method_func_val; + return JS_TRUE; + } +} + +PR_STATIC_CALLBACK(JSBool) +JavaObject_setPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + jobject java_obj; + const char *member_name; + JavaObjectWrapper *java_wrapper; + JavaClassDescriptor *class_descriptor; + JavaMemberDescriptor *member_descriptor; + jsval idval; + JNIEnv *jEnv; + + /* printf("In JavaObject_setProperty\n"); */ + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (!lookup_member_by_id(cx, jEnv, obj, &java_wrapper, id, NULL, &member_descriptor)) + return JS_FALSE; + + /* Check for the case where there is a method with the give name, but no field + with that name */ + if (!member_descriptor->field) + goto no_such_field; + + /* Silently fail if field value is final (immutable), as required by ECMA spec */ + if (member_descriptor->field->modifiers & ACC_FINAL) + return JS_TRUE; + + java_obj = java_wrapper->java_obj; + return jsj_SetJavaFieldValue(cx, jEnv, member_descriptor->field, java_obj, *vp); + +no_such_field: + JS_IdToValue(cx, id, &idval); + member_name = JS_GetStringBytes(JSVAL_TO_STRING(idval)); + class_descriptor = java_wrapper->class_descriptor; + JS_ReportError(cx, "No instance field named \"%s\" in Java class %s", + member_name, class_descriptor->name); + return JS_FALSE; +} + +PR_CALLBACK JSBool +JavaObject_enumerate(JSContext *cx, JSObject *obj) +{ + JavaObjectWrapper *java_wrapper; + JavaClassDescriptor *class_descriptor; + JavaMemberDescriptor *member_descriptor; + JNIEnv *jEnv; + +/* printf("In JavaObject_enumerate\n"); */ + + java_wrapper = JS_GetPrivate(cx, obj); + + /* Check if this is the prototype object */ + if (!java_wrapper) + return JS_TRUE; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + class_descriptor = java_wrapper->class_descriptor; + member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor); + while (member_descriptor) { + JS_DefineProperty(cx, obj, member_descriptor->name, JSVAL_VOID, 0, 0, + JSPROP_PERMANENT|JSPROP_ENUMERATE); + member_descriptor = member_descriptor->next; + } + return JS_TRUE; +} + + +static JSBool +JavaObject_lookupProperty(JSContext *cx, JSObject *obj, jsid id, + JSObject **objp, JSProperty **propp +#if defined JS_THREADSAFE && defined DEBUG + , const char *file, uintN line +#endif + ) +{ + JNIEnv *jEnv; + + /* printf("In JavaObject_lookupProperty()\n"); */ + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + if (!lookup_member_by_id(cx, jEnv, obj, NULL, id, NULL, NULL)) + return JS_FALSE; + *objp = obj; + *propp = (JSProperty*)1; + return JS_TRUE; +} + +static JSBool +JavaObject_defineProperty(JSContext *cx, JSObject *obj, jsid id, jsval value, + JSPropertyOp getter, JSPropertyOp setter, + uintN attrs, JSProperty **propp) +{ + JS_ReportError(cx, "Cannot define a new property in a JavaObject"); + return JS_FALSE; +} + +static JSBool +JavaObject_getAttributes(JSContext *cx, JSObject *obj, jsid id, + JSProperty *prop, uintN *attrsp) +{ + /* We don't maintain JS property attributes for Java class members */ + *attrsp = JSPROP_PERMANENT|JSPROP_ENUMERATE; + return JS_FALSE; +} + +static JSBool +JavaObject_setAttributes(JSContext *cx, JSObject *obj, jsid id, + JSProperty *prop, uintN *attrsp) +{ + /* We don't maintain JS property attributes for Java class members */ + if (*attrsp != JSPROP_PERMANENT|JSPROP_ENUMERATE) { + PR_ASSERT(0); + return JS_FALSE; + } + + /* Silently ignore all setAttribute attempts */ + return JS_TRUE; +} + +static JSBool +JavaObject_deleteProperty(JSContext *cx, JSObject *obj, jsid id, jsval *vp) +{ + JSVersion version = JS_GetVersion(cx); + + *vp = JSVAL_FALSE; + + if (!JSVERSION_IS_ECMA(version)) { + JS_ReportError(cx, "Properties of JavaObject objects may not be deleted"); + return JS_FALSE; + } else { + /* Attempts to delete permanent properties are silently ignored + by ECMAScript. */ + return JS_TRUE; + } +} + +static JSBool +JavaObject_defaultValue(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + /* printf("In JavaObject_defaultValue()\n"); */ + return JavaObject_convert(cx, obj, JSTYPE_STRING, vp); +} + +static JSBool +JavaObject_newEnumerate(JSContext *cx, JSObject *obj, JSIterateOp enum_op, + jsval *statep, jsid *idp) +{ + JavaObjectWrapper *java_wrapper; + JavaMemberDescriptor *member_descriptor; + JavaClassDescriptor *class_descriptor; + JNIEnv *jEnv; + + java_wrapper = JS_GetPrivate(cx, obj); + /* Check for prototype object */ + if (!java_wrapper) { + *statep = JSVAL_NULL; + if (idp) + *idp = INT_TO_JSVAL(0); + return JS_TRUE; + } + + class_descriptor = java_wrapper->class_descriptor; + + switch(enum_op) { + case JSENUMERATE_INIT: + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor); + *statep = PRIVATE_TO_JSVAL(member_descriptor); + if (idp) + *idp = INT_TO_JSVAL(class_descriptor->num_instance_members); + return JS_TRUE; + + case JSENUMERATE_NEXT: + member_descriptor = JSVAL_TO_PRIVATE(*statep); + if (member_descriptor) { + *idp = member_descriptor->id; + *statep = PRIVATE_TO_JSVAL(member_descriptor->next); + return JS_TRUE; + } + + /* Fall through ... */ + + case JSENUMERATE_DESTROY: + *statep = JSVAL_NULL; + return JS_TRUE; + + default: + PR_ASSERT(0); + return JS_FALSE; + } +} + +static JSBool +JavaObject_checkAccess(JSContext *cx, JSObject *obj, jsid id, + JSAccessMode mode, jsval *vp, uintN *attrsp) +{ + switch (mode) { + case JSACC_WATCH: + JS_ReportError(cx, "Cannot place watchpoints on JavaObject object properties"); + return JS_FALSE; + + case JSACC_IMPORT: + JS_ReportError(cx, "Cannot export a JavaObject object's properties"); + return JS_FALSE; + + default: + return JS_TRUE; + } +} + +JSObjectOps JavaObject_ops = { + /* Mandatory non-null function pointer members. */ + NULL, /* newObjectMap */ + NULL, /* destroyObjectMap */ + JavaObject_lookupProperty, + JavaObject_defineProperty, + JavaObject_getPropertyById, /* getProperty */ + JavaObject_setPropertyById, /* setProperty */ + JavaObject_getAttributes, + JavaObject_setAttributes, + JavaObject_deleteProperty, + JavaObject_defaultValue, + JavaObject_newEnumerate, + JavaObject_checkAccess, + + /* Optionally non-null members start here. */ + NULL, /* thisObject */ + NULL, /* dropProperty */ + NULL, /* call */ + NULL, /* construct */ + NULL, /* xdrObject */ + NULL, /* hasInstance */ +}; + +static JSObjectOps * +JavaObject_getObjectOps(JSContext *cx, JSClass *clazz) +{ + return &JavaObject_ops; +} + +JSClass JavaObject_class = { + "JavaObject", JSCLASS_HAS_PRIVATE, + NULL, NULL, NULL, NULL, + NULL, NULL, JavaObject_convert, JavaObject_finalize, + JavaObject_getObjectOps, +}; + +extern PR_IMPORT_DATA(JSObjectOps) js_ObjectOps; + + +JSBool +jsj_init_JavaObject(JSContext *cx, JSObject *global_obj) +{ + JavaObject_ops.newObjectMap = js_ObjectOps.newObjectMap; + JavaObject_ops.destroyObjectMap = js_ObjectOps.destroyObjectMap; + + if (!JS_InitClass(cx, global_obj, + 0, &JavaObject_class, 0, 0, + 0, 0, + 0, 0)) + return JS_FALSE; + + return init_java_obj_reflections_table(); +} diff --git a/mozilla/js/src/liveconnect/jsj_JavaPackage.c b/mozilla/js/src/liveconnect/jsj_JavaPackage.c new file mode 100644 index 00000000000..8f0f9d6d5c9 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_JavaPackage.c @@ -0,0 +1,504 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the native code implementation of the JavaPackage class. + * + * A JavaPackage is JavaScript's representation of a Java package. The + * JavaPackage object contains only a string, which is the path to the package, + * e.g. "java/lang". The JS properties of a JavaPackage are either nested packages + * or a JavaClass object, which represents the path to a Java class. + * + * Note that there is no equivalent to a JavaPackage object in Java. Example: + * Although there are instances of java.lang.String and there are static methods + * of java.lang.String that can be invoked, there's no such thing as a java.lang + * object in Java that exists at run time. + * + */ + +#include +#include + +#include "prtypes.h" +#include "prprf.h" + +#ifdef XP_MAC +#include "prosdep.h" +#endif + +#include "jsj_private.h" /* LiveConnect internals */ +#include "jsjava.h" + + +JSClass JavaPackage_class; /* Forward declaration */ + +/* + * The native part of a JavaPackage object. It gets stored in the object's + * private slot. + */ +typedef struct { + const char * path; /* e.g. "java/lang" or NULL if top level package */ + int flags; /* e.g. PKG_SYSTEM, PKG_CLASS */ +} JavaPackage_Private; + +static JSObject * +define_JavaPackage(JSContext *cx, JSObject *parent_obj, + const char *obj_name, const char *path, int flags) +{ + JSObject *package_obj; + JavaPackage_Private *package; + + package_obj = JS_DefineObject(cx, parent_obj, obj_name, &JavaPackage_class, 0, + JSPROP_PERMANENT | JSPROP_READONLY); + if (!package_obj) + return NULL; + + /* Attach private, native data to the JS object */ + package = (JavaPackage_Private *)JS_malloc(cx, sizeof(JavaPackage_Private)); + JS_SetPrivate(cx, package_obj, (void *)package); + if (path) + package->path = JS_strdup(cx, path); + else + package->path = ""; + + package->flags = flags; + + /* Check for OOM */ + if (!package->path) { + JS_DeleteProperty(cx, parent_obj, obj_name); + JS_free(cx, package); + return NULL; + } + + return package_obj; +} + +/* JavaPackage uses standard JS getProperty */ + +/* + * Don't allow user-defined properties to be set on Java package objects, e.g. + * it is illegal to write "java.lang.myProperty = 4". We probably could relax + * this restriction, but it's potentially confusing and not clearly useful. + */ +static JSBool +JavaPackage_setProperty(JSContext *cx, JSObject *obj, jsval slot, jsval *vp) +{ + JavaPackage_Private *package = JS_GetPrivate(cx, obj); + if (!package) { + JS_ReportError(cx, "illegal attempt to add property to " + "JavaPackage prototype object"); + return JS_FALSE; + } + JS_ReportError(cx, "You may not add properties to a JavaPackage object"); + return JS_FALSE; +} + +static JSBool quiet_resolve_failure; + +/* + * Resolve a component name to be either the name of a class or a package. + */ +static JSBool +JavaPackage_resolve(JSContext *cx, JSObject *obj, jsval id) +{ + JavaPackage_Private *package; + JSBool ok = JS_TRUE; + jclass jclazz; + char *subPath, *newPath; + const char *path; + JNIEnv *jEnv; + + package = (JavaPackage_Private *)JS_GetPrivate(cx, obj); + if (!package) + return JS_TRUE; + + if (!JSVAL_IS_STRING(id)) + return JS_TRUE; + subPath = JS_GetStringBytes(JSVAL_TO_STRING(id)); + + /* + * There will be an attempt to invoke the toString() method when producing + * the string representation of a JavaPackage. When this occurs, avoid + * creating a bogus toString package. (This means that no one can ever + * create a package with the simple name "toString", but we'll live with + * that limitation.) + */ + if (!strcmp(subPath, "toString")) + return JS_FALSE; + + path = package->path; + newPath = PR_smprintf("%s%s%s", path, (path[0] ? "/" : ""), subPath); + if (!newPath) { + JS_ReportOutOfMemory(cx); + return JS_FALSE; + } + + jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + /* + Unfortunately, Java provides no way to find out whether a particular + name is a package or not. The only way to tell is to try to load the + name as a class file and, if that fails, assume it's a package. This + makes things work as expected for the most part, but it has three + noticeable problems that keep coming up: + + - You can refer to a package like java.lang.i.buried.paul without + generating a complaint. Of course, you'll never be able to refer to + any classes through it. + + - An annoying consequence of the above is that misspelling a class name + results in a cryptic error about packages. + + - In a browser context, i.e. where applets are involved, figuring out + whether something is a class may require looking for it over the net + using the current classloader. This means that the first time you + refer to java.lang.System in a js context, there will be an attempt + to search for [[DOCBASE]]/java.class on the server. + + A solution is to explicitly tell jsjava the names of all the (local) + packages on the CLASSPATH. (Not implemented yet.) + + */ + jclazz = (*jEnv)->FindClass(jEnv, newPath); + if (jclazz) { + JSObject *newClass; + + newClass = jsj_define_JavaClass(cx, jEnv, obj, subPath, jclazz); + if (!newClass) { + ok = JS_FALSE; + goto out; + } + } else { + /* beard: if an exception occurred, shouldn't this clear it? */ + if ((*jEnv)->ExceptionOccurred(jEnv)) + (*jEnv)->ExceptionClear(jEnv); + + /* + * If there's no class of the given name, then we must be referring to + * a package. However, don't allow bogus sub-packages of pre-defined + * system packages to be created. + */ + if (JS_InstanceOf(cx, obj, &JavaPackage_class, NULL)) { + JavaPackage_Private *package; + + package = JS_GetPrivate(cx, obj); + if (package->flags & PKG_SYSTEM) { + char *msg, *cp; + + /* Painful hack for pre_define_java_packages() */ + if (quiet_resolve_failure) + return JS_FALSE; + + msg = PR_smprintf("No Java system package with name \"%s\" was identified " + "and no Java class with that name exists either", + newPath); + + /* Check for OOM */ + if (msg) { + /* Convert package of form "java/lang" to "java.lang" */ + for (cp = msg; *cp != '\0'; cp++) + if (*cp == '/') + *cp = '.'; + JS_ReportError(cx, msg); + free((char*)msg); + } + + return JS_FALSE; + } + } + + /* Painful hack for pre_define_java_packages() */ + if (quiet_resolve_failure) + return JS_FALSE; + + if (!define_JavaPackage(cx, obj, subPath, newPath, 0)) { + ok = JS_FALSE; + goto out; + } + +#ifdef DEBUG + /* printf("JavaPackage \'%s\' created\n", newPath); */ +#endif + + } + +out: + free(newPath); + return ok; +} + +static JSBool +JavaPackage_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + JSString *str; + char *name, *cp; + + JavaPackage_Private *package = JS_GetPrivate(cx, obj); + if (!package) { + fprintf(stderr, "JavaPackage_resolve: no private data!\n"); + return JS_FALSE; + } + + switch (type) { + + /* Pretty-printing of JavaPackage */ + case JSTYPE_VOID: /* Default value */ + case JSTYPE_NUMBER: + case JSTYPE_STRING: + /* Convert '/' to '.' so that it looks like Java language syntax. */ + if (!package->path) + break; + name = PR_smprintf("[JavaPackage %s]", package->path); + if (!name) { + JS_ReportOutOfMemory(cx); + return JS_FALSE; + } + for (cp = name; *cp != '\0'; cp++) + if (*cp == '/') + *cp = '.'; + str = JS_NewString(cx, name, strlen(name)); + if (!str) { + free(name); + /* It's not necessary to call JS_ReportOutOfMemory(), as + JS_NewString() will do so on failure. */ + return JS_FALSE; + } + + *vp = STRING_TO_JSVAL(str); + break; + + case JSTYPE_OBJECT: + *vp = OBJECT_TO_JSVAL(obj); + break; + + default: + break; + } + return JS_TRUE; +} + +/* + * Free the private native data associated with the JavaPackage object. + */ +static void +JavaPackage_finalize(JSContext *cx, JSObject *obj) +{ + JavaPackage_Private *package = JS_GetPrivate(cx, obj); + if (!package) + return; + + if (package->path) + JS_free(cx, (char *)package->path); + JS_free(cx, package); +} + +/* + * The definition of the JavaPackage class + */ +JSClass JavaPackage_class = { + "JavaPackage", JSCLASS_HAS_PRIVATE, + JS_PropertyStub, JS_PropertyStub, JS_PropertyStub, JavaPackage_setProperty, + JS_EnumerateStub, JavaPackage_resolve, + JavaPackage_convert, JavaPackage_finalize +}; + +JavaPackageDef +standard_java_packages[] = { + {"java", NULL, PKG_USER}, + {"java.applet", NULL, PKG_USER}, + {"java.awt", NULL, PKG_USER}, + {"java.awt.datatransfer", + NULL, PKG_SYSTEM}, + {"java.awt.event", NULL, PKG_SYSTEM}, + {"java.awt.image", NULL, PKG_SYSTEM}, + {"java.awt.peer", NULL, PKG_SYSTEM}, + {"java.beans", NULL, PKG_USER}, + {"java.io", NULL, PKG_SYSTEM}, + {"java.lang", NULL, PKG_USER}, + {"java.lang.reflect", NULL, PKG_SYSTEM}, + {"java.math", NULL, PKG_SYSTEM}, + {"java.net", NULL, PKG_USER}, + {"java.rmi", NULL, PKG_USER}, + {"java.rmi.dgc", NULL, PKG_USER}, + {"java.rmi.user", NULL, PKG_USER}, + {"java.rmi.registry", NULL, PKG_USER}, + {"java.rmi.server", NULL, PKG_USER}, + {"java.security", NULL, PKG_USER}, + {"java.security.acl", NULL, PKG_SYSTEM}, + {"java.security.interfaces", + NULL, PKG_SYSTEM}, + {"java.sql", NULL, PKG_USER}, + {"java.text", NULL, PKG_USER}, + {"java.text.resources", NULL, PKG_SYSTEM}, + {"java.util", NULL, PKG_USER}, + {"java.util.zip", NULL, PKG_SYSTEM}, + + {"netscape", NULL, PKG_USER}, + {"netscape.applet", NULL, PKG_SYSTEM}, + {"netscape.application",NULL, PKG_SYSTEM}, + {"netscape.debug", NULL, PKG_SYSTEM}, + {"netscape.javascript", NULL, PKG_SYSTEM}, + {"netscape.ldap", NULL, PKG_SYSTEM}, + {"netscape.misc", NULL, PKG_SYSTEM}, + {"netscape.net", NULL, PKG_SYSTEM}, + {"netscape.plugin", NULL, PKG_SYSTEM}, + {"netscape.util", NULL, PKG_SYSTEM}, + {"netscape.secfile", NULL, PKG_SYSTEM}, + {"netscape.security", NULL, PKG_SYSTEM}, + {"netscape.WAI", NULL, PKG_SYSTEM}, + + {"sun", NULL, PKG_USER}, + {"Packages", "", PKG_USER}, + 0 +}; + +/* + * Pre-define a hierarchy of JavaPackage objects. + * Pre-defining a Java package at initialization time is not necessary, but + * it will make package lookup faster and, more importantly, will avoid + * unnecessary network accesses if classes are being loaded over the network. + */ +static JSBool +pre_define_java_packages(JSContext *cx, JSObject *global_obj, + JavaPackageDef *predefined_packages) +{ + JSBool package_exists; + JSObject *parent_obj; + JavaPackageDef *package_def; + char *simple_name, *cp, *package_name, *path; + int flags; + + if (!predefined_packages) + return JS_TRUE; + + /* Iterate over all pre-defined Java packages */ + for (package_def = predefined_packages; package_def->name; package_def++) { + package_name = path = NULL; + + parent_obj = global_obj; + package_name = strdup(package_def->name); + if (!package_name) + goto out_of_memory; + + /* Walk the chain of JavaPackage objects to get to the parent of the + rightmost sub-package in the fully-qualified package name. */ + for (simple_name = strtok(package_name, "."); 1; simple_name = strtok(NULL, ".")) { + jsval v; + + if (!simple_name) { + JS_ReportError(cx, "Package %s defined twice ?", package_name); + goto error; + } + + /* Check to see if the sub-package already exists */ + quiet_resolve_failure = JS_TRUE; + package_exists = JS_LookupProperty(cx, parent_obj, simple_name, &v) && JSVAL_IS_OBJECT(v); + quiet_resolve_failure = JS_FALSE; + + if (package_exists) { + parent_obj = JSVAL_TO_OBJECT(v); + continue; + } else { + /* New package objects should only be created at the terminal + sub-package in a fully-qualified package-name */ + if (strtok(NULL, ".")) { + JS_ReportError(cx, "Illegal predefined package definition for %s", + package_def->name); + goto error; + } + + if (package_def->path) { + path = strdup(package_def->path); + if (!path) + goto out_of_memory; + } else { + + /* + * The default path is specified, so create it from the + * fully-qualified package name. + */ + path = strdup(package_def->name); + if (!path) + goto out_of_memory; + /* Transform package name, e.g. "java.lang" ==> "java/lang" */ + for (cp = path; *cp != '\0'; cp++) { + if (*cp == '.') + *cp = '/'; + } + } + flags = package_def->flags; + parent_obj = define_JavaPackage(cx, parent_obj, simple_name, path, flags); + if (!parent_obj) + goto error; + + free(path); + break; + } + } + free(package_name); + } + return JS_TRUE; + +out_of_memory: + JS_ReportOutOfMemory(cx); + +error: + JS_FREE_IF(cx, package_name); + JS_FREE_IF(cx, path); + return JS_FALSE; +} + +static JSBool +JavaPackage_toString(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, + jsval *rval) +{ + if (!JS_InstanceOf(cx, obj, &JavaPackage_class, argv)) + return JS_FALSE; + return JavaPackage_convert(cx, obj, JSTYPE_STRING, rval); +} + +static JSFunctionSpec JavaPackage_methods[] = { + {"toString", JavaPackage_toString, 0}, + {0} +}; + +/* + * One-time initialization for the JavaPackage class. (This is not + * run once per thread, rather it's run once for a given JSContext.) + */ +JSBool +jsj_init_JavaPackage(JSContext *cx, JSObject *global_obj, + JavaPackageDef *additional_predefined_packages) { + + /* Define JavaPackage class */ + if (!JS_InitClass(cx, global_obj, 0, &JavaPackage_class, + 0, 0, 0, JavaPackage_methods, 0, 0)) + return JS_FALSE; + + /* Add top-level packages, e.g. : java, netscape, sun */ + if (!pre_define_java_packages(cx, global_obj, standard_java_packages)) + return JS_FALSE; + if (!pre_define_java_packages(cx, global_obj, additional_predefined_packages)) + return JS_FALSE; + + return JS_TRUE; +} diff --git a/mozilla/js/src/liveconnect/jsj_array.c b/mozilla/js/src/liveconnect/jsj_array.c new file mode 100644 index 00000000000..b88776f98b0 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_array.c @@ -0,0 +1,183 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the code for reading and writing elements of a Java array. + */ + +#include "prtypes.h" +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ + +/* + * Read the Java value at a given index into a Java array and convert it + * to a JS value. The array_component_signature describes the type of + * the resulting Java value, which can be a primitive type or an object type. + * More specifically it can be an array type in the case of multidimensional + * arrays. + */ +JSBool +jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index, + JavaSignature *array_component_signature, + jsval *vp) +{ + jvalue java_value; + JavaSignatureChar component_type; + +#define GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \ + (*jEnv)->Get##Type##ArrayRegion(jEnv, java_array, index, 1, \ + &java_value.member); \ + if ((*jEnv)->ExceptionOccurred(jEnv)) { \ + jsj_ReportJavaError(cx, jEnv, "Error reading element of " \ + "Java primitive array"); \ + return JS_FALSE; \ + } + + component_type = array_component_signature->type; + switch(component_type) { + case JAVA_SIGNATURE_BYTE: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b); + break; + + case JAVA_SIGNATURE_CHAR: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c); + break; + + case JAVA_SIGNATURE_SHORT: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s); + break; + + case JAVA_SIGNATURE_INT: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i); + break; + + case JAVA_SIGNATURE_BOOLEAN: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z); + break; + + case JAVA_SIGNATURE_LONG: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j); + break; + + case JAVA_SIGNATURE_FLOAT: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f); + break; + + case JAVA_SIGNATURE_DOUBLE: + GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d); + break; + + case JAVA_SIGNATURE_CLASS: + case JAVA_SIGNATURE_ARRAY: + java_value.l = (*jEnv)->GetObjectArrayElement(jEnv, java_array, index); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_ReportJavaError(cx, jEnv, "Error reading Java object array"); + return JS_FALSE; + } + break; + +#undef GET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY + default: + PR_ASSERT(0); /* Unknown java type signature */ + return JS_FALSE; + } + + return jsj_ConvertJavaValueToJSValue(cx, jEnv, array_component_signature, &java_value, vp); +} + +JSBool +jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, jsize index, + JavaSignature *array_component_signature, + jsval js_val) +{ + int dummy_cost; + jvalue java_value; + JavaSignatureChar component_type; + JSBool is_local_ref; + + if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, array_component_signature, + &dummy_cost, &java_value, &is_local_ref)) + return JS_FALSE; + +#define SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Type,member) \ + (*jEnv)->Set##Type##ArrayRegion(jEnv, java_array, index, 1, \ + &java_value.member); \ + if ((*jEnv)->ExceptionOccurred(jEnv)) { \ + jsj_ReportJavaError(cx, jEnv, "Error assigning to element of " \ + "Java primitive array"); \ + return JS_FALSE; \ + } + + component_type = array_component_signature->type; + switch(component_type) { + case JAVA_SIGNATURE_BYTE: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Byte,b); + break; + + case JAVA_SIGNATURE_CHAR: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Char,c); + break; + + case JAVA_SIGNATURE_SHORT: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Short,s); + break; + + case JAVA_SIGNATURE_INT: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Int,i); + break; + + case JAVA_SIGNATURE_BOOLEAN: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Boolean,z); + break; + + case JAVA_SIGNATURE_LONG: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Long,j); + break; + + case JAVA_SIGNATURE_FLOAT: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Float,f); + break; + + case JAVA_SIGNATURE_DOUBLE: + SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY(Double,d); + break; + + case JAVA_SIGNATURE_CLASS: + case JAVA_SIGNATURE_ARRAY: + (*jEnv)->SetObjectArrayElement(jEnv, java_array, index, java_value.l); + if (is_local_ref) \ + (*jEnv)->DeleteLocalRef(jEnv, java_value.l); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_ReportJavaError(cx, jEnv, "Error assigning to Java object array"); + return JS_FALSE; + } + break; + +#undef SET_ELEMENT_FROM_PRIMITIVE_JAVA_ARRAY + default: + PR_ASSERT(0); /* Unknown java type signature */ + return JS_FALSE; + } + + return JS_TRUE; +} + diff --git a/mozilla/js/src/liveconnect/jsj_class.c b/mozilla/js/src/liveconnect/jsj_class.c new file mode 100644 index 00000000000..a7e9a862f7b --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_class.c @@ -0,0 +1,598 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the code that constructs and manipulates JavaClassDescriptor + * structs, which are the native wrappers for Java classes. + * JavaClassDescriptors are used to describe the signatures of methods and + * fields. There is a JavaClassDescriptor associated with the reflection of + * each Java Object. + */ + +#include +#include + +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ + +#include "jsj_hash.h" /* Hash tables */ + +/* A one-to-one mapping between all referenced java.lang.Class objects and + their corresponding JavaClassDescriptor objects */ +static JSJHashTable *java_class_reflections; + +/* + * Given a JVM handle to a java.lang.Class object, malloc a C-string + * containing the UTF8 encoding of the fully qualified name of the class. + * It's the caller's responsibility to free the returned string. + * + * If an error occurs, NULL is returned and the error reporter called. + */ +const char * +jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class) +{ + jstring java_class_name_jstr; + const char *java_class_name; + + /* Get java.lang.String object containing class name */ + java_class_name_jstr = + (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getName); + + + if (!java_class_name_jstr) + goto error; + + /* Convert to UTF8 encoding and copy */ + java_class_name = jsj_DupJavaStringUTF(cx, jEnv, java_class_name_jstr); + if (!java_class_name) + return NULL; + + return java_class_name; + +error: + jsj_UnexpectedJavaError(cx, jEnv, "Can't get Java class name using" + "java.lang.Class.getName()"); + return NULL; +} + +/* + * Convert in-place a string of the form "java.lang.String" into "java/lang/String". + * Though the former style is conventionally used by Java programmers, the latter is + * what the JNI functions require. + */ +void +jsj_MakeJNIClassname(char * class_name) +{ + char * c; + for (c = class_name; *c; c++) + if (*c == '.') + *c = '/'; +} + +/* + * Classify an instance of java.lang.Class as either one of the primitive + * types, e.g. int, char, etc., as an array type or as a non-array object type + * (subclass of java.lang.Object) by returning the appropriate enum member. + * + */ +static JavaSignatureChar +get_signature_type(JSContext *cx, JavaClassDescriptor *class_descriptor) +{ + JavaSignatureChar type; + const char *java_class_name; + + /* Get UTF8 encoding of class name */ + java_class_name = class_descriptor->name; + PR_ASSERT(java_class_name); + if (!java_class_name) + return JAVA_SIGNATURE_UNKNOWN; + + if (!strcmp(java_class_name, "byte")) + type = JAVA_SIGNATURE_BYTE; + else if (!strcmp(java_class_name, "char")) + type = JAVA_SIGNATURE_CHAR; + else if (!strcmp(java_class_name, "float")) + type = JAVA_SIGNATURE_FLOAT; + else if (!strcmp(java_class_name, "double")) + type = JAVA_SIGNATURE_DOUBLE; + else if (!strcmp(java_class_name, "int")) + type = JAVA_SIGNATURE_INT; + else if (!strcmp(java_class_name, "long")) + type = JAVA_SIGNATURE_LONG; + else if (!strcmp(java_class_name, "short")) + type = JAVA_SIGNATURE_SHORT; + else if (!strcmp(java_class_name, "boolean")) + type = JAVA_SIGNATURE_BOOLEAN; + else if (!strcmp(java_class_name, "void")) + type = JAVA_SIGNATURE_VOID; + else + /* Well, I guess it's a Java class, then. */ + type = JAVA_SIGNATURE_CLASS; + + return type; +} + +static JSBool +is_java_array_class(JNIEnv *jEnv, jclass java_class) +{ + return (*jEnv)->CallBooleanMethod(jEnv, java_class, jlClass_isArray); +} + +/* + * Return the class of a Java array's component type. This is not the same + * as the array's element type. For example, the component type of an array + * of type SomeType[][][] is SomeType[][], but its element type is SomeType. + * + * If an error occurs, NULL is returned and an error reported. + */ +static jclass +get_java_array_component_class(JSContext *cx, JNIEnv *jEnv, jclass java_class) +{ + jclass result; + result = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getComponentType); + if (!result) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't get Java array component class using " + "java.lang.Class.getComponentType()"); + return NULL; + } + return result; +} + +/* + * Given a Java class, fill in the signature structure that describes the class. + * If an error occurs, JS_FALSE is returned and the error reporter called. + */ +static JSBool +compute_java_class_signature(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature) +{ + jclass java_class = signature->java_class; + + if (is_java_array_class(jEnv, java_class)) { + jclass component_class; + + signature->type = JAVA_SIGNATURE_ARRAY; + + component_class = get_java_array_component_class(cx, jEnv, java_class); + if (!component_class) + return JS_FALSE; + + signature->array_component_signature = + jsj_GetJavaClassDescriptor(cx, jEnv, component_class); + if (!signature->array_component_signature) + return JS_FALSE; + } else { + signature->type = get_signature_type(cx, signature); + } + return JS_TRUE; +} + +/* + * Convert a JavaSignature object into a string format as used by + * the JNI functions, e.g. java.lang.Object ==> "Ljava/lang/Object;" + * The caller is responsible for freeing the resulting string. + * + * If an error is encountered, NULL is returned and an error reported. + */ +const char * +jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature) +{ + char *sig; + + if (signature->type == JAVA_SIGNATURE_CLASS) { + /* A non-array object class */ + sig = PR_smprintf("L%s;", signature->name); + if (sig) + jsj_MakeJNIClassname(sig); + + } else if (signature->type == JAVA_SIGNATURE_ARRAY) { + /* An array class */ + const char *component_signature_string; + + component_signature_string = + jsj_ConvertJavaSignatureToString(cx, signature->array_component_signature); + if (!component_signature_string) + return NULL; + sig = PR_smprintf("[%s", component_signature_string); + JS_free(cx, (char*)component_signature_string); + + } else { + /* A primitive class */ + sig = PR_smprintf("%c", (char)signature->type); + } + + if (!sig) { + JS_ReportOutOfMemory(cx); + return NULL; + } + return sig; +} + +/* + * Convert a JavaSignature object into a human-readable string format as seen + * in Java source files, e.g. "byte", or "int[][]" or "java.lang.String". + * The caller is responsible for freeing the resulting string. + * + * If an error is encountered, NULL is returned and an error reported. + */ +const char * +jsj_ConvertJavaSignatureToHRString(JSContext *cx, + JavaSignature *signature) +{ + char *sig; + JavaSignature *acs; + + if (signature->type == JAVA_SIGNATURE_ARRAY) { + /* An array class */ + const char *component_signature_string; + acs = signature->array_component_signature; + component_signature_string = + jsj_ConvertJavaSignatureToHRString(cx, acs); + if (!component_signature_string) + return NULL; + sig = PR_smprintf("%s[]", component_signature_string); + JS_free(cx, (char*)component_signature_string); + + } else { + /* A primitive class or a non-array object class */ + sig = JS_strdup(cx, signature->name); + } + + if (!sig) { + JS_ReportOutOfMemory(cx); + return NULL; + } + return sig; +} + +static void +destroy_java_member_descriptor(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor) +{ + JavaMethodSpec *method, *next_method; + if (member_descriptor->field) + jsj_DestroyFieldSpec(cx, jEnv, member_descriptor->field); + + method = member_descriptor->methods; + while (method) { + next_method = method->next; + jsj_DestroyMethodSpec(cx, jEnv, method); + method = next_method; + } +} + +static void +destroy_class_member_descriptors(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor) +{ + JavaMemberDescriptor *next_member; + + while (member_descriptor) { + next_member = member_descriptor->next; + destroy_java_member_descriptor(cx, jEnv, member_descriptor); + member_descriptor = next_member; + } +} + +static void +destroy_class_descriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor) +{ + JS_FREE_IF(cx, (char *)class_descriptor->name); + if (class_descriptor->java_class) { + JSJ_HashTableRemove(java_class_reflections, + class_descriptor->java_class, (void*)jEnv); + (*jEnv)->DeleteGlobalRef(jEnv, class_descriptor->java_class); + } + + if (class_descriptor->array_component_signature) + jsj_ReleaseJavaClassDescriptor(cx, jEnv, class_descriptor->array_component_signature); + + destroy_class_member_descriptors(cx, jEnv, class_descriptor->instance_members); + destroy_class_member_descriptors(cx, jEnv, class_descriptor->static_members); + destroy_class_member_descriptors(cx, jEnv, class_descriptor->constructors); + JS_free(cx, class_descriptor); +} + +static JavaClassDescriptor * +new_class_descriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class) +{ + JavaClassDescriptor *class_descriptor; + + class_descriptor = (JavaClassDescriptor *)JS_malloc(cx, sizeof(JavaClassDescriptor)); + if (!class_descriptor) + return NULL; + memset(class_descriptor, 0, sizeof(JavaClassDescriptor)); + + class_descriptor->name = jsj_GetJavaClassName(cx, jEnv, java_class); + if (!class_descriptor->name) + goto error; + + java_class = (*jEnv)->NewGlobalRef(jEnv, java_class); + if (!java_class) { + jsj_ReportJavaError(cx, jEnv, "Unable to reference Java class"); + goto error; + } + class_descriptor->java_class = java_class; + + if (!compute_java_class_signature(cx, jEnv, class_descriptor)) + goto error; + + class_descriptor->modifiers = + (*jEnv)->CallIntMethod(jEnv, java_class, jlClass_getModifiers); + class_descriptor->ref_count = 1; + + if (!JSJ_HashTableAdd(java_class_reflections, java_class, class_descriptor, + (void*)jEnv)) + goto error; + + return class_descriptor; + +error: + destroy_class_descriptor(cx, jEnv, class_descriptor); + return NULL; +} + +/* Trivial helper for jsj_DiscardJavaClassReflections(), below */ +static PRIntn +enumerate_remove_java_class(JSJHashEntry *he, PRIntn i, void *arg) +{ + JNIEnv *jEnv = (JNIEnv*)arg; + jclass java_class; + + java_class = (jclass)he->key; + (*jEnv)->DeleteGlobalRef(jEnv, java_class); + return HT_ENUMERATE_REMOVE; +} + +/* This shutdown routine discards all JNI references to Java objects + that have been reflected into JS, even if there are still references + to them from JS. */ +void +jsj_DiscardJavaClassReflections(JNIEnv *jEnv) +{ + JSJ_HashTableEnumerateEntries(java_class_reflections, + enumerate_remove_java_class, + (void*)jEnv); +} + +extern JavaClassDescriptor * +jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class) +{ + JavaClassDescriptor *class_descriptor; + class_descriptor = JSJ_HashTableLookup(java_class_reflections, + (const void *)java_class, + (void*)jEnv); + if (!class_descriptor) + return new_class_descriptor(cx, jEnv, java_class); + + PR_ASSERT(class_descriptor->ref_count > 0); + class_descriptor->ref_count++; + return class_descriptor; +} + +void +jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor) +{ + if (!--class_descriptor->ref_count) + destroy_class_descriptor(cx, jEnv, class_descriptor); +} + +static JSBool +reflect_java_methods_and_fields(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + JSBool reflect_statics_only) +{ + JavaMemberDescriptor *member_descriptor; + + if (reflect_statics_only) + class_descriptor->static_members_reflected = JS_TRUE; + else + class_descriptor->instance_members_reflected = JS_TRUE; + + if (!jsj_ReflectJavaMethods(cx, jEnv, class_descriptor, reflect_statics_only)) + return JS_FALSE; + if (!jsj_ReflectJavaFields(cx, jEnv, class_descriptor, reflect_statics_only)) + return JS_FALSE; + + if (reflect_statics_only) { + member_descriptor = class_descriptor->static_members; + while (member_descriptor) { + class_descriptor->num_static_members++; + member_descriptor = member_descriptor->next; + } + } else { + member_descriptor = class_descriptor->instance_members; + while (member_descriptor) { + class_descriptor->num_instance_members++; + member_descriptor = member_descriptor->next; + } + } + return JS_TRUE; +} + +JavaMemberDescriptor * +jsj_GetClassStaticMembers(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor) +{ + if (!class_descriptor->static_members_reflected) + reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE); + return class_descriptor->static_members; +} + +JavaMemberDescriptor * +jsj_GetClassInstanceMembers(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor) +{ + if (!class_descriptor->instance_members_reflected) + reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_FALSE); + return class_descriptor->instance_members; +} + +JavaMemberDescriptor * +jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jsid id) +{ + JavaMemberDescriptor *member_descriptor; + + member_descriptor = jsj_GetClassStaticMembers(cx, jEnv, class_descriptor); + while (member_descriptor) { + if (id == member_descriptor->id) + return member_descriptor; + member_descriptor = member_descriptor->next; + } + return NULL; +} + +JavaMemberDescriptor * +jsj_GetJavaStaticMemberDescriptor(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jstring member_name_jstr) +{ + JavaMemberDescriptor *member_descriptor; + jsid id; + + if (!JavaStringToId(cx, jEnv, member_name_jstr, &id)) + return NULL; + + member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); + if (member_descriptor) + return member_descriptor; + + member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); + if (!member_descriptor) + return NULL; + memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); + + member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr); + if (!member_descriptor->name) { + JS_free(cx, member_descriptor); + return NULL; + } + member_descriptor->id = id; + + member_descriptor->next = class_descriptor->static_members; + class_descriptor->static_members = member_descriptor; + + return member_descriptor; +} + +JavaMemberDescriptor * +jsj_GetJavaClassConstructors(JSContext *cx, + JavaClassDescriptor *class_descriptor) +{ + JavaMemberDescriptor *member_descriptor; + + if (class_descriptor->constructors) + return class_descriptor->constructors; + + member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); + if (!member_descriptor) + return NULL; + memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); + + member_descriptor->name = JS_strdup(cx, ""); + if (!member_descriptor->name) { + JS_free(cx, member_descriptor); + return NULL; + } + + class_descriptor->constructors = member_descriptor; + + return member_descriptor; +} + +JavaMemberDescriptor * +jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor) +{ + if (!class_descriptor->static_members_reflected) + reflect_java_methods_and_fields(cx, jEnv, class_descriptor, JS_TRUE); + return class_descriptor->constructors; +} + +JavaMemberDescriptor * +jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jsid id) +{ + JavaMemberDescriptor *member_descriptor; + + member_descriptor = jsj_GetClassInstanceMembers(cx, jEnv, class_descriptor); + while (member_descriptor) { + if (id == member_descriptor->id) + return member_descriptor; + member_descriptor = member_descriptor->next; + } + return NULL; +} + +JavaMemberDescriptor * +jsj_GetJavaMemberDescriptor(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jstring member_name_jstr) +{ + JavaMemberDescriptor *member_descriptor; + jsid id; + + if (!JavaStringToId(cx, jEnv, member_name_jstr, &id)) + return NULL; + + member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); + if (member_descriptor) + return member_descriptor; + + member_descriptor = JS_malloc(cx, sizeof(JavaMemberDescriptor)); + if (!member_descriptor) + return NULL; + memset(member_descriptor, 0, sizeof(JavaMemberDescriptor)); + + member_descriptor->name = jsj_DupJavaStringUTF(cx, jEnv, member_name_jstr); + if (!member_descriptor->name) { + JS_free(cx, member_descriptor); + return NULL; + } + member_descriptor->id = id; + + member_descriptor->next = class_descriptor->instance_members; + class_descriptor->instance_members = member_descriptor; + + return member_descriptor; +} + +JSBool +jsj_InitJavaClassReflectionsTable() +{ + java_class_reflections = + JSJ_NewHashTable(64, jsj_HashJavaObject, jsj_JavaObjectComparator, + NULL, NULL, NULL); + + if (!java_class_reflections) + return JS_FALSE; + return JS_TRUE; +} diff --git a/mozilla/js/src/liveconnect/jsj_convert.c b/mozilla/js/src/liveconnect/jsj_convert.c new file mode 100644 index 00000000000..5abf3c8a2f1 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_convert.c @@ -0,0 +1,772 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * Below is the code that converts between Java and JavaScript values of all + * types. + */ + +#include +#include + +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ + +/* Floating-point double utilities, stolen from jsnum.h */ +#ifdef IS_LITTLE_ENDIAN +#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[1]) +#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[0]) +#else +#define JSDOUBLE_HI32(x) (((uint32 *)&(x))[0]) +#define JSDOUBLE_LO32(x) (((uint32 *)&(x))[1]) +#endif +#define JSDOUBLE_HI32_SIGNBIT 0x80000000 +#define JSDOUBLE_HI32_EXPMASK 0x7ff00000 +#define JSDOUBLE_HI32_MANTMASK 0x000fffff + +#define JSDOUBLE_IS_NaN(x) \ + ((JSDOUBLE_HI32(x) & JSDOUBLE_HI32_EXPMASK) == JSDOUBLE_HI32_EXPMASK && \ + (JSDOUBLE_LO32(x) || (JSDOUBLE_HI32(x) & JSDOUBLE_HI32_MANTMASK))) + +#define JSDOUBLE_IS_INFINITE(x) \ + ((JSDOUBLE_HI32(x) & ~JSDOUBLE_HI32_SIGNBIT) == JSDOUBLE_HI32_EXPMASK && \ + !JSDOUBLE_LO32(x)) + +static JSBool +convert_js_obj_to_JSObject_wrapper(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj, + JavaSignature *signature, + int *cost, jobject *java_value) +{ + if (!njJSObject) { + if (java_value) + JS_ReportError(cx, "Couldn't convert JavaScript object to an " + "instance of netscape.javascript.JSObject " + "because that class could not be loaded."); + return JS_FALSE; + } + + if (!(*jEnv)->IsAssignableFrom(jEnv, njJSObject, signature->java_class)) + return JS_FALSE; + + if (!java_value) + return JS_TRUE; + + *java_value = jsj_WrapJSObject(cx, jEnv, js_obj); + + return (*java_value != NULL); +} + +jstring +jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str) +{ + jstring result; + result = (*jEnv)->NewString(jEnv, JS_GetStringChars(js_str), + JS_GetStringLength(js_str)); + if (!result) { + jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance " + "of java.lang.String"); + } + return result; +} + +/* + * Convert a JS value to an instance of java.lang.Object or one of its subclasses, + * performing any necessary type coercion. If non-trivial coercion is required, + * the cost value is incremented. If the java_value pass-by-reference argument + * is non-NULL, the resulting Java value is stored there. + * + * Returns JS_TRUE if the conversion is possible, JS_FALSE otherwise + */ +JSBool +jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, + int *cost, jobject *java_value, JSBool *is_local_refp) +{ + JSString *jsstr; + jclass target_java_class; + + PR_ASSERT(signature->type == JAVA_SIGNATURE_CLASS || + signature->type == JAVA_SIGNATURE_ARRAY); + + /* Initialize to default case, in which no new Java object is + synthesized to perform the conversion and, therefore, no JNI local + references are being held. */ + *is_local_refp = JS_FALSE; + + /* Get the Java type of the target value */ + target_java_class = signature->java_class; + + if (JSVAL_IS_OBJECT(v)) { + JSObject *js_obj = JSVAL_TO_OBJECT(v); + + /* JS null is always assignable to a Java object */ + if (!js_obj) { + if (java_value) + *java_value = NULL; + return JS_TRUE; + } + + if (JS_InstanceOf(cx, js_obj, &JavaObject_class, 0) || + JS_InstanceOf(cx, js_obj, &JavaArray_class, 0)) { + + /* The source value is a Java object wrapped inside a JavaScript + object. Unwrap the JS object and return the original Java + object if it's class makes it assignment-compatible with the + target class using Java's assignability rules. */ + JavaObjectWrapper *java_wrapper = JS_GetPrivate(cx, js_obj); + jobject java_obj = java_wrapper->java_obj; + + if ((*jEnv)->IsInstanceOf(jEnv, java_obj, target_java_class)) { + if (java_value) + *java_value = java_obj; + return JS_TRUE; + } + +#ifdef LIVECONNECT_IMPROVEMENTS + /* Don't allow wrapped Java objects to be converted to strings */ + goto conversion_error; +#else + /* Fall through, to attempt conversion to a Java string */ +#endif + + } else if (JS_InstanceOf(cx, js_obj, &JavaClass_class, 0)) { + /* We're dealing with the reflection of a Java class */ + JavaClassDescriptor *java_class_descriptor = JS_GetPrivate(cx, js_obj); + + /* Check if target type is java.lang.Class class */ + if ((*jEnv)->IsAssignableFrom(jEnv, jlClass, target_java_class)) { + if (java_value) + *java_value = java_class_descriptor->java_class; + return JS_TRUE; + } + + /* Check if target type is netscape.javascript.JSObject wrapper class */ + if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) + return JS_TRUE; + + /* Fall through, to attempt conversion to a Java string */ + + } else if (JS_TypeOfValue(cx, v) == JSTYPE_FUNCTION) { + /* JS functions can be wrapped as a netscape.javascript.JSObject */ + if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) + return JS_TRUE; + + /* That didn't work, so fall through, to attempt conversion to + a java.lang.String ... */ + + /* Check for a Java object wrapped inside a JS object */ + } else { + /* Otherwise, see if the target type is the netscape.javascript.JSObject + wrapper class or one of its subclasses, in which case a + reference is passed to the original JS object by wrapping it + inside an instance of netscape.javascript.JSObject */ + if (convert_js_obj_to_JSObject_wrapper(cx, jEnv, js_obj, signature, cost, java_value)) + return JS_TRUE; + + /* Fall through, to attempt conversion to a Java string */ + } + + } else if (JSVAL_IS_NUMBER(v)) { + /* JS numbers, integral or not, can be converted to instances of java.lang.Double */ + if ((*jEnv)->IsAssignableFrom(jEnv, jlDouble, target_java_class)) { + if (java_value) { + jsdouble d; + if (!JS_ValueToNumber(cx, v, &d)) + goto conversion_error; + *java_value = (*jEnv)->NewObject(jEnv, jlDouble, jlDouble_Double, d); + if (*java_value) { + *is_local_refp = JS_TRUE; + } else { + jsj_UnexpectedJavaError(cx, jEnv, + "Couldn't construct instance of java.lang.Double"); + return JS_FALSE; + } + } +#ifdef LIVECONNECT_IMPROVEMENTS + (*cost)++; +#endif + return JS_TRUE; + } + /* Fall through, to attempt conversion to a java.lang.String ... */ + + } else if (JSVAL_IS_BOOLEAN(v)) { + /* JS boolean values can be converted to instances of java.lang.Boolean */ + if ((*jEnv)->IsAssignableFrom(jEnv, jlBoolean, target_java_class)) { + if (java_value) { + JSBool b; + if (!JS_ValueToBoolean(cx, v, &b)) + goto conversion_error; + *java_value = + (*jEnv)->NewObject(jEnv, jlBoolean, jlBoolean_Boolean, b); + if (*java_value) { + *is_local_refp = JS_TRUE; + } else { + jsj_UnexpectedJavaError(cx, jEnv, "Couldn't construct instance " + "of java.lang.Boolean"); + return JS_FALSE; + } + } +#ifdef LIVECONNECT_IMPROVEMENTS + (*cost)++; +#endif + return JS_TRUE; + } + /* Fall through, to attempt conversion to a java.lang.String ... */ + } + + /* If no other conversion is possible, see if the target type is java.lang.String */ + if ((*jEnv)->IsAssignableFrom(jEnv, jlString, target_java_class)) { + JSBool is_string = JSVAL_IS_STRING(v); + + /* Convert to JS string, if necessary, and then to a Java Unicode string */ + jsstr = JS_ValueToString(cx, v); + if (jsstr) { + if (java_value) { + *java_value = jsj_ConvertJSStringToJavaString(cx, jEnv, jsstr); + if (*java_value) { + *is_local_refp = JS_TRUE; + } else { + return JS_FALSE; + } + } +#ifdef LIVECONNECT_IMPROVEMENTS + if (!is_string) + (*cost)++; +#endif + return JS_TRUE; + } + } + +conversion_error: + return JS_FALSE; +} + +/* Utility macro for jsj_ConvertJSValueToJavaValue(), below */ +#define JSVAL_TO_INTEGRAL_JVALUE(type_name, member_name, member_type, jsval, java_value) \ +if (!JSVAL_IS_NUMBER(v)) { \ + if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) \ + goto conversion_error; \ + (*cost)++; \ + } \ + { \ + member_type member_name; \ + \ + if (JSVAL_IS_INT(v)) { \ + jsint ival = JSVAL_TO_INT(v); \ + member_name = (member_type) ival; \ + \ + /* Check to see if the jsval's magnitude is too large to be \ + representable in the target java type */ \ + if (member_name != ival) \ + goto conversion_error; \ + } else { \ + jdouble dval = *JSVAL_TO_DOUBLE(v); \ + if (JSDOUBLE_IS_NaN(dval)) \ + member_name = 0; \ + else \ + member_name = (member_type) dval; \ + \ + /* Don't allow a non-integral number to be converted \ + to an integral type */ \ + /* Actually, we have to allow this for LC1 compatibility */ \ + /* if ((jdouble)member_name != dval) \ + (*cost)++; */ \ + } \ + if (java_value) \ + java_value->member_name = member_name; \ + } + +#if XP_MAC + +/* on MRJ jlong is typedef'd to wide, which is a struct. */ +#include + +static jsint jlong_to_jsint(jlong lvalue) +{ + SInt64 val = WideToSInt64(lvalue); + return S32Set(val); +} + +static jlong jsint_to_jlong(jsint ivalue) +{ + SInt64 val = S64Set(ivalue); + wide wval =SInt64ToWide(val); + return *(jlong*)&wval; +} + +static jdouble jlong_to_jdouble(jlong lvalue) +{ + SInt64 val = WideToSInt64(lvalue); + return SInt64ToLongDouble(val); +} + +static jlong jdouble_to_jlong(jdouble dvalue) +{ + SInt64 val = LongDoubleToSInt64(dvalue); + wide wval = SInt64ToWide(val); + return *(jlong*)&wval; +} + +/* Mac utility macro for jsj_ConvertJSValueToJavaValue(), below */ +#define JSVAL_TO_JLONG_JVALUE(member_name, member_type, jsvalue, java_value) \ +if (!JSVAL_IS_NUMBER(jsvalue)) { \ + if (!JS_ConvertValue(cx, jsvalue, JSTYPE_NUMBER, &jsvalue)) \ + goto conversion_error; \ + (*cost)++; \ + } \ + { \ + member_type member_name; \ + \ + if (JSVAL_IS_INT(jsvalue)) { \ + jsint ival = JSVAL_TO_INT(jsvalue); \ + member_name = jsint_to_jlong(ival); \ + \ + } else { \ + jdouble dval = *JSVAL_TO_DOUBLE(jsvalue); \ + if (JSDOUBLE_IS_NaN(dval)) \ + member_name = jsint_to_jlong(0); \ + else \ + member_name = jdouble_to_jlong(dval); \ + \ + /* Don't allow a non-integral number to be converted \ + to an integral type */ \ + /* Actually, we have to allow this for LC1 compatibility */ \ + /*if (jlong_to_jdouble(member_name) != dval) \ + (*cost)++;*/ \ + } \ + if (java_value) \ + java_value->member_name = member_name; \ + } + +#else + +#define jlong_to_jdouble(lvalue) ((jdouble) lvalue) + +#endif + +/* + * Convert a JS value to a Java value of the given type signature. The cost + * variable is incremented if coercion is required, e.g. the source value is + * a string, but the target type is a boolean. + * + * Returns JS_FALSE if no conversion is possible, either because the jsval has + * a type that is wholly incompatible with the Java value, or because a scalar + * jsval can't be represented in a variable of the target type without loss of + * precision, e.g. the source value is "4.2" but the destination type is byte. + * If conversion is not possible and java_value is non-NULL, the JS error + * reporter is called with an appropriate message. + */ +JSBool +jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v, + JavaSignature *signature, + int *cost, jvalue *java_value, JSBool *is_local_refp) +{ + JavaSignatureChar type; + + /* Initialize to default case, in which no new Java object is + synthesized to perform the conversion and, therefore, no JNI local + references are being held. */ + *is_local_refp = JS_FALSE; + + type = signature->type; + switch (type) { + case JAVA_SIGNATURE_BOOLEAN: + if (!JSVAL_IS_BOOLEAN(v)) { + if (!JS_ConvertValue(cx, v, JSTYPE_BOOLEAN, &v)) + goto conversion_error; + (*cost)++; + } + if (java_value) + java_value->z = (jboolean)(JSVAL_TO_BOOLEAN(v) == JS_TRUE); + break; + + case JAVA_SIGNATURE_SHORT: + JSVAL_TO_INTEGRAL_JVALUE(short, s, jshort, v, java_value); + break; + + case JAVA_SIGNATURE_BYTE: + JSVAL_TO_INTEGRAL_JVALUE(byte, b, jbyte, v, java_value); + break; + + case JAVA_SIGNATURE_CHAR: + /* A one-character string can be converted into a character */ + if (JSVAL_IS_STRING(v) && (JS_GetStringLength(JSVAL_TO_STRING(v)) == 1)) { + v = INT_TO_JSVAL(*JS_GetStringChars(JSVAL_TO_STRING(v))); + } + JSVAL_TO_INTEGRAL_JVALUE(char, c, jchar, v, java_value); + break; + + case JAVA_SIGNATURE_INT: + JSVAL_TO_INTEGRAL_JVALUE(int, i, jint, v, java_value); + break; + + case JAVA_SIGNATURE_LONG: +#if XP_MAC + JSVAL_TO_JLONG_JVALUE(j, jlong, v, java_value); +#else + JSVAL_TO_INTEGRAL_JVALUE(long, j, jlong, v, java_value); +#endif + break; + + case JAVA_SIGNATURE_FLOAT: + if (!JSVAL_IS_NUMBER(v)) { + if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) + goto conversion_error; + (*cost)++; + } + if (java_value) { + if (JSVAL_IS_INT(v)) + java_value->f = (jfloat) JSVAL_TO_INT(v); + else + java_value->f = (jfloat) *JSVAL_TO_DOUBLE(v); + } + break; + + case JAVA_SIGNATURE_DOUBLE: + if (!JSVAL_IS_NUMBER(v)) { + if (!JS_ConvertValue(cx, v, JSTYPE_NUMBER, &v)) + goto conversion_error; + (*cost)++; + } + if (java_value) { + if (JSVAL_IS_INT(v)) + java_value->d = (jdouble) JSVAL_TO_INT(v); + else + java_value->d = (jdouble) *JSVAL_TO_DOUBLE(v); + } + break; + + case JAVA_SIGNATURE_CLASS: + case JAVA_SIGNATURE_ARRAY: + if (!jsj_ConvertJSValueToJavaObject(cx, jEnv, v, signature, cost, + &java_value->l, is_local_refp)) + goto conversion_error; + break; + + default: + PR_ASSERT(0); + return JS_FALSE; + } + + /* Success */ + return JS_TRUE; + +conversion_error: + + if (java_value) { + const char *jsval_string; + JSString *jsstr; + + jsval_string = NULL; + jsstr = JS_ValueToString(cx, v); + if (jsstr) + jsval_string = JS_GetStringBytes(jsstr); + if (!jsval_string) + jsval_string = ""; + + JS_ReportError(cx, "Unable to convert JavaScript value %s to " + "Java value of type %s", + jsval_string, signature->name); + } + return JS_FALSE; +} + +/* + * A utility routine to create a JavaScript Unicode string from a + * java.lang.String (Unicode) string. + */ +JSString * +jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str) +{ + JSString *js_str; + jboolean is_copy; + const jchar *ucs2_str; + jchar *copy_ucs2_str; + jsize ucs2_str_len, num_bytes; + + ucs2_str_len = (*jEnv)->GetStringLength(jEnv, java_str); + ucs2_str = (*jEnv)->GetStringChars(jEnv, java_str, &is_copy); + if (!ucs2_str) { + jsj_UnexpectedJavaError(cx, jEnv, + "Unable to extract native Unicode from Java string"); + return NULL; + } + + js_str = NULL; + + /* Unlike JS_NewString(), the string data passed into JS_NewUCString() is + not copied, so make a copy of the Unicode character vector. */ + num_bytes = ucs2_str_len * sizeof(jchar); + copy_ucs2_str = (jchar*)JS_malloc(cx, num_bytes); + if (!copy_ucs2_str) + goto done; + memcpy(copy_ucs2_str, ucs2_str, num_bytes); + + js_str = JS_NewUCString(cx, (jschar*)copy_ucs2_str, ucs2_str_len); + +done: + (*jEnv)->ReleaseStringChars(jEnv, java_str, ucs2_str); + return js_str; +} + +/* + * Attempt to obtain a JS string representation of a Java object. + * The java_obj argument must be of type java.lang.Object or a subclass. + * If java_obj is a Java string, it's value is simply extracted and + * copied into a JS string. Otherwise, the toString() method is called + * on java_obj. + */ +JSBool +jsj_ConvertJavaObjectToJSString(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jobject java_obj, jsval *vp) +{ + JSString *js_str; + jstring java_str; + jmethodID toString; + + /* Create a Java string, unless java_obj is already a java.lang.String */ + if ((*jEnv)->IsInstanceOf(jEnv, java_obj, jlString)) { + java_str = java_obj; + } else { + jclass java_class; + + java_class = class_descriptor->java_class; + toString = (*jEnv)->GetMethodID(jEnv, java_class, "toString", + "()Ljava/lang/String;"); + if (!toString) { + /* All Java objects have a toString method */ + jsj_UnexpectedJavaError(cx, jEnv, "No toString() method for class %s!", + class_descriptor->name); + return JS_FALSE; + } + java_str = (*jEnv)->CallObjectMethod(jEnv, java_obj, toString); + if (!java_str) { + jsj_ReportJavaError(cx, jEnv, "toString() method failed"); + return JS_FALSE; + } + } + + /* Extract Unicode from java.lang.String instance and convert to JS string */ + js_str = jsj_ConvertJavaStringToJSString(cx, jEnv, java_str); + if (!js_str) + return JS_FALSE; + + *vp = STRING_TO_JSVAL(js_str); + return JS_TRUE; +} + +/* + * Convert a Java object to a number by attempting to call the + * doubleValue() method on a Java object to get a double result. + * This usually only works on instances of java.lang.Double, but the code + * is generalized to work with any Java object that supports this method. + * + * Returns JS_TRUE if the call was successful. + * Returns JS_FALSE if conversion is not possible or an error occurs. + */ +JSBool +jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv, + jobject java_obj, jsval *vp) +{ + jdouble d; + jmethodID doubleValue; + +#ifndef SUN_VM_IS_NOT_GARBAGE + /* Late breaking news: calling GetMethodID() on an object that doesn't + contain the given method may cause the Sun VM to crash. So we only + call the method on instances of java.lang.Double */ + JSBool is_Double; + + /* Make sure that we have a java.lang.Double */ + is_Double = (*jEnv)->IsInstanceOf(jEnv, java_obj, jlDouble); + if (!is_Double) + return JS_FALSE; + doubleValue = jlDouble_doubleValue; +#else + doubleValue = (*jEnv)->GetMethodID(jEnv, java_obj, "doubleValue", "()D"); + if (!doubleValue) + return JS_FALSE; +#endif + + d = (*jEnv)->CallDoubleMethod(jEnv, java_obj, doubleValue); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, "doubleValue() method failed"); + return JS_FALSE; + } + return JS_NewDoubleValue(cx, d, vp); +} + +/* + * Convert a Java object to a boolean by attempting to call the + * booleanValue() method on a Java object to get a boolean result. + * This usually only works on instances of java.lang.Boolean, but the code + * is generalized to work with any Java object that supports this method. + * + * Returns JS_TRUE if the call was successful. + * Returns JS_FALSE if conversion is not possible or an error occurs. + */ +extern JSBool +jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv, + jobject java_obj, jsval *vp) +{ + jboolean b; + jmethodID booleanValue; + +#ifndef SUN_VM_IS_NOT_GARBAGE + /* Late breaking news: calling GetMethodID() on an object that doesn't + contain the given method may cause the Sun VM to crash. So we only + call the method on instances of java.lang.Boolean */ + + JSBool is_Boolean; + + /* Make sure that we have a java.lang.Boolean */ + is_Boolean = (*jEnv)->IsInstanceOf(jEnv, java_obj, jlBoolean); + if (!is_Boolean) + return JS_FALSE; + booleanValue = jlBoolean_booleanValue; +#else + booleanValue = (*jEnv)->GetMethodID(jEnv, java_obj, "booleanValue", "()Z"); + if (!booleanValue) + return JS_FALSE; +#endif + + b = (*jEnv)->CallBooleanMethod(jEnv, java_obj, booleanValue); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, "booleanValue() method failed"); + return JS_FALSE; + } + *vp = BOOLEAN_TO_JSVAL(b); + return JS_TRUE; +} + +/* + * Reflect a Java object into a JS value. The source object, java_obj, must + * be of type java.lang.Object or a subclass and may, therefore, be an array. + */ +JSBool +jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv, + jobject java_obj, jsval *vp) +{ + jclass java_class; + JSObject *js_obj; + + /* A null in Java-land is also null in JS */ + if (!java_obj) { + *vp = JSVAL_NULL; + return JS_TRUE; + } + + java_class = (*jEnv)->GetObjectClass(jEnv, java_obj); + + /* + * If it's an instance of netscape.javascript.JSObject, i.e. a wrapper + * around a JS object that has been passed into the Java world, unwrap + * it to obtain the original JS object. + */ + if (njJSObject && (*jEnv)->IsInstanceOf(jEnv, java_obj, njJSObject)) { + js_obj = (JSObject *)((*jEnv)->GetIntField(jEnv, java_obj, njJSObject_internal)); + PR_ASSERT(js_obj); + if (!js_obj) + return JS_FALSE; + *vp = OBJECT_TO_JSVAL(js_obj); + return JS_TRUE; + } + + /* + * Instances of java.lang.String are wrapped so we can call methods on + * them, but they convert to a JS string if used in a string context. + */ + /* TODO - let's get rid of this annoying "feature" */ + + /* otherwise, wrap it inside a JavaObject */ + js_obj = jsj_WrapJavaObject(cx, jEnv, java_obj, java_class); + if (!js_obj) + return JS_FALSE; + *vp = OBJECT_TO_JSVAL(js_obj); + return JS_TRUE; +} + +/* + * Convert a Java value (primitive or object) to a JS value. + * + * This is usually an infallible operation, but JS_FALSE is returned + * on an out-of-memory condition and the error reporter is called. + */ +JSBool +jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv, + JavaSignature *signature, + jvalue *java_value, + jsval *vp) +{ + int32 ival32; + + switch (signature->type) { + case JAVA_SIGNATURE_VOID: + *vp = JSVAL_VOID; + return JS_TRUE; + + case JAVA_SIGNATURE_BYTE: + *vp = INT_TO_JSVAL((jsint)java_value->b); + return JS_TRUE; + + case JAVA_SIGNATURE_CHAR: + *vp = INT_TO_JSVAL((jsint)java_value->c); + return JS_TRUE; + + case JAVA_SIGNATURE_SHORT: + *vp = INT_TO_JSVAL((jsint)java_value->s); + return JS_TRUE; + + case JAVA_SIGNATURE_INT: + ival32 = java_value->i; + if (INT_FITS_IN_JSVAL(ival32)) { + *vp = INT_TO_JSVAL((jsint) ival32); + return JS_TRUE; + } else { + return JS_NewDoubleValue(cx, ival32, vp); + } + + case JAVA_SIGNATURE_BOOLEAN: + *vp = BOOLEAN_TO_JSVAL((JSBool) java_value->z); + return JS_TRUE; + + case JAVA_SIGNATURE_LONG: + return JS_NewDoubleValue(cx, jlong_to_jdouble(java_value->j), vp); + + case JAVA_SIGNATURE_FLOAT: + return JS_NewDoubleValue(cx, java_value->f, vp); + + case JAVA_SIGNATURE_DOUBLE: + return JS_NewDoubleValue(cx, java_value->d, vp); + + case JAVA_SIGNATURE_CLASS: + case JAVA_SIGNATURE_ARRAY: + return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_value->l, vp); + + default: + PR_ASSERT(0); + return JS_FALSE; + } +} + diff --git a/mozilla/js/src/liveconnect/jsj_field.c b/mozilla/js/src/liveconnect/jsj_field.c new file mode 100644 index 00000000000..96e0b938c89 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_field.c @@ -0,0 +1,386 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the code used to reflect Java fields as properties of + * JavaObject objects and the code to access those fields. + * + */ + +#include +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#include "jsj_private.h" /* LiveConnect internals */ + +/* + * Add a single field, described by java_field, to the JavaMemberDescriptor + * named by field_name within the given JavaClassDescriptor. + * + * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. + */ +static JSBool +add_java_field_to_class_descriptor(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jstring field_name_jstr, + jobject java_field, /* a java.lang.reflect.Field */ + jint modifiers) +{ + jclass fieldType; + jfieldID fieldID; + jclass java_class; + + JSBool is_static_field; + JavaMemberDescriptor *member_descriptor = NULL; + const char *sig_cstr = NULL; + const char *field_name = NULL; + JavaSignature *signature = NULL; + JavaFieldSpec *field_spec = NULL; + + is_static_field = modifiers & ACC_STATIC; + if (is_static_field) { + member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); + } else { + member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, field_name_jstr); + } + if (!member_descriptor) + goto error; + + field_spec = (JavaFieldSpec*)JS_malloc(cx, sizeof(JavaFieldSpec)); + if (!field_spec) + goto error; + + field_spec->modifiers = modifiers; + + /* Get the Java class corresponding to the type of the field */ + fieldType = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getType); + if (!fieldType) { + jsj_UnexpectedJavaError(cx, jEnv, + "Unable to determine type of field using" + " java.lang.reflect.Field.getType()"); + goto error; + } + + signature = jsj_GetJavaClassDescriptor(cx, jEnv, fieldType); + if (!signature) + goto error; + field_spec->signature = signature; + + field_name = jsj_DupJavaStringUTF(cx, jEnv, field_name_jstr); + if (!field_name) + goto error; + field_spec->name = field_name; + + /* Compute the JNI-style (string-based) signature of the field type */ + sig_cstr = jsj_ConvertJavaSignatureToString(cx, signature); + if (!sig_cstr) + goto error; + + /* Compute the JNI fieldID and cache it for quick field access */ + java_class = class_descriptor->java_class; + if (is_static_field) + fieldID = (*jEnv)->GetStaticFieldID(jEnv, java_class, field_name, sig_cstr); + else + fieldID = (*jEnv)->GetFieldID(jEnv, java_class, field_name, sig_cstr); + if (!fieldID) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't get Java field ID for class %s, field %s (sig=%s)", + class_descriptor->name, field_name, sig_cstr); + goto error; + } + field_spec->fieldID = fieldID; + + JS_free(cx, (char*)sig_cstr); + + member_descriptor->field = field_spec; + + /* Success */ + return JS_TRUE; + +error: + if (field_spec) { + JS_FREE_IF(cx, (char*)field_spec->name); + JS_free(cx, field_spec); + } + JS_FREE_IF(cx, (char*)sig_cstr); + if (signature) + jsj_ReleaseJavaClassDescriptor(cx, jEnv, signature); + return JS_FALSE; +} + +/* + * Free up a JavaFieldSpec and all its resources. + */ +void +jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field) +{ + JS_FREE_IF(cx, (char*)field->name); + jsj_ReleaseJavaClassDescriptor(cx, jEnv, field->signature); + JS_free(cx, field); +} + +/* + * Add a JavaMemberDescriptor to the collection of members in class_descriptor + * for every public field of the identified Java class. (A separate collection + * is kept in class_descriptor for static and instance members.) + * If reflect_only_static_fields is set, instance fields are not reflected. If + * it isn't set, only instance fields are reflected and static fields are not + * reflected. + * + * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. + */ +JSBool +jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor, + JSBool reflect_only_static_fields) +{ + int i; + JSBool ok; + jint modifiers; + jobject java_field; + jstring field_name_jstr; + jarray joFieldArray; + jsize num_fields; + jclass java_class; + + /* Get a java array of java.lang.reflect.Field objects, by calling + java.lang.Class.getFields(). */ + java_class = class_descriptor->java_class; + joFieldArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getFields); + if (!joFieldArray) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't determine Java object's fields " + "using java.lang.Class.getFields()"); + return JS_FALSE; + } + + /* Iterate over the class fields */ + num_fields = (*jEnv)->GetArrayLength(jEnv, joFieldArray); + for (i = 0; i < num_fields; i++) { + + /* Get the i'th reflected field */ + java_field = (*jEnv)->GetObjectArrayElement(jEnv, joFieldArray, i); + if (!java_field) { + jsj_UnexpectedJavaError(cx, jEnv, "Can't access a Field[] array"); + return JS_FALSE; + } + + /* Get the field modifiers, e.g. static, public, private, etc. */ + modifiers = (*jEnv)->CallIntMethod(jEnv, java_field, jlrField_getModifiers); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't access a Field's modifiers using" + "java.lang.reflect.Field.getModifiers()"); + return JS_FALSE; + } + + /* Don't allow access to private or protected Java fields. */ + if (!(modifiers & ACC_PUBLIC)) + continue; + + /* Reflect all instance fields or all static fields, but not both */ + if (reflect_only_static_fields != ((modifiers & ACC_STATIC) != 0)) + continue; + + /* Determine the unqualified name of the field */ + field_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_field, jlrField_getName); + if (!field_name_jstr) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't obtain a Field's name" + "java.lang.reflect.Field.getName()"); + return JS_FALSE; + } + + /* Add a JavaFieldSpec object to the JavaClassDescriptor */ + ok = add_java_field_to_class_descriptor(cx, jEnv, class_descriptor, field_name_jstr, + java_field, modifiers); + if (!ok) + return JS_FALSE; + } + + /* Success */ + return JS_TRUE; +} + +/* + * Read the value of a Java field and return it as a JavaScript value. + * If the field is static, then java_obj is a Java class, otherwise + * it's a Java instance object. + * + * Returns JS_TRUE on success. Otherwise, returns JS_FALSE and reports an error. + */ +JSBool +jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, + jobject java_obj, jsval *vp) +{ + JSBool is_static_field; + jvalue java_value; + JavaSignature *signature; + JavaSignatureChar field_type; + jfieldID fieldID = field_spec->fieldID; + + is_static_field = field_spec->modifiers & ACC_STATIC; + +#define GET_JAVA_FIELD(Type,member) \ + PR_BEGIN_MACRO \ + if (is_static_field) \ + java_value.member = \ + (*jEnv)->GetStatic##Type##Field(jEnv, java_obj, fieldID); \ + else \ + java_value.member = \ + (*jEnv)->Get##Type##Field(jEnv, java_obj, fieldID); \ + if ((*jEnv)->ExceptionOccurred(jEnv)) { \ + jsj_ReportJavaError(cx, jEnv, "Error reading Java field"); \ + return JS_FALSE; \ + } \ + PR_END_MACRO + + signature = field_spec->signature; + field_type = signature->type; + switch(field_type) { + case JAVA_SIGNATURE_BYTE: + GET_JAVA_FIELD(Byte,b); + break; + + case JAVA_SIGNATURE_CHAR: + GET_JAVA_FIELD(Char,c); + break; + + case JAVA_SIGNATURE_SHORT: + GET_JAVA_FIELD(Short,s); + break; + + case JAVA_SIGNATURE_INT: + GET_JAVA_FIELD(Int,i); + break; + + case JAVA_SIGNATURE_BOOLEAN: + GET_JAVA_FIELD(Boolean,z); + break; + + case JAVA_SIGNATURE_LONG: + GET_JAVA_FIELD(Long,j); + break; + + case JAVA_SIGNATURE_FLOAT: + GET_JAVA_FIELD(Float,f); + break; + + case JAVA_SIGNATURE_DOUBLE: + GET_JAVA_FIELD(Double,d); + break; + + case JAVA_SIGNATURE_CLASS: + case JAVA_SIGNATURE_ARRAY: + GET_JAVA_FIELD(Object,l); + break; + +#undef GET_JAVA_FIELD + default: + PR_ASSERT(0); /* Unknown java type signature */ + return JS_FALSE; + } + + return jsj_ConvertJavaValueToJSValue(cx, jEnv, signature, &java_value, vp); +} + +JSBool +jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, + jclass java_obj, jsval js_val) +{ + JSBool is_static_field, is_local_ref; + int dummy_cost; + jvalue java_value; + JavaSignature *signature; + JavaSignatureChar field_type; + jfieldID fieldID = field_spec->fieldID; + + is_static_field = field_spec->modifiers & ACC_STATIC; + +#define SET_JAVA_FIELD(Type,member) \ + PR_BEGIN_MACRO \ + if (is_static_field) { \ + (*jEnv)->SetStatic##Type##Field(jEnv, java_obj, fieldID, \ + java_value.member); \ + } else { \ + (*jEnv)->Set##Type##Field(jEnv, java_obj, fieldID,java_value.member);\ + } \ + if ((*jEnv)->ExceptionOccurred(jEnv)) { \ + jsj_ReportJavaError(cx, jEnv, "Error assigning to Java field"); \ + return JS_FALSE; \ + } \ + PR_END_MACRO + + signature = field_spec->signature; + if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, js_val, signature, &dummy_cost, + &java_value, &is_local_ref)) + return JS_FALSE; + + field_type = signature->type; + switch(field_type) { + case JAVA_SIGNATURE_BYTE: + SET_JAVA_FIELD(Byte,b); + break; + + case JAVA_SIGNATURE_CHAR: + SET_JAVA_FIELD(Char,c); + break; + + case JAVA_SIGNATURE_SHORT: + SET_JAVA_FIELD(Short,s); + break; + + case JAVA_SIGNATURE_INT: + SET_JAVA_FIELD(Int,i); + break; + + case JAVA_SIGNATURE_BOOLEAN: + SET_JAVA_FIELD(Boolean,z); + break; + + case JAVA_SIGNATURE_LONG: + SET_JAVA_FIELD(Long,j); + break; + + case JAVA_SIGNATURE_FLOAT: + SET_JAVA_FIELD(Float,f); + break; + + case JAVA_SIGNATURE_DOUBLE: + SET_JAVA_FIELD(Double,d); + break; + + case JAVA_SIGNATURE_CLASS: + case JAVA_SIGNATURE_ARRAY: + SET_JAVA_FIELD(Object,l); + if (is_local_ref) + (*jEnv)->DeleteLocalRef(jEnv, java_value.l); + break; + +#undef SET_JAVA_FIELD + default: + PR_ASSERT(0); /* Unknown java type signature */ + return JS_FALSE; + } + + return JS_TRUE; +} diff --git a/mozilla/js/src/liveconnect/jsj_hash.c b/mozilla/js/src/liveconnect/jsj_hash.c new file mode 100644 index 00000000000..ab2aa15dc4a --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_hash.c @@ -0,0 +1,481 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This is a copy of the NSPR hash-table library, but it has been slightly + * modified to allow an additional argument to be passed into the hash + * key-comparision function. This is used to maintain thread-safety by + * passing in a JNIEnv pointer to the key-comparison function rather + * than storing it in a global. All types,function names, etc. have + * been renamed from their original NSPR names to protect the innocent. + */ + +#include "jsj_hash.h" +#include "prtypes.h" +#include "prlog.h" +#include +#include + +/* Compute the number of buckets in ht */ +#define NBUCKETS(ht) (1 << (JSJ_HASH_BITS - (ht)->shift)) + +/* The smallest table has 16 buckets */ +#define MINBUCKETSLOG2 4 +#define MINBUCKETS (1 << MINBUCKETSLOG2) + +/* Compute the maximum entries given n buckets that we will tolerate, ~90% */ +#define OVERLOADED(n) ((n) - ((n) >> 3)) + +/* Compute the number of entries below which we shrink the table by half */ +#define UNDERLOADED(n) (((n) > MINBUCKETS) ? ((n) >> 2) : 0) + +/* +** Stubs for default hash allocator ops. +*/ +static void * +DefaultAllocTable(void *pool, size_t size) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + return malloc(size); +} + +static void +DefaultFreeTable(void *pool, void *item) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + free(item); +} + +static JSJHashEntry * +DefaultAllocEntry(void *pool, const void *key) +{ +#if defined(XP_MAC) +#pragma unused (pool,key) +#endif + + return malloc(sizeof(JSJHashEntry)); +} + +static void +DefaultFreeEntry(void *pool, JSJHashEntry *he, PRUintn flag) +{ +#if defined(XP_MAC) +#pragma unused (pool) +#endif + + if (flag == HT_FREE_ENTRY) + free(he); +} + +static JSJHashAllocOps defaultHashAllocOps = { + DefaultAllocTable, DefaultFreeTable, + DefaultAllocEntry, DefaultFreeEntry +}; + +PR_IMPLEMENT(JSJHashTable *) +JSJ_NewHashTable(PRUint32 n, JSJHashFunction keyHash, + JSJHashComparator keyCompare, JSJHashComparator valueCompare, + JSJHashAllocOps *allocOps, void *allocPriv) +{ + JSJHashTable *ht; + PRUint32 nb; + + if (n <= MINBUCKETS) { + n = MINBUCKETSLOG2; + } else { + n = PR_CeilingLog2(n); + if ((PRInt32)n < 0) + return 0; + } + + if (!allocOps) allocOps = &defaultHashAllocOps; + + ht = (*allocOps->allocTable)(allocPriv, sizeof *ht); + if (!ht) + return 0; + memset(ht, 0, sizeof *ht); + ht->shift = JSJ_HASH_BITS - n; + n = 1 << n; +#if defined(XP_PC) && !defined(_WIN32) + if (n > 16000) { + (*allocOps->freeTable)(allocPriv, ht); + return 0; + } +#endif /* WIN16 */ + nb = n * sizeof(JSJHashEntry *); + ht->buckets = (*allocOps->allocTable)(allocPriv, nb); + if (!ht->buckets) { + (*allocOps->freeTable)(allocPriv, ht); + return 0; + } + memset(ht->buckets, 0, nb); + + ht->keyHash = keyHash; + ht->keyCompare = keyCompare; + ht->valueCompare = valueCompare; + ht->allocOps = allocOps; + ht->allocPriv = allocPriv; + return ht; +} + +PR_IMPLEMENT(void) +JSJ_HashTableDestroy(JSJHashTable *ht) +{ + PRUint32 i, n; + JSJHashEntry *he, *next; + JSJHashAllocOps *allocOps = ht->allocOps; + void *allocPriv = ht->allocPriv; + + n = NBUCKETS(ht); + for (i = 0; i < n; i++) { + for (he = ht->buckets[i]; he; he = next) { + next = he->next; + (*allocOps->freeEntry)(allocPriv, he, HT_FREE_ENTRY); + } + } +#ifdef DEBUG + memset(ht->buckets, 0xDB, n * sizeof ht->buckets[0]); +#endif + (*allocOps->freeTable)(allocPriv, ht->buckets); +#ifdef DEBUG + memset(ht, 0xDB, sizeof *ht); +#endif + (*allocOps->freeTable)(allocPriv, ht); +} + +/* +** Multiplicative hash, from Knuth 6.4. +*/ +#define GOLDEN_RATIO 0x9E3779B9U + +PR_IMPLEMENT(JSJHashEntry **) +JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg) +{ + JSJHashEntry *he, **hep, **hep0; + JSJHashNumber h; + +#ifdef HASHMETER + ht->nlookups++; +#endif + h = keyHash * GOLDEN_RATIO; + h >>= ht->shift; + hep = hep0 = &ht->buckets[h]; + while ((he = *hep) != 0) { + if (he->keyHash == keyHash && (*ht->keyCompare)(key, he->key, arg)) { + /* Move to front of chain if not already there */ + if (hep != hep0) { + *hep = he->next; + he->next = *hep0; + *hep0 = he; + } + return hep0; + } + hep = &he->next; +#ifdef HASHMETER + ht->nsteps++; +#endif + } + return hep; +} + +PR_IMPLEMENT(JSJHashEntry *) +JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep, + JSJHashNumber keyHash, const void *key, void *value, + void *arg) +{ + PRUint32 i, n; + JSJHashEntry *he, *next, **oldbuckets; + PRUint32 nb; + + /* Grow the table if it is overloaded */ + n = NBUCKETS(ht); + if (ht->nentries >= OVERLOADED(n)) { +#ifdef HASHMETER + ht->ngrows++; +#endif + ht->shift--; + oldbuckets = ht->buckets; +#if defined(XP_PC) && !defined(_WIN32) + if (2 * n > 16000) + return 0; +#endif /* WIN16 */ + nb = 2 * n * sizeof(JSJHashEntry *); + ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb); + if (!ht->buckets) { + ht->buckets = oldbuckets; + return 0; + } + memset(ht->buckets, 0, nb); + + for (i = 0; i < n; i++) { + for (he = oldbuckets[i]; he; he = next) { + next = he->next; + hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg); + PR_ASSERT(*hep == 0); + he->next = 0; + *hep = he; + } + } +#ifdef DEBUG + memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); +#endif + (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); + hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); + } + + /* Make a new key value entry */ + he = (*ht->allocOps->allocEntry)(ht->allocPriv, key); + if (!he) + return 0; + he->keyHash = keyHash; + he->key = key; + he->value = value; + he->next = *hep; + *hep = he; + ht->nentries++; + return he; +} + +PR_IMPLEMENT(JSJHashEntry *) +JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg) +{ + JSJHashNumber keyHash; + JSJHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key, arg); + hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); + if ((he = *hep) != 0) { + /* Hit; see if values match */ + if ((*ht->valueCompare)(he->value, value, arg)) { + /* key,value pair is already present in table */ + return he; + } + if (he->value) + (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_VALUE); + he->value = value; + return he; + } + return JSJ_HashTableRawAdd(ht, hep, keyHash, key, value, arg); +} + +PR_IMPLEMENT(void) +JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg) +{ + PRUint32 i, n; + JSJHashEntry *next, **oldbuckets; + PRUint32 nb; + + *hep = he->next; + (*ht->allocOps->freeEntry)(ht->allocPriv, he, HT_FREE_ENTRY); + + /* Shrink table if it's underloaded */ + n = NBUCKETS(ht); + if (--ht->nentries < UNDERLOADED(n)) { +#ifdef HASHMETER + ht->nshrinks++; +#endif + ht->shift++; + oldbuckets = ht->buckets; + nb = n * sizeof(JSJHashEntry*) / 2; + ht->buckets = (*ht->allocOps->allocTable)(ht->allocPriv, nb); + if (!ht->buckets) { + ht->buckets = oldbuckets; + return; + } + memset(ht->buckets, 0, nb); + + for (i = 0; i < n; i++) { + for (he = oldbuckets[i]; he; he = next) { + next = he->next; + hep = JSJ_HashTableRawLookup(ht, he->keyHash, he->key, arg); + PR_ASSERT(*hep == 0); + he->next = 0; + *hep = he; + } + } +#ifdef DEBUG + memset(oldbuckets, 0xDB, n * sizeof oldbuckets[0]); +#endif + (*ht->allocOps->freeTable)(ht->allocPriv, oldbuckets); + } +} + +PR_IMPLEMENT(PRBool) +JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg) +{ + JSJHashNumber keyHash; + JSJHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key, arg); + hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); + if ((he = *hep) == 0) + return PR_FALSE; + + /* Hit; remove element */ + JSJ_HashTableRawRemove(ht, hep, he, arg); + return PR_TRUE; +} + +PR_IMPLEMENT(void *) +JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg) +{ + JSJHashNumber keyHash; + JSJHashEntry *he, **hep; + + keyHash = (*ht->keyHash)(key, arg); + hep = JSJ_HashTableRawLookup(ht, keyHash, key, arg); + if ((he = *hep) != 0) { + return he->value; + } + return 0; +} + +/* +** Iterate over the entries in the hash table calling func for each +** entry found. Stop if "f" says to (return value & PR_ENUMERATE_STOP). +** Return a count of the number of elements scanned. +*/ +PR_IMPLEMENT(int) +JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg) +{ + JSJHashEntry *he, **hep; + PRUint32 i, nbuckets; + int rv, n = 0; + JSJHashEntry *todo = 0; + + nbuckets = NBUCKETS(ht); + for (i = 0; i < nbuckets; i++) { + hep = &ht->buckets[i]; + while ((he = *hep) != 0) { + rv = (*f)(he, n, arg); + n++; + if (rv & (HT_ENUMERATE_REMOVE | HT_ENUMERATE_UNHASH)) { + *hep = he->next; + if (rv & HT_ENUMERATE_REMOVE) { + he->next = todo; + todo = he; + } + } else { + hep = &he->next; + } + if (rv & HT_ENUMERATE_STOP) { + goto out; + } + } + } + +out: + hep = &todo; + while ((he = *hep) != 0) { + JSJ_HashTableRawRemove(ht, hep, he, arg); + } + return n; +} + +#ifdef HASHMETER +#include +#include + +PR_IMPLEMENT(void) +JSJ_HashTableDumpMeter(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp) +{ + double mean, variance; + PRUint32 nchains, nbuckets; + PRUint32 i, n, maxChain, maxChainLen; + JSJHashEntry *he; + + variance = 0; + nchains = 0; + maxChainLen = 0; + nbuckets = NBUCKETS(ht); + for (i = 0; i < nbuckets; i++) { + he = ht->buckets[i]; + if (!he) + continue; + nchains++; + for (n = 0; he; he = he->next) + n++; + variance += n * n; + if (n > maxChainLen) { + maxChainLen = n; + maxChain = i; + } + } + mean = (double)ht->nentries / nchains; + variance = fabs(variance / nchains - mean * mean); + + fprintf(fp, "\nHash table statistics:\n"); + fprintf(fp, " number of lookups: %u\n", ht->nlookups); + fprintf(fp, " number of entries: %u\n", ht->nentries); + fprintf(fp, " number of grows: %u\n", ht->ngrows); + fprintf(fp, " number of shrinks: %u\n", ht->nshrinks); + fprintf(fp, " mean steps per hash: %g\n", (double)ht->nsteps + / ht->nlookups); + fprintf(fp, "mean hash chain length: %g\n", mean); + fprintf(fp, " standard deviation: %g\n", sqrt(variance)); + fprintf(fp, " max hash chain length: %u\n", maxChainLen); + fprintf(fp, " max hash chain: [%u]\n", maxChain); + + for (he = ht->buckets[maxChain], i = 0; he; he = he->next, i++) + if ((*dump)(he, i, fp) != HT_ENUMERATE_NEXT) + break; +} +#endif /* HASHMETER */ + +PR_IMPLEMENT(int) +JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp) +{ + int count; + + count = JSJ_HashTableEnumerateEntries(ht, dump, fp); +#ifdef HASHMETER + JSJ_HashTableDumpMeter(ht, dump, fp); +#endif + return count; +} + +PR_IMPLEMENT(JSJHashNumber) +JSJ_HashString(const void *key) +{ + JSJHashNumber h; + const unsigned char *s; + + h = 0; + for (s = key; *s; s++) + h = (h >> 28) ^ (h << 4) ^ *s; + return h; +} + +PR_IMPLEMENT(int) +JSJ_CompareStrings(const void *v1, const void *v2) +{ + return strcmp(v1, v2) == 0; +} + +PR_IMPLEMENT(int) +JSJ_CompareValues(const void *v1, const void *v2) +{ + return v1 == v2; +} diff --git a/mozilla/js/src/liveconnect/jsj_hash.h b/mozilla/js/src/liveconnect/jsj_hash.h new file mode 100644 index 00000000000..e6fb30aa41b --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_hash.h @@ -0,0 +1,141 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This is a copy of the NSPR hash-table library, but it has been slightly + * modified to allow an additional argument to be passed into the hash + * key-comparision function. This is used to maintain thread-safety by + * passing in a JNIEnv pointer to the key-comparison function rather + * than storing it in a global. All types,function names, etc. have + * been renamed from their original NSPR names to protect the innocent. + */ + +#ifndef jsj_hash_h___ +#define jsj_hash_h___ +/* + * API to portable hash table code. + */ +#include +#include +#include "prtypes.h" + +PR_BEGIN_EXTERN_C + +typedef struct JSJHashEntry JSJHashEntry; +typedef struct JSJHashTable JSJHashTable; +typedef PRUint32 JSJHashNumber; +#define JSJ_HASH_BITS 32 +typedef JSJHashNumber (*JSJHashFunction)(const void *key, void *arg); +typedef PRIntn (*JSJHashComparator)(const void *v1, const void *v2, void *arg); +typedef PRIntn (*JSJHashEnumerator)(JSJHashEntry *he, PRIntn i, void *arg); + +/* Flag bits in JSJHashEnumerator's return value */ +#define HT_ENUMERATE_NEXT 0 /* continue enumerating entries */ +#define HT_ENUMERATE_STOP 1 /* stop enumerating entries */ +#define HT_ENUMERATE_REMOVE 2 /* remove and free the current entry */ +#define HT_ENUMERATE_UNHASH 4 /* just unhash the current entry */ + +typedef struct JSJHashAllocOps { + void * (*allocTable)(void *pool, size_t size); + void (*freeTable)(void *pool, void *item); + JSJHashEntry * (*allocEntry)(void *pool, const void *key); + void (*freeEntry)(void *pool, JSJHashEntry *he, PRUintn flag); +} JSJHashAllocOps; + +#define HT_FREE_VALUE 0 /* just free the entry's value */ +#define HT_FREE_ENTRY 1 /* free value and entire entry */ + +struct JSJHashEntry { + JSJHashEntry *next; /* hash chain linkage */ + JSJHashNumber keyHash; /* key hash function result */ + const void *key; /* ptr to opaque key */ + void *value; /* ptr to opaque value */ +}; + +struct JSJHashTable { + JSJHashEntry **buckets; /* vector of hash buckets */ + PRUint32 nentries; /* number of entries in table */ + PRUint32 shift; /* multiplicative hash shift */ + JSJHashFunction keyHash; /* key hash function */ + JSJHashComparator keyCompare; /* key comparison function */ + JSJHashComparator valueCompare; /* value comparison function */ + JSJHashAllocOps *allocOps; /* allocation operations */ + void *allocPriv; /* allocation private data */ +#ifdef HASHMETER + PRUint32 nlookups; /* total number of lookups */ + PRUint32 nsteps; /* number of hash chains traversed */ + PRUint32 ngrows; /* number of table expansions */ + PRUint32 nshrinks; /* number of table contractions */ +#endif +}; + +/* + * Create a new hash table. + * If allocOps is null, use default allocator ops built on top of malloc(). + */ +PR_EXTERN(JSJHashTable *) +JSJ_NewHashTable(PRUint32 n, JSJHashFunction keyHash, + JSJHashComparator keyCompare, JSJHashComparator valueCompare, + JSJHashAllocOps *allocOps, void *allocPriv); + +PR_EXTERN(void) +JSJ_HashTableDestroy(JSJHashTable *ht); + +/* Low level access methods */ +PR_EXTERN(JSJHashEntry **) +JSJ_HashTableRawLookup(JSJHashTable *ht, JSJHashNumber keyHash, const void *key, void *arg); + +PR_EXTERN(JSJHashEntry *) +JSJ_HashTableRawAdd(JSJHashTable *ht, JSJHashEntry **hep, JSJHashNumber keyHash, + const void *key, void *value, void *arg); + +PR_EXTERN(void) +JSJ_HashTableRawRemove(JSJHashTable *ht, JSJHashEntry **hep, JSJHashEntry *he, void *arg); + +/* Higher level access methods */ +PR_EXTERN(JSJHashEntry *) +JSJ_HashTableAdd(JSJHashTable *ht, const void *key, void *value, void *arg); + +PR_EXTERN(PRBool) +JSJ_HashTableRemove(JSJHashTable *ht, const void *key, void *arg); + +PR_EXTERN(PRIntn) +JSJ_HashTableEnumerateEntries(JSJHashTable *ht, JSJHashEnumerator f, void *arg); + +PR_EXTERN(void *) +JSJ_HashTableLookup(JSJHashTable *ht, const void *key, void *arg); + +PR_EXTERN(PRIntn) +JSJ_HashTableDump(JSJHashTable *ht, JSJHashEnumerator dump, FILE *fp); + +/* General-purpose C string hash function. */ +PR_EXTERN(JSJHashNumber) +JSJ_HashString(const void *key); + +/* Compare strings using strcmp(), return true if equal. */ +PR_EXTERN(int) +JSJ_CompareStrings(const void *v1, const void *v2); + +/* Stub function just returns v1 == v2 */ +PR_EXTERN(PRIntn) +JSJ_CompareValues(const void *v1, const void *v2); + +PR_END_EXTERN_C + +#endif /* jsj_hash_h___ */ diff --git a/mozilla/js/src/liveconnect/jsj_method.c b/mozilla/js/src/liveconnect/jsj_method.c new file mode 100644 index 00000000000..db98a5849a7 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_method.c @@ -0,0 +1,1158 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains the code used to reflect Java methods as properties of + * JavaObject objects and the code to invoke those methods. + * + */ + +#include +#include + +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#ifdef XP_MAC +#include "prosdep.h" +#endif + +#include "jsj_private.h" /* LiveConnect internals */ +#include "jsjava.h" /* LiveConnect external API */ + +/* + * A helper function for jsj_ConvertJavaMethodSignatureToString(): + * Compute JNI-style (string) signatures for an array of JavaSignature objects + * and concatenate the results into a single string. + * + * If an error is encountered, NULL is returned and the error reporter is called. + */ +static const char * +convert_java_method_arg_signatures_to_string(JSContext *cx, + JavaSignature **arg_signatures, + int num_args) +{ + const char *first_arg_signature, *rest_arg_signatures, *sig; + JavaSignature **rest_args; + + /* Convert the first method argument in the array to a string */ + first_arg_signature = jsj_ConvertJavaSignatureToString(cx, arg_signatures[0]); + if (!first_arg_signature) + return NULL; + + /* If this is the last method argument in the array, we're done. */ + if (num_args == 1) + return first_arg_signature; + + /* Convert the remaining method arguments to a string */ + rest_args = &arg_signatures[1]; + rest_arg_signatures = + convert_java_method_arg_signatures_to_string(cx, rest_args, num_args - 1); + if (!rest_arg_signatures) { + free((void*)first_arg_signature); + return NULL; + } + + /* Concatenate the signature string of this argument with the signature + strings of all the remaining arguments. */ + sig = PR_smprintf("%s%s", first_arg_signature, rest_arg_signatures); + free((void*)first_arg_signature); + free((void*)rest_arg_signatures); + if (!sig) { + JS_ReportOutOfMemory(cx); + return NULL; + } + + return sig; +} + +/* + * Compute a JNI-style (string) signature for the given method, e.g. the method + * "String MyFunc(int, byte)" is translated to "(IB)Ljava/lang/String;". + * + * If an error is encountered, NULL is returned and the error reporter is called. + */ +const char * +jsj_ConvertJavaMethodSignatureToString(JSContext *cx, + JavaMethodSignature *method_signature) +{ + JavaSignature **arg_signatures, *return_val_signature; + const char *arg_sigs_cstr; + const char *return_val_sig_cstr; + const char *sig_cstr; + + arg_signatures = method_signature->arg_signatures; + return_val_signature = method_signature->return_val_signature; + + /* Convert the method argument signatures to a C-string */ + arg_sigs_cstr = NULL; + if (arg_signatures) { + arg_sigs_cstr = + convert_java_method_arg_signatures_to_string(cx, arg_signatures, + method_signature->num_args); + if (!arg_sigs_cstr) + return NULL; + } + + /* Convert the method return value signature to a C-string */ + return_val_sig_cstr = jsj_ConvertJavaSignatureToString(cx, return_val_signature); + if (!return_val_sig_cstr) { + free((void*)arg_sigs_cstr); + return NULL; + } + + /* Compose method arg signatures string and return val signature string */ + if (arg_sigs_cstr) { + sig_cstr = PR_smprintf("(%s)%s", arg_sigs_cstr, return_val_sig_cstr); + free((void*)arg_sigs_cstr); + } else { + sig_cstr = PR_smprintf("()%s", return_val_sig_cstr); + } + + free((void*)return_val_sig_cstr); + + if (!sig_cstr) { + JS_ReportOutOfMemory(cx); + return NULL; + } + return sig_cstr; +} + +/* + * A helper function for jsj_ConvertJavaMethodSignatureToHRString(): + * Compute human-readable string signatures for an array of JavaSignatures + * and concatenate the results into a single string. + * + * If an error is encountered, NULL is returned and the error reporter is called. + */ +static const char * +convert_java_method_arg_signatures_to_hr_string(JSContext *cx, + JavaSignature **arg_signatures, + int num_args) +{ + const char *first_arg_signature, *rest_arg_signatures, *sig; + JavaSignature **rest_args; + + /* Convert the first method argument in the array to a string */ + first_arg_signature = jsj_ConvertJavaSignatureToHRString(cx, arg_signatures[0]); + if (!first_arg_signature) + return NULL; + + /* If this is the last method argument in the array, we're done. */ + if (num_args == 1) + return first_arg_signature; + + /* Convert the remaining method arguments to a string */ + rest_args = &arg_signatures[1]; + rest_arg_signatures = + convert_java_method_arg_signatures_to_hr_string(cx, rest_args, num_args - 1); + if (!rest_arg_signatures) { + free((void*)first_arg_signature); + return NULL; + } + + /* Concatenate the signature string of this argument with the signature + strings of all the remaining arguments. */ + sig = PR_smprintf("%s, %s", first_arg_signature, rest_arg_signatures); + free((void*)first_arg_signature); + free((void*)rest_arg_signatures); + if (!sig) { + JS_ReportOutOfMemory(cx); + return NULL; + } + + return sig; +} +/* + * Compute a string signature for the given method using the same type names + * that appear in Java source files, e.g. "int[][]", rather than the JNI-style + * type strings that are provided by the functions above. An example return + * value might be "String MyFunc(int, byte, char[][], java.lang.String)". + * + * If an error is encountered, NULL is returned and the error reporter is called. + */ +const char * +jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx, + const char *method_name, + JavaMethodSignature *method_signature) +{ + JavaSignature **arg_signatures, *return_val_signature; + const char *arg_sigs_cstr; + const char *return_val_sig_cstr; + const char *sig_cstr; + + arg_signatures = method_signature->arg_signatures; + return_val_signature = method_signature->return_val_signature; + + /* Convert the method argument signatures to a C-string */ + arg_sigs_cstr = NULL; + if (arg_signatures) { + arg_sigs_cstr = + convert_java_method_arg_signatures_to_hr_string(cx, arg_signatures, + method_signature->num_args); + if (!arg_sigs_cstr) + return NULL; + } + + /* Convert the method return value signature to a C-string */ + return_val_sig_cstr = jsj_ConvertJavaSignatureToHRString(cx, return_val_signature); + if (!return_val_sig_cstr) { + free((void*)arg_sigs_cstr); + return NULL; + } + + /* Compose method arg signatures string and return val signature string */ + if (arg_sigs_cstr) { + sig_cstr = PR_smprintf("%s %s(%s)", return_val_sig_cstr, method_name, arg_sigs_cstr); + free((void*)arg_sigs_cstr); + } else { + sig_cstr = PR_smprintf("%s %s()", return_val_sig_cstr, method_name); + } + + free((void*)return_val_sig_cstr); + + if (!sig_cstr) { + JS_ReportOutOfMemory(cx); + return NULL; + } + return sig_cstr; +} +/* + * Destroy the sub-structure of a JavaMethodSignature object without free'ing + * the method signature itself. + */ +void +jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *method_signature) +{ + int i, num_args; + JavaSignature **arg_signatures; + + if (!method_signature) /* Paranoia */ + return; + + /* Free the method argument signatures */ + num_args = method_signature->num_args; + arg_signatures = method_signature->arg_signatures; + for (i = 0; i < num_args; i++) + jsj_ReleaseJavaClassDescriptor(cx, jEnv, arg_signatures[i]); + if (arg_signatures) + JS_free(cx, arg_signatures); + + /* Free the return type signature */ + if (method_signature->return_val_signature) + jsj_ReleaseJavaClassDescriptor(cx, jEnv, method_signature->return_val_signature); +} + +/* + * Fill in the members of a JavaMethodSignature object using the method + * argument, which can be either an instance of either java.lang.reflect.Method + * or java.lang.reflect.Constructor. + * + * With normal completion, return the original method_signature argument. + * If an error occurs, return NULL and call the error reporter. + */ +JavaMethodSignature * +jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, + jobject method, + JavaMethodSignature *method_signature) +{ + int i; + jboolean is_constructor; + jclass return_val_class; + jsize num_args; + JavaSignature *return_val_signature; + jarray arg_classes; + jmethodID getParameterTypes; + + memset(method_signature, 0, sizeof (JavaMethodSignature)); + + is_constructor = (*jEnv)->IsInstanceOf(jEnv, method, jlrConstructor); + + /* Get a Java array that lists the class of each of the method's arguments */ + if (is_constructor) + getParameterTypes = jlrConstructor_getParameterTypes; + else + getParameterTypes = jlrMethod_getParameterTypes; + arg_classes = (*jEnv)->CallObjectMethod(jEnv, method, getParameterTypes); + if (!arg_classes) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't determine argument signature of method"); + goto error; + } + + /* Compute the number of method arguments */ + num_args = jsj_GetJavaArrayLength(cx, jEnv, arg_classes); + if (num_args < 0) + goto error; + method_signature->num_args = num_args; + + /* Build a JavaSignature array corresponding to the method's arguments */ + if (num_args) { + JavaSignature **arg_signatures; + + /* Allocate an array of JavaSignatures, one for each method argument */ + size_t arg_signatures_size = num_args * sizeof(JavaSignature *); + arg_signatures = (JavaSignature **)JS_malloc(cx, arg_signatures_size); + if (!arg_signatures) + goto error; + memset(arg_signatures, 0, arg_signatures_size); + method_signature->arg_signatures = arg_signatures; + + /* Build an array of JavaSignature objects, each of which corresponds + to the type of an individual method argument. */ + for (i = 0; i < num_args; i++) { + JavaSignature *a; + jclass arg_class = (*jEnv)->GetObjectArrayElement(jEnv, arg_classes, i); + + a = arg_signatures[i] = jsj_GetJavaClassDescriptor(cx, jEnv, arg_class); + if (!a) { + jsj_ReportJavaError(cx, jEnv, "Could not determine Java class " + "signature using java.lang.reflect"); + goto error; + } + } + } + + /* Get the Java class of the method's return value */ + if (is_constructor) { + /* Constructors always have a "void" return type */ + return_val_class = jlVoid_TYPE; + } else { + return_val_class = + (*jEnv)->CallObjectMethod(jEnv, method, jlrMethod_getReturnType); + if (!return_val_class) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't determine return type of method " + "using java.lang.reflect.Method.getReturnType()"); + goto error; + } + } + + /* Build a JavaSignature object corresponding to the method's return value */ + return_val_signature = jsj_GetJavaClassDescriptor(cx, jEnv, return_val_class); + if (!return_val_signature) + goto error; + method_signature->return_val_signature = return_val_signature; + + return method_signature; + +error: + + jsj_PurgeJavaMethodSignature(cx, jEnv, method_signature); + return NULL; +} + +static JSBool +add_java_method_to_class_descriptor(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jstring method_name_jstr, + jobject java_method, + JSBool is_static_method, + JSBool is_constructor) +{ + jmethodID methodID; + jclass java_class = class_descriptor->java_class; + + JavaMemberDescriptor *member_descriptor = NULL; + const char *sig_cstr = NULL; + const char *method_name = NULL; + JavaMethodSignature *signature = NULL; + JavaMethodSpec **specp, *method_spec = NULL; + + if (is_constructor) { + member_descriptor = jsj_GetJavaClassConstructors(cx, class_descriptor); + } else { + if (is_static_method) { + member_descriptor = jsj_GetJavaStaticMemberDescriptor(cx, jEnv, class_descriptor, method_name_jstr); + } else { + member_descriptor = jsj_GetJavaMemberDescriptor(cx, jEnv, class_descriptor, method_name_jstr); + } + } + if (!member_descriptor) + return JS_FALSE; + + method_spec = (JavaMethodSpec*)JS_malloc(cx, sizeof(JavaMethodSpec)); + if (!method_spec) + goto error; + memset(method_spec, 0, sizeof(JavaMethodSpec)); + + signature = jsj_InitJavaMethodSignature(cx, jEnv, java_method, &method_spec->signature); + if (!signature) + goto error; + + method_name = JS_strdup(cx, member_descriptor->name); + if (!method_name) + goto error; + method_spec->name = method_name; + + sig_cstr = jsj_ConvertJavaMethodSignatureToString(cx, signature); + if (!sig_cstr) + goto error; + + if (is_static_method) + methodID = (*jEnv)->GetStaticMethodID(jEnv, java_class, method_name, sig_cstr); + else + methodID = (*jEnv)->GetMethodID(jEnv, java_class, method_name, sig_cstr); + method_spec->methodID = methodID; + + if (!methodID) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't get Java method ID for %s.%s() (sig=%s)", + class_descriptor->name, method_name, sig_cstr); + goto error; + } + + JS_free(cx, (char*)sig_cstr); + + /* Add method to end of list of overloaded methods for this class member */ + specp = &member_descriptor->methods; + while (*specp) { + specp = &(*specp)->next; + } + *specp = method_spec; + + return JS_TRUE; + +error: + if (method_spec) + JS_FREE_IF(cx, (char*)method_spec->name); + JS_FREE_IF(cx, (char*)sig_cstr); + if (signature) + jsj_PurgeJavaMethodSignature(cx, jEnv, signature); + JS_FREE_IF(cx, method_spec); + return JS_FALSE; +} + +JSBool +jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + JSBool reflect_only_static_methods) +{ + jarray joMethodArray, joConstructorArray; + jsize num_methods, num_constructors; + int i; + jclass java_class; + JSBool ok, reflect_only_instance_methods; + + reflect_only_instance_methods = !reflect_only_static_methods; + + /* Get a java array of java.lang.reflect.Method objects, by calling + java.lang.Class.getMethods(). */ + java_class = class_descriptor->java_class; + joMethodArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getMethods); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + (*jEnv)->ExceptionDescribe(jEnv); + (*jEnv)->ExceptionClear(jEnv); + return JS_FALSE; + } + if (!joMethodArray) { + jsj_UnexpectedJavaError(cx, jEnv, + "Can't determine Java object's methods " + "using java.lang.Class.getMethods()"); + return JS_FALSE; + } + + /* Iterate over the class methods */ + num_methods = (*jEnv)->GetArrayLength(jEnv, joMethodArray); + for (i = 0; i < num_methods; i++) { + jstring method_name_jstr; + + /* Get the i'th reflected method */ + jobject java_method = (*jEnv)->GetObjectArrayElement(jEnv, joMethodArray, i); + + /* Get the method modifiers, eg static, public, private, etc. */ + jint modifiers = (*jEnv)->CallIntMethod(jEnv, java_method, jlrMethod_getModifiers); + + /* Don't allow access to private or protected Java methods. */ + if (!(modifiers & ACC_PUBLIC)) + continue; + + /* Abstract methods can't be invoked */ + if (modifiers & ACC_ABSTRACT) + continue; + + /* Reflect all instance methods or all static methods, but not both */ + if (reflect_only_static_methods != ((modifiers & ACC_STATIC) != 0)) + continue; + + + /* Add a JavaMethodSpec object to the JavaClassDescriptor */ + method_name_jstr = (*jEnv)->CallObjectMethod(jEnv, java_method, jlrMethod_getName); + ok = add_java_method_to_class_descriptor(cx, jEnv, class_descriptor, method_name_jstr, java_method, + reflect_only_static_methods, JS_FALSE); + if (!ok) + return JS_FALSE; + } + + if (reflect_only_instance_methods) + return JS_TRUE; + + joConstructorArray = (*jEnv)->CallObjectMethod(jEnv, java_class, jlClass_getConstructors); + if (!joConstructorArray) { + jsj_UnexpectedJavaError(cx, jEnv, "internal error: " + "Can't determine Java class's constructors " + "using java.lang.Class.getConstructors()"); + return JS_FALSE; + } + + /* Iterate over the class constructors */ + num_constructors = (*jEnv)->GetArrayLength(jEnv, joConstructorArray); + for (i = 0; i < num_constructors; i++) { + /* Get the i'th reflected constructor */ + jobject java_constructor = + (*jEnv)->GetObjectArrayElement(jEnv, joConstructorArray, i); + + /* Get the method modifiers, eg public, private, etc. */ + jint modifiers = (*jEnv)->CallIntMethod(jEnv, java_constructor, + jlrConstructor_getModifiers); + + /* Don't allow access to private or protected Java methods. */ + if (!(modifiers & ACC_PUBLIC)) + continue; + + /* Add a JavaMethodSpec object to the JavaClassDescriptor */ + ok = add_java_method_to_class_descriptor(cx, jEnv, class_descriptor, NULL, + java_constructor, + JS_FALSE, JS_TRUE); + if (!ok) + return JS_FALSE; + } + return JS_TRUE; +} + +/* + * Free up a JavaMethodSpec and all its resources. + */ +void +jsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec) +{ + JS_FREE_IF(cx, (char*)method_spec->name); + jsj_PurgeJavaMethodSignature(cx, jEnv, &method_spec->signature); + JS_free(cx, method_spec); +} + +static JSBool +method_signature_matches_JS_args(JSContext *cx, JNIEnv *jEnv, uintN argc, jsval *argv, + JavaMethodSignature *method_signature, int *cost) +{ + uintN i; + JavaSignature *arg_signature; + JSBool dummy_bool; + + if (argc != (uintN)method_signature->num_args) + return JS_FALSE; + + for (i = 0; i < argc; i++) { + arg_signature = method_signature->arg_signatures[i]; + if (!jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signature, cost, + NULL, &dummy_bool)) + return JS_FALSE; + } + return JS_TRUE; +} + +/* + * Return the JavaScript types that a JavaScript method was invoked with + * as a string, e.g. a JS method invoked like foo(3, 'hey', 'you', true) + * would cause a return value of "(number, string, string, boolean)". + * The returned string must be free'ed by the caller. + * Returns NULL and reports an error if out-of-memory. + */ +static const char * +get_js_arg_types_as_string(JSContext *cx, uintN argc, jsval *argv) +{ + uintN i; + const char *arg_type, *arg_string, *tmp; + + if (argc == 0) + return strdup("()"); + + arg_string = strdup("("); + if (!arg_string) + goto out_of_memory; + for (i = 0; i < argc; i++) { + arg_type = JS_GetTypeName(cx, JS_TypeOfValue(cx, argv[i])); + tmp = PR_smprintf("%s%s%s%s", arg_string, i ? ", " : "", arg_type, + (i == argc-1) ? ")" : ""); + free((char*)arg_string); + if (!tmp) + goto out_of_memory; + arg_string = tmp; + } + + return arg_string; + +out_of_memory: + JS_ReportOutOfMemory(cx); + return NULL; +} + + +static void +report_method_match_failure(JSContext *cx, + JavaMemberDescriptor *member_descriptor, + JavaClassDescriptor *class_descriptor, + JSBool is_static_method, + uintN argc, jsval *argv) +{ + const char *err, *js_arg_string, *tmp, *method_str, *method_name; + JSBool is_constructor; + JavaMethodSpec *method; + + err = NULL; + is_constructor = (!strcmp(member_descriptor->name, "")); + + js_arg_string = get_js_arg_types_as_string(cx, argc, argv); + if (!js_arg_string) + goto out_of_memory; + + if (is_constructor) { + err = PR_smprintf("There is no Java constructor for class %s that matches " + "JavaScript argument types %s.\n", class_descriptor->name, + js_arg_string); + method_name = class_descriptor->name; + } else { + err = PR_smprintf("There is no %sJava method %s.%s that matches " + "JavaScript argument types %s.\n", + is_static_method ? "static ": "", + class_descriptor->name, member_descriptor->name, js_arg_string); + method_name = member_descriptor->name; + } + if (!err) + goto out_of_memory; + + tmp = PR_smprintf("%sCandidate methods with the same name are:\n", err); + if (!tmp) + goto out_of_memory; + err = tmp; + + method = member_descriptor->methods; + while (method) { + method_str = + jsj_ConvertJavaMethodSignatureToHRString(cx, method_name, &method->signature); + if (!method_str) + goto out_of_memory; + tmp = PR_smprintf("%s %s\n", err, method_str); + free((char*)method_str); + if (!tmp) + goto out_of_memory; + err = tmp; + + method = method->next; + } + + JS_ReportError(cx, err); + return; + +out_of_memory: + if (js_arg_string) + free((char*)js_arg_string); + if (err) + free((char*)err); +} + +static JavaMethodSpec * +resolve_overloaded_method(JSContext *cx, JNIEnv *jEnv, JavaMemberDescriptor *member_descriptor, + JavaClassDescriptor *class_descriptor, + JSBool is_static_method, + uintN argc, jsval *argv) +{ + int cost, lowest_cost, num_method_matches; + JavaMethodSpec *best_method_match, *method; + + num_method_matches = 0; + lowest_cost = 10000; + best_method_match = NULL; + + for (method = member_descriptor->methods; method; method = method->next) { + cost = 0; + if (!method_signature_matches_JS_args(cx, jEnv, argc, argv, &method->signature, &cost)) + continue; + +#if 1 + if (cost < lowest_cost) { + lowest_cost = cost; + best_method_match = method; + num_method_matches++; + } +#else + best_method_match = method; + break; +#endif + } + + if (!best_method_match) + report_method_match_failure(cx, member_descriptor, class_descriptor, + is_static_method, argc, argv); + + /* +#ifdef LIVECONNECT_IMPROVEMENTS + if (num_method_matches > 1) + return NULL; +#else + if (lowest_cost != 0) + return NULL; +#endif +*/ + return best_method_match; +} + +static jvalue * +convert_JS_method_args_to_java_argv(JSContext *cx, JNIEnv *jEnv, jsval *argv, + JavaMethodSpec *method, JSBool **localvp) +{ + jvalue *jargv; + JSBool ok, *localv; + uintN i, argc; + JavaSignature **arg_signatures; + JavaMethodSignature *signature; + + + signature = &method->signature; + argc = signature->num_args; + PR_ASSERT(argc != 0); + arg_signatures = signature->arg_signatures; + + jargv = (jvalue *)JS_malloc(cx, sizeof(jvalue) * argc); + + if (!jargv) + return NULL; + + /* + * Allocate an array that contains a flag for each argument, indicating whether + * or not the conversion from a JS value to a Java value resulted in a new + * JNI local reference. + */ + localv = (JSBool *)JS_malloc(cx, sizeof(JSBool) * argc); + if (!localv) { + JS_free(cx, jargv); + return NULL; + } + *localvp = localv; + + for (i = 0; i < argc; i++) { + int dummy_cost; + + ok = jsj_ConvertJSValueToJavaValue(cx, jEnv, argv[i], arg_signatures[i], + &dummy_cost, &jargv[i], &localv[i]); + if (!ok) { + JS_ReportError(cx, "Internal error: can't convert JS value to Java value"); + JS_free(cx, jargv); + JS_free(cx, localv); + return NULL; + } + } + + return jargv; +} + +static JSBool +invoke_java_method(JSContext *cx, JSJavaThreadState *jsj_env, + jobject java_class_or_instance, + JavaClassDescriptor *class_descriptor, + JavaMethodSpec *method, + JSBool is_static_method, + jsval *argv, jsval *vp) +{ + jvalue java_value; + jvalue *jargv; + uintN argc, i; + jobject java_object; + jclass java_class; + jmethodID methodID; + JavaMethodSignature *signature; + JavaSignature *return_val_signature; + JSContext *old_cx; + JNIEnv *jEnv; + JSBool *localv; + + methodID = method->methodID; + signature = &method->signature; + argc = signature->num_args; + + jEnv = jsj_env->jEnv; + + if (is_static_method) { + java_object = NULL; + java_class = java_class_or_instance; + } else { + java_object = java_class_or_instance; + java_class = NULL; + } + + jargv = NULL; + if (argc) { + jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv); + if (!jargv) + return JS_FALSE; + } + +#define CALL_JAVA_METHOD(type, member) \ + PR_BEGIN_MACRO \ + if (is_static_method) { \ + java_value.member = (*jEnv)->CallStatic##type##MethodA(jEnv, java_class, methodID, jargv);\ + } else { \ + java_value.member = (*jEnv)->Call##type##MethodA(jEnv, java_object, methodID, jargv);\ + } \ + if ((*jEnv)->ExceptionOccurred(jEnv)) { \ + jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()", \ + class_descriptor->name, method->name); \ + goto error; \ + } \ + PR_END_MACRO + + old_cx = JSJ_SetDefaultJSContextForJavaThread(cx, jsj_env); + if (old_cx && old_cx != cx) { + JS_ReportError(cx, "Java thread in simultaneous use by more than " + "one JSContext ?"); + } + + return_val_signature = signature->return_val_signature; + switch(return_val_signature->type) { + case JAVA_SIGNATURE_BYTE: + CALL_JAVA_METHOD(Byte, b); + break; + + case JAVA_SIGNATURE_CHAR: + CALL_JAVA_METHOD(Char, c); + break; + + case JAVA_SIGNATURE_FLOAT: + CALL_JAVA_METHOD(Float, f); + break; + + case JAVA_SIGNATURE_DOUBLE: + CALL_JAVA_METHOD(Double, d); + break; + + case JAVA_SIGNATURE_INT: + CALL_JAVA_METHOD(Int, i); + break; + + case JAVA_SIGNATURE_LONG: + CALL_JAVA_METHOD(Long, j); + break; + + case JAVA_SIGNATURE_SHORT: + CALL_JAVA_METHOD(Short, s); + break; + + case JAVA_SIGNATURE_BOOLEAN: + CALL_JAVA_METHOD(Boolean, z); + break; + + case JAVA_SIGNATURE_ARRAY: + case JAVA_SIGNATURE_CLASS: + CALL_JAVA_METHOD(Object, l); + break; + + case JAVA_SIGNATURE_VOID: + if (is_static_method) + (*jEnv)->CallStaticVoidMethodA(jEnv, java_class, methodID, jargv); + else + (*jEnv)->CallVoidMethodA(jEnv, java_object, methodID, jargv); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_ReportJavaError(cx, jEnv, "Error calling method %s.%s()", + class_descriptor->name, method->name); + goto error; + } + break; + + default: + PR_ASSERT(0); + return JS_FALSE; + } + + for (i = 0; i < argc; i++) { + if (localv[i]) + (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l); + } + if (jargv) + JS_free(cx, jargv); + + JSJ_SetDefaultJSContextForJavaThread(old_cx, jsj_env); + + return jsj_ConvertJavaValueToJSValue(cx, jEnv, return_val_signature, &java_value, vp); + +error: + for (i = 0; i < argc; i++) { + if (localv[i]) + (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l); + } + if (jargv) + JS_free(cx, jargv); + JSJ_SetDefaultJSContextForJavaThread(old_cx, jsj_env); + return JS_FALSE; +} + +static JSBool +invoke_overloaded_java_method(JSContext *cx, JSJavaThreadState *jsj_env, + JavaMemberDescriptor *member, + JSBool is_static_method, + jobject java_class_or_instance, + JavaClassDescriptor *class_descriptor, + uintN argc, jsval *argv, + jsval *vp) +{ + JavaMethodSpec *method; + JNIEnv *jEnv; + + jEnv = jsj_env->jEnv; + + method = resolve_overloaded_method(cx, jEnv, member, class_descriptor, + is_static_method, argc, argv); + if (!method) + return JS_FALSE; + + return invoke_java_method(cx, jsj_env, java_class_or_instance, class_descriptor, + method, is_static_method, argv, vp); +} + +PR_CALLBACK JSBool +jsj_JavaStaticMethodWrapper(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *vp) +{ + JSFunction *function; + JavaMemberDescriptor *member_descriptor; + JavaClassDescriptor *class_descriptor; + jsid id; + jsval idval; + JNIEnv *jEnv; + JSJavaThreadState *jsj_env; + jobject java_class; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_env = jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + class_descriptor = JS_GetPrivate(cx, obj); + if (!class_descriptor) + return JS_FALSE; + java_class = class_descriptor->java_class; + + PR_ASSERT(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION); + function = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2])); + idval = STRING_TO_JSVAL(JS_InternString(cx, JS_GetFunctionName(function))); + JS_ValueToId(cx, idval, &id); + + member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); + if (!member_descriptor) { + PR_ASSERT(0); + return JS_FALSE; + } + + return invoke_overloaded_java_method(cx, jsj_env, member_descriptor, JS_TRUE, + java_class, class_descriptor, argc, argv, vp); +} + +PR_CALLBACK JSBool +jsj_JavaInstanceMethodWrapper(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *vp) +{ + JSFunction *function; + JavaMemberDescriptor *member_descriptor; + JavaObjectWrapper *java_wrapper; + JavaClassDescriptor *class_descriptor; + jsid id; + jsval idval; + JSJavaThreadState *jsj_env; + JNIEnv *jEnv; + jobject java_obj, java_class; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_env = jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + java_wrapper = JS_GetPrivate(cx, obj); + if (!java_wrapper) + return JS_FALSE; + java_obj = java_wrapper->java_obj; + + PR_ASSERT(JS_TypeOfValue(cx, argv[-2]) == JSTYPE_FUNCTION); + function = JS_GetPrivate(cx, JSVAL_TO_OBJECT(argv[-2])); + idval = STRING_TO_JSVAL(JS_InternString(cx, JS_GetFunctionName(function))); + JS_ValueToId(cx, idval, &id); + class_descriptor = java_wrapper->class_descriptor; + member_descriptor = jsj_LookupJavaMemberDescriptorById(cx, jEnv, class_descriptor, id); + + /* If no instance method was found, try for a static method */ + if (!member_descriptor) { + member_descriptor = jsj_LookupJavaStaticMemberDescriptorById(cx, jEnv, class_descriptor, id); + if (!member_descriptor) { + PR_ASSERT(0); + return JS_FALSE; + } + java_class = class_descriptor->java_class; + return invoke_overloaded_java_method(cx, jsj_env, member_descriptor, JS_TRUE, + java_class, class_descriptor, argc, argv, vp); + } + + return invoke_overloaded_java_method(cx, jsj_env, member_descriptor, + JS_FALSE, java_obj, + class_descriptor, argc, argv, vp); +} + +static JSBool +invoke_java_constructor(JSContext *cx, + JSJavaThreadState *jsj_env, + jclass java_class, + JavaMethodSpec *method, + jsval *argv, jsval *vp) +{ + jvalue *jargv; + uintN argc, i; + jobject java_object; + jmethodID methodID; + JavaMethodSignature *signature; + JSContext *old_cx; + JNIEnv *jEnv; + JSBool *localv; + + methodID = method->methodID; + signature = &method->signature; + argc = signature->num_args; + + jEnv = jsj_env->jEnv; + + jargv = NULL; + if (argc) { + jargv = convert_JS_method_args_to_java_argv(cx, jEnv, argv, method, &localv); + if (!jargv) + return JS_FALSE; + } + + old_cx = JSJ_SetDefaultJSContextForJavaThread(cx, jsj_env); + if (old_cx && old_cx != cx) { + JS_ReportError(cx, "Java thread in simultaneous use by more than " + "one JSContext ?"); + } + + /* Call the constructor */ + java_object = (*jEnv)->NewObjectA(jEnv, java_class, methodID, jargv); + + JSJ_SetDefaultJSContextForJavaThread(old_cx, jsj_env); + + if (!java_object) { + jsj_ReportJavaError(cx, jEnv, "Error while constructing instance of %s", + jsj_GetJavaClassName(cx, jEnv, java_class)); + goto error; + } + + for (i = 0; i < argc; i++) { + if (localv[i]) + (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l); + } + if (jargv) + JS_free(cx, jargv); + + return jsj_ConvertJavaObjectToJSValue(cx, jEnv, java_object, vp); + +error: + for (i = 0; i < argc; i++) { + if (localv[i]) + (*jEnv)->DeleteLocalRef(jEnv, jargv[i].l); + } + if (jargv) + JS_free(cx, jargv); + return JS_FALSE; +} + +static JSBool +invoke_overloaded_java_constructor(JSContext *cx, + JSJavaThreadState *jsj_env, + JavaMemberDescriptor *member, + JSObject *obj, uintN argc, jsval *argv, + jsval *vp) +{ + jclass java_class; + JavaMethodSpec *method; + JavaClassDescriptor *class_descriptor; + JNIEnv *jEnv; + + jEnv = jsj_env->jEnv; + + class_descriptor = JS_GetPrivate(cx, obj); + PR_ASSERT(class_descriptor); + if (!class_descriptor) + return JS_FALSE; + + + method = resolve_overloaded_method(cx, jEnv, member, class_descriptor, JS_TRUE, + argc, argv); + if (!method) + return JS_FALSE; + + java_class = class_descriptor->java_class; + return invoke_java_constructor(cx, jsj_env, java_class, method, argv, vp); +} + + +PR_CALLBACK JSBool +jsj_JavaConstructorWrapper(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *vp) +{ + jint modifiers; + JavaMemberDescriptor *member_descriptor; + JavaClassDescriptor *class_descriptor; + JSJavaThreadState *jsj_env; + JNIEnv *jEnv; + + /* Get the Java per-thread environment pointer for this JSContext */ + jsj_env = jsj_MapJSContextToJSJThread(cx, &jEnv); + if (!jEnv) + return JS_FALSE; + + obj = JSVAL_TO_OBJECT(argv[-2]); + class_descriptor = JS_GetPrivate(cx, obj); + if (!class_descriptor) + return JS_FALSE; + + /* Get class/interface flags and check them */ + modifiers = class_descriptor->modifiers; + if (modifiers & ACC_ABSTRACT) { + JS_ReportError(cx, "Java class %s is abstract and therefore may not " + "be instantiated", class_descriptor->name); + return JS_FALSE; + } + if (modifiers & ACC_INTERFACE) { + JS_ReportError(cx, "%s is a Java interface and therefore may not " + "be instantiated", class_descriptor->name); + return JS_FALSE; + } + if ( !(modifiers & ACC_PUBLIC) ) { + JS_ReportError(cx, "Java class %s is not public and therefore may not " + "be instantiated", class_descriptor->name); + return JS_FALSE; + } + + member_descriptor = jsj_LookupJavaClassConstructors(cx, jEnv, class_descriptor); + if (!member_descriptor) { + JS_ReportError(cx, "No public constructors defined for Java class %s", + class_descriptor->name); + return JS_FALSE; + } + + return invoke_overloaded_java_constructor(cx, jsj_env, member_descriptor, obj, argc, argv, vp); +} + diff --git a/mozilla/js/src/liveconnect/jsj_nodl.c b/mozilla/js/src/liveconnect/jsj_nodl.c new file mode 100644 index 00000000000..e69de29bb2d diff --git a/mozilla/js/src/liveconnect/jsj_private.h b/mozilla/js/src/liveconnect/jsj_private.h new file mode 100644 index 00000000000..04d3ebf5392 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_private.h @@ -0,0 +1,507 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * Declarations of private (internal) functions/data/types for + * JavaScript <==> Java communication. + * + */ + + +#ifndef _JSJAVA_PVT_H +#define _JSJAVA_PVT_H + +#include "jsjava.h" +#include "jsj_hash.h" /* Hash tables */ +#include "plhash.h" /* NSPR hash-tables */ +#include "jni.h" /* Java Native Interface */ +#include "jsapi.h" /* JavaScript engine API */ + + +/*************************** Type Declarations ******************************/ + +/* Forward type declarations */ +typedef struct JavaMemberDescriptor JavaMemberDescriptor; +typedef struct JavaMethodSpec JavaMethodSpec; +typedef struct JavaClassDescriptor JavaClassDescriptor; +typedef struct JavaClassDescriptor JavaSignature; +typedef struct CapturedJSError CapturedJSError; +typedef struct JavaMemberVal JavaMemberVal; + +/* + * This enum uses the same character encoding used by the JDK to encode + * Java type signatures, but the enum is easier to debug/compile with. + */ +typedef enum { + JAVA_SIGNATURE_ARRAY = '[', + JAVA_SIGNATURE_BYTE = 'B', + JAVA_SIGNATURE_CHAR = 'C', + JAVA_SIGNATURE_CLASS = 'L', + JAVA_SIGNATURE_FLOAT = 'F', + JAVA_SIGNATURE_DOUBLE = 'D', + JAVA_SIGNATURE_INT = 'I', + JAVA_SIGNATURE_LONG = 'J', + JAVA_SIGNATURE_SHORT = 'S', + JAVA_SIGNATURE_VOID = 'V', + JAVA_SIGNATURE_BOOLEAN = 'Z', + JAVA_SIGNATURE_UNKNOWN = 0 +} JavaSignatureChar; + +/* The signature of a Java method consists of the signatures of all its + arguments and its return type signature. */ +typedef struct JavaMethodSignature { + jsize num_args; /* Length of arg_signatures array */ + JavaSignature ** arg_signatures; /* Array of argument signatures */ + JavaSignature * return_val_signature; /* Return type signature */ +} JavaMethodSignature; + +/* A descriptor for the reflection of a single Java field */ +typedef struct JavaFieldSpec { + jfieldID fieldID; /* JVM opaque access handle for field */ + JavaSignature * signature; /* Java type of field */ + int modifiers; /* Bitfield indicating field qualifiers */ + const char * name; /* UTF8; TODO - Should support Unicode field names */ +} JavaFieldSpec; + +/* A descriptor for the reflection of a single Java method. + Each overloaded method has a separate corresponding JavaMethodSpec. */ +struct JavaMethodSpec { + jmethodID methodID; /* JVM opaque access handle for method */ + JavaMethodSignature signature; + const char * name; /* UTF8; TODO - Should support Unicode method names */ + JavaMethodSpec * next; /* next method in chain of overloaded methods */ +}; + +/* + * A descriptor for the reflection of a single member of a Java object. + * This can represent one or more Java methods and/or a single field. + * (When there is more than one method attached to a single JavaMemberDescriptor + * they are overloaded methods sharing the same simple name.) This same + * descriptor type is used for both static or instance members. + */ +struct JavaMemberDescriptor { + const char * name; /* simple name of field and/or method */ + jsid id; /* hashed name for quick JS property lookup */ + JavaFieldSpec * field; /* field with the given name, if any */ + JavaMethodSpec * methods; /* Overloaded methods which share the same name, if any */ + JavaMemberDescriptor * next; /* next descriptor in same defining class */ +}; + +/* This is the native portion of a reflected Java class */ +struct JavaClassDescriptor { + const char * name; /* Name of class, e.g. "java/lang/Byte" */ + JavaSignatureChar type; /* class category: primitive type, object, array */ + jclass java_class; /* Opaque JVM handle to corresponding java.lang.Class */ + int num_instance_members; + int num_static_members; + JSBool instance_members_reflected; + JavaMemberDescriptor * instance_members; + JSBool static_members_reflected; + JavaMemberDescriptor * static_members; + JavaMemberDescriptor * constructors; + int modifiers; /* Class declaration qualifiers, + e.g. abstract, private */ + int ref_count; /* # of references to this struct */ + JavaSignature * array_component_signature; /* Only non-NULL for array classes */ +}; + +/* This is the native portion of a reflected Java method or field */ +struct JavaMemberVal { + jsval field_val; /* Captured value of Java field */ + jsval invoke_method_func_val; /* JSFunction wrapper around Java method invoker */ + JavaMemberDescriptor * descriptor; + JavaMemberVal * next; +}; + +/* This is the native portion of a reflected Java object */ +typedef struct JavaObjectWrapper { + jobject java_obj; /* Opaque JVM ref to Java object */ + JavaClassDescriptor * class_descriptor; /* Java class info */ + JavaMemberVal * members; /* Reflected methods and fields */ +} JavaObjectWrapper; + +/* These are definitions of the Java class/method/field modifier bits. + These really shouldn't be hard-coded here. Rather, + they should be read from java.lang.reflect.Modifier */ +#define ACC_PUBLIC 0x0001 /* visible to everyone */ +#define ACC_STATIC 0x0008 /* instance variable is static */ +#define ACC_FINAL 0x0010 /* no further subclassing,overriding */ +#define ACC_INTERFACE 0x0200 /* class is an interface */ +#define ACC_ABSTRACT 0x0400 /* no definition provided */ + +/* A JSJavaVM structure must be created for each Java VM that is accessed + via LiveConnect */ +struct JSJavaVM { +/* TODO - all LiveConnect global variables should be migrated into this + structure in order to allow more than one LiveConnect-enabled + Java VM to exist within the same process. */ + JavaVM * java_vm; + JNIEnv * main_thread_env; /* Main-thread Java environment */ + JSBool jsj_created_java_vm; + int num_attached_threads; + JSJavaVM * next; /* next VM among all created VMs */ +}; + +/* Per-thread state that encapsulates the connection to the Java VM */ +struct JSJavaThreadState { + const char * name; /* Thread name, for debugging */ + JSJavaVM * jsjava_vm; /* All per-JVM state */ + JNIEnv * jEnv; /* Per-thread opaque handle to Java VM */ + CapturedJSError * pending_js_errors; /* JS errors to be thrown as Java exceptions */ + JSContext * cx; /* current JS context for thread */ + JSJavaThreadState * next; /* next thread state among all created threads */ +}; + +/******************************** Globals ***********************************/ + +extern JSJCallbacks *JSJ_callbacks; + +/* JavaScript classes that reflect Java objects */ +extern JSClass JavaObject_class; +extern JSClass JavaArray_class; +extern JSClass JavaClass_class; + +/* + * Opaque JVM handles to Java classes, methods and objects required for + * Java reflection. These are computed and cached during initialization. + * TODO: These should be moved inside the JSJavaVM struct + */ +extern jclass jlObject; /* java.lang.Object */ +extern jclass jlrConstructor; /* java.lang.reflect.Constructor */ +extern jclass jlThrowable; /* java.lang.Throwable */ +extern jclass jlSystem; /* java.lang.System */ +extern jclass jlClass; /* java.lang.Class */ +extern jclass jlBoolean; /* java.lang.Boolean */ +extern jclass jlDouble; /* java.lang.Double */ +extern jclass jlString; /* java.lang.String */ +extern jclass njJSObject; /* netscape.javascript.JSObject */ +extern jclass njJSException; /* netscape.javascript.JSException */ +extern jclass njJSUtil; /* netscape.javascript.JSUtil */ + +extern jmethodID jlClass_getMethods; /* java.lang.Class.getMethods() */ +extern jmethodID jlClass_getConstructors; /* java.lang.Class.getConstructors() */ +extern jmethodID jlClass_getFields; /* java.lang.Class.getFields() */ +extern jmethodID jlClass_getName; /* java.lang.Class.getName() */ +extern jmethodID jlClass_getComponentType; /* java.lang.Class.getComponentType() */ +extern jmethodID jlClass_getModifiers; /* java.lang.Class.getModifiers() */ +extern jmethodID jlClass_isArray; /* java.lang.Class.isArray() */ + +extern jmethodID jlrMethod_getName; /* java.lang.reflect.Method.getName() */ +extern jmethodID jlrMethod_getParameterTypes; /* java.lang.reflect.Method.getParameterTypes() */ +extern jmethodID jlrMethod_getReturnType; /* java.lang.reflect.Method.getReturnType() */ +extern jmethodID jlrMethod_getModifiers; /* java.lang.reflect.Method.getModifiers() */ + +extern jmethodID jlrConstructor_getParameterTypes; /* java.lang.reflect.Constructor.getParameterTypes() */ +extern jmethodID jlrConstructor_getModifiers; /* java.lang.reflect.Constructor.getModifiers() */ + +extern jmethodID jlrField_getName; /* java.lang.reflect.Field.getName() */ +extern jmethodID jlrField_getType; /* java.lang.reflect.Field.getType() */ +extern jmethodID jlrField_getModifiers; /* java.lang.reflect.Field.getModifiers() */ + +extern jmethodID jlThrowable_getMessage; /* java.lang.Throwable.getMessage() */ +extern jmethodID jlThrowable_toString; /* java.lang.Throwable.toString() */ + +extern jmethodID jlBoolean_Boolean; /* java.lang.Boolean constructor */ +extern jmethodID jlBoolean_booleanValue; /* java.lang.Boolean.booleanValue() */ +extern jmethodID jlDouble_Double; /* java.lang.Double constructor */ +extern jmethodID jlDouble_doubleValue; /* java.lang.Double.doubleValue() */ + +extern jmethodID jlSystem_identityHashCode; /* java.lang.System.identityHashCode() */ + +extern jobject jlVoid_TYPE; /* java.lang.Void.TYPE value */ + +extern jmethodID njJSException_JSException; /* netscape.javascipt.JSexception constructor */ +extern jmethodID njJSObject_JSObject; /* netscape.javascript.JSObject constructor */ +extern jmethodID njJSUtil_getStackTrace; /* netscape.javascript.JSUtil.getStackTrace() */ +extern jfieldID njJSObject_internal; /* netscape.javascript.JSObject.internal */ +extern jfieldID njJSException_lineno; /* netscape.javascript.JSException.lineno */ +extern jfieldID njJSException_tokenIndex; /* netscape.javascript.JSException.tokenIndex */ +extern jfieldID njJSException_source; /* netscape.javascript.JSException.source */ +extern jfieldID njJSException_filename; /* netscape.javascript.JSException.filename */ + + +/**************** Java <==> JS conversions and Java types *******************/ +extern JSBool +jsj_ComputeJavaClassSignature(JSContext *cx, + JavaSignature *signature, + jclass java_class); + +extern const char * +jsj_ConvertJavaSignatureToString(JSContext *cx, JavaSignature *signature); +extern const char * +jsj_ConvertJavaSignatureToHRString(JSContext *cx, + JavaSignature *signature); +extern JavaMethodSignature * +jsj_InitJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, jobject method, + JavaMethodSignature *method_signature); + +extern const char * +jsj_ConvertJavaMethodSignatureToString(JSContext *cx, + JavaMethodSignature *method_signature); +extern const char * +jsj_ConvertJavaMethodSignatureToHRString(JSContext *cx, + const char *method_name, + JavaMethodSignature *method_signature); +extern void +jsj_PurgeJavaMethodSignature(JSContext *cx, JNIEnv *jEnv, JavaMethodSignature *signature); + +extern JSBool +jsj_ConvertJSValueToJavaValue(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, + int *cost, jvalue *java_value, JSBool *is_local_refp); +extern JSBool +jsj_ConvertJSValueToJavaObject(JSContext *cx, JNIEnv *jEnv, jsval v, JavaSignature *signature, + int *cost, jobject *java_value, JSBool *is_local_refp); +extern jstring +jsj_ConvertJSStringToJavaString(JSContext *cx, JNIEnv *jEnv, JSString *js_str); + +extern JSBool +jsj_ConvertJavaValueToJSValue(JSContext *cx, JNIEnv *jEnv, JavaSignature *signature, + jvalue *java_value, jsval *vp); +extern JSBool +jsj_ConvertJavaObjectToJSValue(JSContext *cx, JNIEnv *jEnv, + jobject java_obj, jsval *vp); + +extern JSString * +jsj_ConvertJavaStringToJSString(JSContext *cx, JNIEnv *jEnv, jstring java_str); + +extern JSBool +jsj_ConvertJavaObjectToJSString(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jobject java_obj, jsval *vp); +extern JSBool +jsj_ConvertJavaObjectToJSNumber(JSContext *cx, JNIEnv *jEnv, + jobject java_obj, jsval *vp); +extern JSBool +jsj_ConvertJavaObjectToJSBoolean(JSContext *cx, JNIEnv *jEnv, + jobject java_obj, jsval *vp); + +/************************ Java package reflection **************************/ +extern JSBool +jsj_init_JavaPackage(JSContext *, JSObject *, + JavaPackageDef *predefined_packages); + +/************************* Java class reflection ***************************/ +extern JSBool +jsj_init_JavaClass(JSContext *cx, JSObject *global_obj); + +extern void +jsj_DiscardJavaClassReflections(JNIEnv *jEnv); + +extern const char * +jsj_GetJavaClassName(JSContext *cx, JNIEnv *jEnv, jclass java_class); + +extern JavaClassDescriptor * +jsj_GetJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, jclass java_class); + +extern void +jsj_ReleaseJavaClassDescriptor(JSContext *cx, JNIEnv *jEnv, JavaClassDescriptor *class_descriptor); + +extern JSObject * +jsj_define_JavaClass(JSContext *cx, JNIEnv *jEnv, JSObject *obj, + const char *unqualified_class_name, + jclass jclazz); + +extern JavaMemberDescriptor * +jsj_GetJavaMemberDescriptor(JSContext *cx, + JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jstring member_name); + +extern JavaMemberDescriptor * +jsj_LookupJavaMemberDescriptorById(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jsid id); + +extern JavaMemberDescriptor * +jsj_LookupJavaStaticMemberDescriptorById(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jsid id); + +extern JavaMemberDescriptor * +jsj_GetJavaStaticMemberDescriptor(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + jstring member_name); + +extern JavaMemberDescriptor * +jsj_GetJavaClassConstructors(JSContext *cx, + JavaClassDescriptor *class_descriptor); + +extern JavaMemberDescriptor * +jsj_LookupJavaClassConstructors(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor); + +extern JavaMemberDescriptor * +jsj_GetClassInstanceMembers(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor); + +extern JavaMemberDescriptor * +jsj_GetClassStaticMembers(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor); + +extern JSBool +jsj_InitJavaClassReflectionsTable(); + +/************************* Java field reflection ***************************/ + +extern JSBool +jsj_GetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, + jobject java_obj, jsval *vp); +extern JSBool +jsj_SetJavaFieldValue(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field_spec, + jobject java_obj, jsval js_val); +extern JSBool +jsj_ReflectJavaFields(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + JSBool reflect_only_static_fields); +extern void +jsj_DestroyFieldSpec(JSContext *cx, JNIEnv *jEnv, JavaFieldSpec *field); + +/************************* Java method reflection ***************************/ +extern JSBool +jsj_JavaInstanceMethodWrapper(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *vp); +extern JSBool +jsj_JavaStaticMethodWrapper(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *vp); +extern JSBool +jsj_JavaConstructorWrapper(JSContext *cx, JSObject *obj, + uintN argc, jsval *argv, jsval *vp); +extern JSBool +jsj_ReflectJavaMethods(JSContext *cx, JNIEnv *jEnv, + JavaClassDescriptor *class_descriptor, + JSBool reflect_only_static_methods); +extern void +jsj_DestroyMethodSpec(JSContext *cx, JNIEnv *jEnv, JavaMethodSpec *method_spec); + +/************************* Java member reflection ***************************/ +extern JSBool +jsj_init_JavaMember(JSContext *, JSObject *); + +extern JSBool +jsj_ReflectJavaMethodsAndFields(JSContext *cx, JavaClassDescriptor *class_descriptor, + JSBool reflect_only_statics); + +/************************* Java object reflection **************************/ +extern JSBool +jsj_init_JavaObject(JSContext *, JSObject *); + +extern JSObject * +jsj_WrapJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_obj, jclass java_class); + +extern void +jsj_DiscardJavaObjReflections(JNIEnv *jEnv); + +extern JSBool +JavaObject_convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp); + +extern void +JavaObject_finalize(JSContext *cx, JSObject *obj); + +extern JSBool +JavaObject_resolve(JSContext *cx, JSObject *obj, jsval id); + +extern JSBool +JavaObject_enumerate(JSContext *cx, JSObject *obj); + +extern JSBool +JavaObject_getProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp); + +extern JSBool +JavaObject_getPropertyById(JSContext *cx, JSObject *obj, jsid id, jsval *vp); + +/************************* Java array reflection ***************************/ +extern JSBool +jsj_init_JavaArray(JSContext *cx, JSObject *global_obj); + +extern JSBool +jsj_GetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, + jsize index, JavaSignature *array_component_signature, + jsval *vp); + +extern JSBool +jsj_SetJavaArrayElement(JSContext *cx, JNIEnv *jEnv, jarray java_array, + jsize index, JavaSignature *array_component_signature, + jsval js_val); + +/********************* JavaScript object reflection ************************/ +extern jobject +jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj); + +extern void +jsj_ClearPendingJSErrors(JSJavaThreadState *jsj_env); + +extern JSBool +jsj_ReportUncaughtJSException(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception); + +/**************************** Utilities ************************************/ +extern void +jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...); + +extern void +jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...); + +extern const char * +jsj_GetJavaErrorMessage(JNIEnv *env); + +extern void +jsj_LogError(const char *error_msg); + +PR_CALLBACK JSJHashNumber +jsj_HashJavaObject(const void *key, void* env); + +PR_CALLBACK intN +jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg); + +extern JSJavaThreadState * +jsj_MapJavaThreadToJSJavaThreadState(JNIEnv *jEnv, char **errp); + +extern void +jsj_MakeJNIClassname(char *jClassName); + +extern const char * +jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object); + +extern jsize +jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array); + +extern JSBool +JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp); + +extern const char * +jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr); + +JSJavaThreadState * +jsj_MapJSContextToJSJThread(JSContext *cx, JNIEnv **envp); + +JSJavaThreadState * +jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env); + +#ifdef DEBUG +#define DEBUG_LOG(args) printf args +#endif + +#define JS_FREE_IF(cx, x) \ + PR_BEGIN_MACRO \ + if (x) \ + JS_free(cx, x); \ + PR_END_MACRO + +#endif /* _JSJAVA_PVT_H */ diff --git a/mozilla/js/src/liveconnect/jsj_utils.c b/mozilla/js/src/liveconnect/jsj_utils.c new file mode 100644 index 00000000000..da10111bfba --- /dev/null +++ b/mozilla/js/src/liveconnect/jsj_utils.c @@ -0,0 +1,369 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * It contains low-level utility code. + * + */ + +#include +#include + +#include "prtypes.h" +#include "prprf.h" +#include "prlog.h" + +#ifdef XP_MAC +#include "prosdep.h" +#endif + +#include "jsj_private.h" /* LiveConnect internals */ +#include "jsjava.h" /* External LiveConnect API */ + + +/* + * This is a hash-table utility routine that computes the hash code of a Java + * object by calling java.lang.System.identityHashCode() + */ +PR_CALLBACK JSJHashNumber +jsj_HashJavaObject(const void *key, void* env) +{ + JSJHashNumber hash_code; + jobject java_obj; + JNIEnv *jEnv; + + java_obj = (jobject)key; + jEnv = (JNIEnv*) env; + hash_code = (*jEnv)->CallStaticIntMethod(jEnv, jlSystem, + jlSystem_identityHashCode, java_obj); + PR_ASSERT(!(*jEnv)->ExceptionOccurred(jEnv)); + return hash_code; +} + +/* + * This is a hash-table utility routine for comparing two Java objects. + * It's not possible to use the == operator to directly compare two jobject's, + * since they're opaque references and aren't guaranteed to be simple pointers + * or handles (though they may be in some JVM implementations). Instead, + * use the JNI routine for comparing the two objects. + */ +PR_CALLBACK intN +jsj_JavaObjectComparator(const void *v1, const void *v2, void *arg) +{ + jobject java_obj1, java_obj2; + JNIEnv *jEnv; + + jEnv = (JNIEnv*)arg; + java_obj1 = (jobject)v1; + java_obj2 = (jobject)v2; + + if (java_obj1 == java_obj2) + return 1; + return (*jEnv)->IsSameObject(jEnv, java_obj1, java_obj2); +} + +/* + * Return a UTF8, null-terminated encoding of a Java string. The string must + * be free'ed by the caller. + * + * If an error occurs, returns NULL and calls the JS error reporter. + */ +const char * +jsj_DupJavaStringUTF(JSContext *cx, JNIEnv *jEnv, jstring jstr) +{ + const char *str, *retval; + + str = (*jEnv)->GetStringUTFChars(jEnv, jstr, 0); + if (!str) { + jsj_UnexpectedJavaError(cx, jEnv, "Can't get UTF8 characters from " + "Java string"); + return NULL; + } + retval = JS_strdup(cx, str); + (*jEnv)->ReleaseStringUTFChars(jEnv, jstr, str); + return retval; +} + +JSBool +JavaStringToId(JSContext *cx, JNIEnv *jEnv, jstring jstr, jsid *idp) +{ + const jschar *ucs2; + JSString *jsstr; + jsize ucs2_len; + jsval val; + + ucs2 = (*jEnv)->GetStringChars(jEnv, jstr, 0); + if (!ucs2) { + jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain Unicode characters" + "from Java string"); + return JS_FALSE; + } + + ucs2_len = (*jEnv)->GetStringLength(jEnv, jstr); + jsstr = JS_InternUCStringN(cx, ucs2, ucs2_len); + (*jEnv)->ReleaseStringChars(jEnv, jstr, ucs2); + if (!jsstr) + return JS_FALSE; + + val = STRING_TO_JSVAL(jsstr); + JS_ValueToId(cx, STRING_TO_JSVAL(jsstr), idp); + return JS_TRUE; +} + +/* Not used ? +const char * +jsj_ClassNameOfJavaObject(JSContext *cx, JNIEnv *jEnv, jobject java_object) +{ + jobject java_class; + + java_class = (*jEnv)->GetObjectClass(jEnv, java_object); + + if (!java_class) { + PR_ASSERT(0); + return NULL; + } + + return jsj_GetJavaClassName(cx, jEnv, java_class); +} +*/ + +/* + * Return, as a C string, the error message associated with a Java exception + * that occurred as a result of a JNI call, preceded by the class name of + * the exception. As a special case, if the class of the exception is + * netscape.javascript.JSException, the exception class name is omitted. + * + * NULL is returned if no Java exception is pending. The caller is + * responsible for free'ing the returned string. On exit, the Java exception + * is *not* cleared. + */ +const char * +jsj_GetJavaErrorMessage(JNIEnv *jEnv) +{ + const char *java_error_msg; + char *error_msg = NULL; + jthrowable exception; + jstring java_exception_jstring; + + exception = (*jEnv)->ExceptionOccurred(jEnv); + if (exception) { + java_exception_jstring = + (*jEnv)->CallObjectMethod(jEnv, exception, jlThrowable_toString); + java_error_msg = (*jEnv)->GetStringUTFChars(jEnv, java_exception_jstring, NULL); + error_msg = strdup((char*)java_error_msg); + (*jEnv)->ReleaseStringUTFChars(jEnv, java_exception_jstring, java_error_msg); + +#ifdef DEBUG + /* (*jEnv)->ExceptionDescribe(jEnv); */ +#endif + } + return error_msg; +} + +/* + * Return, as a C string, the JVM stack trace associated with a Java + * exception, as would be printed by java.lang.Throwable.printStackTrace(). + * The caller is responsible for free'ing the returned string. + * + * Returns NULL if an error occurs. + */ +static const char * +get_java_stack_trace(JSContext *cx, JNIEnv *jEnv, jthrowable java_exception) +{ + const char *backtrace; + jstring backtrace_jstr; + + backtrace = NULL; + if (java_exception && njJSUtil_getStackTrace) { + backtrace_jstr = (*jEnv)->CallStaticObjectMethod(jEnv, njJSUtil, + njJSUtil_getStackTrace, + java_exception); + if (!backtrace_jstr) { + jsj_UnexpectedJavaError(cx, jEnv, "Unable to get exception stack trace"); + return NULL; + } + backtrace = jsj_DupJavaStringUTF(cx, jEnv, backtrace_jstr); + } + return backtrace; +} + +/* Full Java backtrace when Java exceptions reported to JavaScript */ +#define REPORT_JAVA_EXCEPTION_STACK_TRACE + +/* + * This is a wrapper around JS_ReportError(), useful when an error condition + * is the result of a JVM failure or exception condition. It appends the + * message associated with the pending Java exception to the passed in + * printf-style format string and arguments. + */ +static void +vreport_java_error(JSContext *cx, JNIEnv *jEnv, const char *format, va_list ap) +{ + char *error_msg, *js_error_msg; + const char *java_stack_trace; + const char *java_error_msg; + jthrowable java_exception; + + java_error_msg = NULL; + java_exception = (*jEnv)->ExceptionOccurred(jEnv); + if (java_exception && njJSException && + (*jEnv)->IsInstanceOf(jEnv, java_exception, njJSException)) { + (*jEnv)->ExceptionClear(jEnv); + jsj_ReportUncaughtJSException(cx, jEnv, java_exception); + return; + } + + js_error_msg = PR_vsmprintf(format, ap); + + if (!js_error_msg) { + PR_ASSERT(0); /* Out-of-memory */ + return; + } + +#ifdef REPORT_JAVA_EXCEPTION_STACK_TRACE + + java_stack_trace = get_java_stack_trace(cx, jEnv, java_exception); + if (java_stack_trace) { + error_msg = PR_smprintf("%s\n%s", js_error_msg, java_stack_trace); + free((char*)java_stack_trace); + if (!error_msg) { + PR_ASSERT(0); /* Out-of-memory */ + return; + } + } else + +#endif + { + java_error_msg = jsj_GetJavaErrorMessage(jEnv); + if (java_error_msg) { + error_msg = PR_smprintf("%s (%s)\n", js_error_msg, java_error_msg); + free((char*)java_error_msg); + free(js_error_msg); + } else { + error_msg = js_error_msg; + } + } + + JS_ReportError(cx, error_msg); + + /* Important: the Java exception must not be cleared until the reporter + has been called, because the capture_js_error_reports_for_java(), + called from JS_ReportError(), needs to read the exception from the JVM */ + (*jEnv)->ExceptionClear(jEnv); + free(error_msg); +} + +void +jsj_ReportJavaError(JSContext *cx, JNIEnv *env, const char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vreport_java_error(cx, env, format, ap); + va_end(ap); +} + +/* + * Same as jsj_ReportJavaError, except "internal error: " is prepended + * to message. + */ +void +jsj_UnexpectedJavaError(JSContext *cx, JNIEnv *env, const char *format, ...) +{ + va_list ap; + const char *format2; + + va_start(ap, format); + format2 = PR_smprintf("internal error: %s", format); + if (format2) { + vreport_java_error(cx, env, format2, ap); + free((void*)format2); + } + va_end(ap); +} + +/* + * Most LiveConnect errors are signaled by calling JS_ReportError(), + * but in some circumstances, the target JSContext for such errors + * is not determinable, e.g. during initialization. In such cases + * any error messages are routed to this function. + */ +void +jsj_LogError(const char *error_msg) +{ + if (JSJ_callbacks && JSJ_callbacks->error_print) + JSJ_callbacks->error_print(error_msg); + else + fputs(error_msg, stderr); +} + +jsize +jsj_GetJavaArrayLength(JSContext *cx, JNIEnv *jEnv, jarray java_array) +{ + jsize array_length = (*jEnv)->GetArrayLength(jEnv, java_array); + if ((*jEnv)->ExceptionOccurred(jEnv)) { + jsj_UnexpectedJavaError(cx, jEnv, "Couldn't obtain array length"); + return -1; + } + return array_length; +} + +static JSJavaThreadState *the_java_jsj_env = NULL; + +JSJavaThreadState * +jsj_MapJSContextToJSJThread(JSContext *cx, JNIEnv **envp) +{ + JSJavaThreadState *jsj_env; + char *err_msg; + + *envp = NULL; + err_msg = NULL; + + jsj_env = the_java_jsj_env; + if (jsj_env == NULL) + jsj_env = JSJ_callbacks->map_js_context_to_jsj_thread(cx, &err_msg); + if (!jsj_env) { + if (err_msg) { + JS_ReportError(cx, err_msg); + free(err_msg); + } + return NULL; + } + if (envp) + *envp = jsj_env->jEnv; + return jsj_env; +} + +/** + * Since only one Java thread is allowed to enter JavaScript, this function is + * used to enforce the use of that thread's state. The static global the_java_jsj_env + * overrides using JSJ_callbacks->map_js_context_to_jsj_thread, which maps + * native threads to JSJavaThreadStates. This isn't appropriate when Java calls + * JavaScript, as there can be a many to one mapping from Java threads to native + * threads. + */ +JSJavaThreadState * +jsj_SetJavaJSJEnv(JSJavaThreadState* java_jsj_env) +{ + JSJavaThreadState *old_jsj_env = the_java_jsj_env; + the_java_jsj_env = java_jsj_env; + return old_jsj_env; +} diff --git a/mozilla/js/src/liveconnect/jsjava.h b/mozilla/js/src/liveconnect/jsjava.h new file mode 100644 index 00000000000..afe57712303 --- /dev/null +++ b/mozilla/js/src/liveconnect/jsjava.h @@ -0,0 +1,244 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * The contents of this file are subject to the Netscape Public License + * Version 1.0 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/NPL/ + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See + * the License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Mozilla Communicator client code. + * + * The Initial Developer of the Original Code is Netscape Communications + * Corporation. Portions created by Netscape are Copyright (C) 1998 + * Netscape Communications Corporation. All Rights Reserved. + */ + +/* + * This file is part of the Java-vendor-neutral implementation of LiveConnect + * + * Publicly exported functions for JavaScript <==> Java communication. + * + */ + +#ifndef _JSJAVA_H +#define _JSJAVA_H + +#ifndef prtypes_h___ +#include "prtypes.h" +#endif + +PR_BEGIN_EXTERN_C + +#include "jni.h" /* Java Native Interface */ +#include "jsapi.h" /* JavaScript engine API */ + +/* + * A JSJavaVM structure is a wrapper around a JavaVM which incorporates + * additional LiveConnect state. + */ +typedef struct JSJavaVM JSJavaVM; + +/* LiveConnect and Java state, one per thread */ +typedef struct JSJavaThreadState JSJavaThreadState; + +/* + * This callback table provides hooks to external functions that implement + * functionality specific to the embedding. For example, these callbacks are + * necessary in multi-threaded environments or to implement a security + * policy. + */ +typedef struct JSJCallbacks { + + /* This callback is invoked when there is no JavaScript execution + environment (JSContext) associated with the current Java thread and + a call is made from Java into JavaScript. (A JSContext is associated + with a Java thread by calling the JSJ_SetJSContextForJavaThread() + function.) This callback is only invoked when Java spontaneously calls + into JavaScript, i.e. it is not called when JS calls into Java which + calls back into JS. + + This callback can be used to create a JSContext lazily, or obtain + one from a pool of available JSContexts. The implementation of this + callback can call JSJ_SetJSContextForJavaThread() to avoid any further + callbacks of this type for this Java thread. */ + JSContext * (*map_jsj_thread_to_js_context)(JNIEnv *jEnv, + char **errp); + + /* This callback is invoked whenever a call is made into Java from + JavaScript. It's responsible for mapping from a JavaScript execution + environment (JSContext) to a Java thread. (A JavaContext can only + be associated with one Java thread at a time.) */ + JSJavaThreadState * (*map_js_context_to_jsj_thread)(JSContext *cx, + char **errp); + + /* This callback implements netscape.javascript.JSObject.getWindow(), + a method named for its behavior in the browser environment, where it + returns the JS "Window" object corresponding to the HTML window that an + applet is embedded within. More generally, it's a way for Java to get + hold of a JS object that has not been explicitly passed to it. */ + JSObject * (*map_java_object_to_js_object)(JNIEnv *jEnv, jobject hint, + char **errp); + + /* An interim callback function until the LiveConnect security story is + straightened out. This function pointer can be set to NULL. */ + JSPrincipals * (*get_JSPrincipals_from_java_caller)(JNIEnv *jEnv); + + /* The following two callbacks sandwich any JS evaluation performed + from Java. They may be used to implement concurrency constraints, e.g. + by suspending the current thread until some condition is met. In the + browser embedding, these are used to maintain the run-to-completion + semantics of JavaScript. It is acceptable for either function pointer + to be NULL. */ + JSBool (*enter_js_from_java)(char **errp); + void (*exit_js)(void); + + /* Most LiveConnect errors are signaled by calling JS_ReportError(), but in + some circumstances, the target JSContext for such errors is not + determinable, e.g. during initialization. In such cases any error + messages are routed to this function. If the function pointer is set to + NULL, error messages are sent to stderr. */ + void (*error_print)(const char *error_msg); + + JavaVM * (*get_java_vm)(char **errp); + + /* Reserved for future use */ + void * reserved[10]; +} JSJCallbacks; + +/*===========================================================================*/ + +/* A flag that denotes that a Java package has no sub-packages other than those + explicitly pre-defined at the time of initialization. An access + to a simple name within such a package, therefore, must either correspond to + one of these explicitly pre-defined sub-packages or to a class within this + package. It is reasonable for LiveConnect to signal an error if a simple + name does not comply with these criteria. */ +#define PKG_SYSTEM 1 + +/* A flag that denotes that a Java package which might contain sub-packages + that are not pre-defined at initialization time, because the sub-packages + may not be the same in all installations. Therefore, an access to a simple + name within such a a package which does not correspond to either a + pre-defined sub-package or to a class, must be assummed to refer to an + unknown sub-package. This behavior may cause bogus JavaPackage objects to be + created if a package name is misspelled, e.g. sun.oi.net. */ +#define PKG_USER 2 + +/* A Java package defined at initialization time. */ +typedef struct JavaPackageDef { + const char * name; /* e.g. "java.lang" */ + const char * path; /* e.g. "java/lang", or NULL for default */ + int flags; /* PKG_USER, PKG_SYSTEM, etc. */ +} JavaPackageDef; + +/*===========================================================================*/ + +/* The following two convenience functions present a complete, but simplified + LiveConnect API which is designed to handle the special case of a single + Java-VM, with single-threaded operation, and the use of only one JSContext. + The full API is in the section below. */ + +/* Initialize the provided JSContext by setting up the JS classes necessary for + reflection and by defining JavaPackage objects for the default Java packages + as properties of global_obj. If java_vm is NULL, a new Java VM is + created, using the provided classpath in addition to any default classpath. + The classpath argument is ignored, however, if java_vm is non-NULL. */ +PR_IMPLEMENT(JSBool) +JSJ_SimpleInit(JSContext *cx, JSObject *global_obj, + JavaVM *java_vm, const char *classpath); + +/* Free up all resources. Destroy the Java VM if it was created by LiveConnect */ +PR_IMPLEMENT(void) +JSJ_SimpleShutdown(); + +/*===========================================================================*/ + +/* The "full" LiveConnect API, required when more than one thread, Java VM, or + JSContext is involved. Initialization pseudocode might go roughly like + this: + + JSJ_Init() // Setup callbacks + for each JavaVM { + JSJ_ConnectToJavaVM(...) + } + for each JSContext { + JSJ_InitJSContext(...) + } + for each JS evaluation { + run JavaScript code in the JSContext; + } + */ + +/* Called once for all instances of LiveConnect to set up callbacks */ +PR_IMPLEMENT(void) +JSJ_Init(JSJCallbacks *callbacks); + +/* Called once per Java VM, this function initializes the classes, fields, and + methods required for Java reflection. If java_vm is NULL, a new Java VM is + created, using the provided classpath in addition to any default classpath. + The classpath argument is ignored, however, if java_vm is non-NULL. */ +PR_IMPLEMENT(JSJavaVM *) +JSJ_ConnectToJavaVM(JavaVM *java_vm, const char *classpath); + +/* Initialize the provided JSContext by setting up the JS classes necessary for + reflection and by defining JavaPackage objects for the default Java packages + as properties of global_obj. Additional packages may be pre-defined by + setting the predefined_packages argument. (Pre-defining a Java package at + initialization time is not necessary, but it will make package lookup faster + and, more importantly, will avoid unnecessary network accesses if classes + are being loaded over the network.) */ +PR_IMPLEMENT(JSBool) +JSJ_InitJSContext(JSContext *cx, JSObject *global_obj, + JavaPackageDef *predefined_packages); + +/* This function returns a structure that encapsulates the Java and JavaScript + execution environment for the current native thread. It is intended to + be called from the embedder's implementation of JSJCallback's + map_js_context_to_jsj_thread() function. The thread_name argument is only + used for debugging purposes and can be set to NULL. The Java JNI + environment associated with this thread is returned through the java_envp + argument if java_envp is non-NULL. */ +PR_IMPLEMENT(JSJavaThreadState *) +JSJ_AttachCurrentThreadToJava(JSJavaVM *jsjava_vm, const char *thread_name, + JNIEnv **java_envp); + +/* Destructor routine for per-thread JSJavaThreadState structure */ +PR_IMPLEMENT(JSBool) +JSJ_DetachCurrentThreadFromJava(JSJavaThreadState *jsj_env); + +/* This function is used to specify a particular JSContext as *the* JavaScript + execution environment to be used when LiveConnect is accessed from the given + Java thread, i.e. when one of the methods of netscape.javascript.JSObject + has been called. There can only be one such JS context for any given Java + thread at a time. To multiplex JSContexts among a single thread, this + function could be called before Java is invoked on that thread.) The return + value is the previous JSContext associated with the given Java thread. + + If this function has not been called for a thread and a crossing is made + into JavaScript from Java, the map_jsj_thread_to_js_context() callback will + be invoked to determine the JSContext for the thread. The purpose of the + function is to improve performance by avoiding the expense of the callback. +*/ +PR_IMPLEMENT(JSContext *) +JSJ_SetDefaultJSContextForJavaThread(JSContext *cx, JSJavaThreadState *jsj_env); + +/* This routine severs the connection to a Java VM, freeing all related resources. + It shouldn't be called until the global scope has been cleared in all related + JSContexts (so that all LiveConnect objects are finalized) and a JavaScript + GC is performed. Otherwise, accessed to free'ed memory could result. */ +PR_IMPLEMENT(void) +JSJ_DisconnectFromJavaVM(JSJavaVM *); + +/* + * Reflect a Java object into a JS value. The source object, java_obj, must + * be of type java.lang.Object or a subclass and may, therefore, be an array. + */ +PR_IMPLEMENT(JSBool) +JSJ_ConvertJavaObjectToJSValue(JSContext *cx, jobject java_obj, jsval *vp); + +PR_END_EXTERN_C +#endif /* _JSJAVA_H */ diff --git a/mozilla/js/src/liveconnect/makefile.win b/mozilla/js/src/liveconnect/makefile.win new file mode 100644 index 00000000000..d4354554b33 --- /dev/null +++ b/mozilla/js/src/liveconnect/makefile.win @@ -0,0 +1,203 @@ +# 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. + +IGNORE_MANIFEST=1 + +#//------------------------------------------------------------------------ +#// +#// Makefile to build the Java reflections of JavaScript objects +#// +#//------------------------------------------------------------------------ + + +#//------------------------------------------------------------------------ +#// +#// Specify the depth of the current directory relative to the +#// root of NS +#// +#//------------------------------------------------------------------------ +DEPTH= ..\..\.. + +include <$(DEPTH)/config/config.mak> + +!ifdef JAVA_OR_OJI +!ifdef REGENERATE +DIRS = classes +!endif +!endif + + +#//------------------------------------------------------------------------ +#// +#// Define any Public Make Variables here: (ie. PDFFILE, MAPFILE, ...) +#// +#//------------------------------------------------------------------------ +DLLNAME=jsj$(MOZ_BITS)$(VERSION_NUMBER) +PDBFILE=$(DLLNAME).pdb +MAPFILE = $(DLLNAME).map +RESFILE = jsj1640.res +DLL=.\$(OBJDIR)\$(DLLNAME).dll +MAKE_OBJ_TYPE = DLL + +!if "$(MOZ_BITS)" == "16" +DEFFILE = $(DLLNAME).def +!endif + +!ifdef JAVA_OR_NSJVM +LLIBS=$(LIBNSPR) $(DIST)\lib\jrt$(MOZ_BITS)$(VERSION_NUMBER).lib \ + $(DIST)\lib\js$(MOZ_BITS)$(VERSION_NUMBER).lib +!else +LLIBS=$(LIBNSPR) $(DIST)\lib\js$(MOZ_BITS)$(VERSION_NUMBER).lib +!endif + +#//------------------------------------------------------------------------ +#// +#// Define the files necessary to build the target (ie. OBJS) +#// +#//------------------------------------------------------------------------ +!ifdef MOZ_OJI +OBJS= \ + .\$(OBJDIR)\jsj.obj \ + .\$(OBJDIR)\jsj_JSObject.obj \ + .\$(OBJDIR)\jsj_JavaArray.obj \ + .\$(OBJDIR)\jsj_JavaClass.obj \ + .\$(OBJDIR)\jsj_JavaObject.obj \ + .\$(OBJDIR)\jsj_JavaPackage.obj \ + .\$(OBJDIR)\jsj_array.obj \ + .\$(OBJDIR)\jsj_class.obj \ + .\$(OBJDIR)\jsj_convert.obj \ + .\$(OBJDIR)\jsj_field.obj \ + .\$(OBJDIR)\jsj_hash.obj \ + .\$(OBJDIR)\jsj_method.obj \ + .\$(OBJDIR)\jsj_utils.obj \ +!if "$(MOZ_BITS)" == "16" + .\$(OBJDIR)\jsj_nodl.obj \ +!endif + $(NULL) +!endif # MOZ_OJI +# + +#//------------------------------------------------------------------------ +#// +#// install headers +#// +#//------------------------------------------------------------------------ +INSTALL_DIR=$(PUBLIC)\js +INSTALL_FILE_LIST= \ + jsjava.h + +#//------------------------------------------------------------------------ +#// +#// Define any Public Targets here (ie. PROGRAM, LIBRARY, DLL, ...) +#// (these must be defined before the common makefiles are included) +#// +#//------------------------------------------------------------------------ + +!ifdef REGENERATE + +JNI_GEN= \ + netscape.javascript.JSObject \ + netscape.javascript.JSException \ + $(NULL) + +!endif + +!ifdef JAVA_OR_OJI +MODULE = java +EXPORTS = \ + $(JNI_GEN_DIR)/netscape_javascript_JSObject.h \ + $(JNI_GEN_DIR)/netscape_javascript_JSException.h \ + $(NULL) +!endif + + +#//------------------------------------------------------------------------ +#// +#// Define any local options for the make tools +#// (ie. LCFLAGS, LLFLAGS, LLIBS, LINCS) +#// +#//------------------------------------------------------------------------ + +LINCS=$(LINCS) -I_jni \ + -I$(PUBLIC)\js \ + -I$(PUBLIC)\java \ + $(NULL) + +#!ifdef SERVER_BUILD +#LLIBS=$(DIST)/lib/httpdlw.lib $(DIST)/lib/libsjboot.lib +#!endif + +#//------------------------------------------------------------------------ +#// +#// Include the common makefile rules +#// +#//------------------------------------------------------------------------ +include <$(DEPTH)/config/rules.mak> + +export:: INSTALL_FILES + +!ifndef REGENERATE + +export:: jsj10.jar + $(MAKE_INSTALL) jsj10.jar $(JAVA_DESTPATH) + cd $(JAVA_DESTPATH) + unzip -o jsj10.jar + cd ..\..\js\src\liveconnect + +!endif + +!ifdef JAVA_OR_OJI +libs:: $(DLL) + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).lib $(DIST)\lib +!endif + +!ifdef REGENERATE + +clobber:: + $(RM_R) _jni + +!endif + +#### +# this bit of extreme scariness came from the js/src makefile +# reproduced here since that's where jsjava.c lives now... + +!if ("$(MOZ_BITS)" == "16") +#// +#// Win16 Hoovers SO BAD!!! +#// + +!if !defined(MOZ_DEBUG) +#// +#// We must turn off codeview debug info so jni.c can build. +#// Otherwise the linker gives errors about data in the $SYMBOLS +#// segment being beyond a segment boundary. +#// +$(OBJDIR)\jsjava.obj: jsjava.c + @$(CC) @<<$(CFGFILE) + -c + -Od + $(CFLAGS) + $(LCFLAGS) + $(LINCS) + $(LINCS_1) + $(INCS) + -Fd$(PDBFILE) + -Fo.\$(OBJDIR)\ + $(*B).c +< +/* Header for class netscape_javascript_JSObject */ + +#ifndef _Included_netscape_javascript_JSObject +#define _Included_netscape_javascript_JSObject +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: netscape_javascript_JSObject + * Method: initClass + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_initClass + (JNIEnv *, jclass); + +/* + * Class: netscape_javascript_JSObject + * Method: getMember + * Signature: (Ljava/lang/String;)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getMember + (JNIEnv *, jobject, jstring); + +/* + * Class: netscape_javascript_JSObject + * Method: getSlot + * Signature: (I)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getSlot + (JNIEnv *, jobject, jint); + +/* + * Class: netscape_javascript_JSObject + * Method: setMember + * Signature: (Ljava/lang/String;Ljava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setMember + (JNIEnv *, jobject, jstring, jobject); + +/* + * Class: netscape_javascript_JSObject + * Method: setSlot + * Signature: (ILjava/lang/Object;)V + */ +JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_setSlot + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: netscape_javascript_JSObject + * Method: removeMember + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_removeMember + (JNIEnv *, jobject, jstring); + +/* + * 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 *, jobject, jstring, jobjectArray); + +/* + * Class: netscape_javascript_JSObject + * Method: eval + * Signature: (Ljava/lang/String;)Ljava/lang/Object; + */ +JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_eval + (JNIEnv *, jobject, jstring); + +/* + * Class: netscape_javascript_JSObject + * Method: toString + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_netscape_javascript_JSObject_toString + (JNIEnv *, jobject); + +/* + * Class: netscape_javascript_JSObject + * Method: getWindow + * Signature: (Ljava/applet/Applet;)Lnetscape/javascript/JSObject; + */ +JNIEXPORT jobject JNICALL Java_netscape_javascript_JSObject_getWindow + (JNIEnv *, jclass, jobject); + +/* + * Class: netscape_javascript_JSObject + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_netscape_javascript_JSObject_finalize + (JNIEnv *, jobject); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/mozilla/modules/plugin/base/public/npupp.h b/mozilla/modules/plugin/base/public/npupp.h new file mode 100644 index 00000000000..3260c811e4e --- /dev/null +++ b/mozilla/modules/plugin/base/public/npupp.h @@ -0,0 +1,1213 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + + +/* + * npupp.h $Revision: 3.1 $ + * function call mecahnics needed by platform specific glue code. + */ + + +#ifndef _NPUPP_H_ +#define _NPUPP_H_ + +#if defined(__OS2__) +#pragma pack(1) +#endif + +#ifndef GENERATINGCFM +#define GENERATINGCFM 0 +#endif + +#ifndef _NPAPI_H_ +#include "npapi.h" +#endif + +#include "jri.h" + +/****************************************************************************************** + plug-in function table macros + for each function in and out of the plugin API we define + typedef NPP_FooUPP + #define NewNPP_FooProc + #define CallNPP_FooProc + for mac, define the UPP magic for PPC/68K calling + *******************************************************************************************/ + + +/* NPP_Initialize */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_InitializeUPP; + +enum { + uppNPP_InitializeProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPP_InitializeProc(FUNC) \ + (NPP_InitializeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_InitializeProcInfo, GetCurrentArchitecture()) +#define CallNPP_InitializeProc(FUNC) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_InitializeProcInfo) + +#else + +typedef void (* NP_LOADDS NPP_InitializeUPP)(void); +#define NewNPP_InitializeProc(FUNC) \ + ((NPP_InitializeUPP) (FUNC)) +#define CallNPP_InitializeProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPP_Shutdown */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_ShutdownUPP; + +enum { + uppNPP_ShutdownProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(0)) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPP_ShutdownProc(FUNC) \ + (NPP_ShutdownUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_ShutdownProcInfo, GetCurrentArchitecture()) +#define CallNPP_ShutdownProc(FUNC) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_ShutdownProcInfo) + +#else + +typedef void (* NP_LOADDS NPP_ShutdownUPP)(void); +#define NewNPP_ShutdownProc(FUNC) \ + ((NPP_ShutdownUPP) (FUNC)) +#define CallNPP_ShutdownProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPP_New */ + +#if GENERATINGCFM +typedef UniversalProcPtr NPP_NewUPP; + +enum { + uppNPP_NewProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(uint16))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int16))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(char **))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(char **))) + | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(NPSavedData *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; + +#define NewNPP_NewProc(FUNC) \ + (NPP_NewUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewProcInfo, GetCurrentArchitecture()) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewProcInfo, \ + (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#else + +typedef NPError (* NP_LOADDS NPP_NewUPP)(NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved); +#define NewNPP_NewProc(FUNC) \ + ((NPP_NewUPP) (FUNC)) +#define CallNPP_NewProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) + +#endif + + +/* NPP_Destroy */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_DestroyUPP; +enum { + uppNPP_DestroyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPSavedData **))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_DestroyProc(FUNC) \ + (NPP_DestroyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyProcInfo, GetCurrentArchitecture()) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyProcInfo, (ARG1), (ARG2)) +#else + +typedef NPError (* NP_LOADDS NPP_DestroyUPP)(NPP instance, NPSavedData** save); +#define NewNPP_DestroyProc(FUNC) \ + ((NPP_DestroyUPP) (FUNC)) +#define CallNPP_DestroyProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPP_SetWindow */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_SetWindowUPP; +enum { + uppNPP_SetWindowProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPWindow *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_SetWindowProc(FUNC) \ + (NPP_SetWindowUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_SetWindowProcInfo, GetCurrentArchitecture()) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_SetWindowProcInfo, (ARG1), (ARG2)) + +#else + +typedef NPError (* NP_LOADDS NPP_SetWindowUPP)(NPP instance, NPWindow* window); +#define NewNPP_SetWindowProc(FUNC) \ + ((NPP_SetWindowUPP) (FUNC)) +#define CallNPP_SetWindowProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPP_NewStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_NewStreamUPP; +enum { + uppNPP_NewStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPBool))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(uint16 *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_NewStreamProc(FUNC) \ + (NPP_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_NewStreamProcInfo, GetCurrentArchitecture()) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_NewStreamProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#else + +typedef NPError (* NP_LOADDS NPP_NewStreamUPP)(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype); +#define NewNPP_NewStreamProc(FUNC) \ + ((NPP_NewStreamUPP) (FUNC)) +#define CallNPP_NewStreamProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) +#endif + + +/* NPP_DestroyStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_DestroyStreamUPP; +enum { + uppNPP_DestroyStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_DestroyStreamProc(FUNC) \ + (NPP_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, GetCurrentArchitecture()) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_DestroyStreamProcInfo, (NPParg), (NPStreamPtr), (NPReasonArg)) + +#else + +typedef NPError (* NP_LOADDS NPP_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPP_DestroyStreamProc(FUNC) \ + ((NPP_DestroyStreamUPP) (FUNC)) +#define CallNPP_DestroyStreamProc(FUNC, NPParg, NPStreamPtr, NPReasonArg) \ + (*(FUNC))((NPParg), (NPStreamPtr), (NPReasonArg)) + +#endif + + +/* NPP_WriteReady */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_WriteReadyUPP; +enum { + uppNPP_WriteReadyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPP_WriteReadyProc(FUNC) \ + (NPP_WriteReadyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, GetCurrentArchitecture()) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteReadyProcInfo, (NPParg), (NPStreamPtr)) + +#else + +typedef int32 (* NP_LOADDS NPP_WriteReadyUPP)(NPP instance, NPStream* stream); +#define NewNPP_WriteReadyProc(FUNC) \ + ((NPP_WriteReadyUPP) (FUNC)) +#define CallNPP_WriteReadyProc(FUNC, NPParg, NPStreamPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr)) + +#endif + + +/* NPP_Write */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_WriteUPP; +enum { + uppNPP_WriteProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPP_WriteProc(FUNC) \ + (NPP_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_WriteProcInfo, GetCurrentArchitecture()) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_WriteProcInfo, (NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +#else + +typedef int32 (* NP_LOADDS NPP_WriteUPP)(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer); +#define NewNPP_WriteProc(FUNC) \ + ((NPP_WriteUPP) (FUNC)) +#define CallNPP_WriteProc(FUNC, NPParg, NPStreamPtr, offsetArg, lenArg, bufferPtr) \ + (*(FUNC))((NPParg), (NPStreamPtr), (offsetArg), (lenArg), (bufferPtr)) + +#endif + + +/* NPP_StreamAsFile */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_StreamAsFileUPP; +enum { + uppNPP_StreamAsFileProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; +#define NewNPP_StreamAsFileProc(FUNC) \ + (NPP_StreamAsFileUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, GetCurrentArchitecture()) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_StreamAsFileProcInfo, (ARG1), (ARG2), (ARG3)) + +#else + +typedef void (* NP_LOADDS NPP_StreamAsFileUPP)(NPP instance, NPStream* stream, const char* fname); +#define NewNPP_StreamAsFileProc(FUNC) \ + ((NPP_StreamAsFileUPP) (FUNC)) +#define CallNPP_StreamAsFileProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPP_Print */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_PrintUPP; +enum { + uppNPP_PrintProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPrint *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; +#define NewNPP_PrintProc(FUNC) \ + (NPP_PrintUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_PrintProcInfo, GetCurrentArchitecture()) +#define CallNPP_PrintProc(FUNC, NPParg, voidPtr) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_PrintProcInfo, (NPParg), (voidPtr)) + +#else + +typedef void (* NP_LOADDS NPP_PrintUPP)(NPP instance, NPPrint* platformPrint); +#define NewNPP_PrintProc(FUNC) \ + ((NPP_PrintUPP) (FUNC)) +#define CallNPP_PrintProc(FUNC, NPParg, NPPrintArg) \ + (*(FUNC))((NPParg), (NPPrintArg)) + +#endif + + +/* NPP_HandleEvent */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_HandleEventUPP; +enum { + uppNPP_HandleEventProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(int16))) +}; +#define NewNPP_HandleEventProc(FUNC) \ + (NPP_HandleEventUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_HandleEventProcInfo, GetCurrentArchitecture()) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (int16)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_HandleEventProcInfo, (NPParg), (voidPtr)) + +#else + +typedef int16 (* NP_LOADDS NPP_HandleEventUPP)(NPP instance, void* event); +#define NewNPP_HandleEventProc(FUNC) \ + ((NPP_HandleEventUPP) (FUNC)) +#define CallNPP_HandleEventProc(FUNC, NPParg, voidPtr) \ + (*(FUNC))((NPParg), (voidPtr)) + +#endif + + +/* NPP_URLNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_URLNotifyUPP; +enum { + uppNPP_URLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(SIZE_CODE(0))) +}; +#define NewNPP_URLNotifyProc(FUNC) \ + (NPP_URLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_URLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) + +#else + +typedef void (* NP_LOADDS NPP_URLNotifyUPP)(NPP instance, const char* url, NPReason reason, void* notifyData); +#define NewNPP_URLNotifyProc(FUNC) \ + ((NPP_URLNotifyUPP) (FUNC)) +#define CallNPP_URLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) + +#endif + + +/* NPP_GetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_GetValueUPP; +enum { + uppNPP_GetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_GetValueProc(FUNC) \ + (NPP_GetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_GetValueProcInfo, GetCurrentArchitecture()) +#define CallNPP_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_GetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPP_GetValueUPP)(NPP instance, NPPVariable variable, void *ret_alue); +#define NewNPP_GetValueProc(FUNC) \ + ((NPP_GetValueUPP) (FUNC)) +#define CallNPP_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPP_SetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_SetValueUPP; +enum { + uppNPP_SetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPNVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_SetValueProc(FUNC) \ + (NPP_SetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_SetValueProcInfo, GetCurrentArchitecture()) +#define CallNPP_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPP_SetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPP_SetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPP_SetValueProc(FUNC) \ + ((NPP_SetValueUPP) (FUNC)) +#define CallNPP_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + + + +/* + * Netscape entry points + */ + + +/* NPN_GetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetValueUPP; +enum { + uppNPN_GetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPNVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetValueProc(FUNC) \ + (NPN_GetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetValueProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPN_GetValueUPP)(NPP instance, NPNVariable variable, void *ret_alue); +#define NewNPN_GetValueProc(FUNC) \ + ((NPN_GetValueUPP) (FUNC)) +#define CallNPN_GetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_SetValue */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_SetValueUPP; +enum { + uppNPN_SetValueProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPVariable))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(void *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_SetValueProc(FUNC) \ + (NPN_SetValueUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_SetValueProcInfo, GetCurrentArchitecture()) +#define CallNPN_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_SetValueProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPN_SetValueUPP)(NPP instance, NPPVariable variable, void *ret_alue); +#define NewNPN_SetValueProc(FUNC) \ + ((NPN_SetValueUPP) (FUNC)) +#define CallNPN_SetValueProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_GetUrlNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetURLNotifyUPP; +enum { + uppNPN_GetURLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetURLNotifyProc(FUNC) \ + (NPN_GetURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4)) +#else + +typedef NPError (* NP_LOADDS NPN_GetURLNotifyUPP)(NPP instance, const char* url, const char* window, void* notifyData); +#define NewNPN_GetURLNotifyProc(FUNC) \ + ((NPN_GetURLNotifyUPP) (FUNC)) +#define CallNPN_GetURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) +#endif + + +/* NPN_PostUrlNotify */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_PostURLNotifyUPP; +enum { + uppNPN_PostURLNotifyProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) + | STACK_ROUTINE_PARAMETER(7, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_PostURLNotifyProc(FUNC) \ + (NPN_PostURLNotifyUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, GetCurrentArchitecture()) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLNotifyProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#else + +typedef NPError (* NP_LOADDS NPN_PostURLNotifyUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData); +#define NewNPN_PostURLNotifyProc(FUNC) \ + ((NPN_PostURLNotifyUPP) (FUNC)) +#define CallNPN_PostURLNotifyProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6), (ARG7)) +#endif + + +/* NPN_GetUrl */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetURLUPP; +enum { + uppNPN_GetURLProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_GetURLProc(FUNC) \ + (NPN_GetURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetURLProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetURLProcInfo, (ARG1), (ARG2), (ARG3)) +#else + +typedef NPError (* NP_LOADDS NPN_GetURLUPP)(NPP instance, const char* url, const char* window); +#define NewNPN_GetURLProc(FUNC) \ + ((NPN_GetURLUPP) (FUNC)) +#define CallNPN_GetURLProc(FUNC, ARG1, ARG2, ARG3) \ + (*(FUNC))((ARG1), (ARG2), (ARG3)) +#endif + + +/* NPN_PostUrl */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_PostURLUPP; +enum { + uppNPN_PostURLProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(uint32))) + | STACK_ROUTINE_PARAMETER(5, SIZE_CODE(sizeof(const char*))) + | STACK_ROUTINE_PARAMETER(6, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_PostURLProc(FUNC) \ + (NPN_PostURLUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_PostURLProcInfo, GetCurrentArchitecture()) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_PostURLProcInfo, (ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) +#else + +typedef NPError (* NP_LOADDS NPN_PostURLUPP)(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file); +#define NewNPN_PostURLProc(FUNC) \ + ((NPN_PostURLUPP) (FUNC)) +#define CallNPN_PostURLProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5), (ARG6)) +#endif + + +/* NPN_RequestRead */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_RequestReadUPP; +enum { + uppNPN_RequestReadProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPByteRange *))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_RequestReadProc(FUNC) \ + (NPN_RequestReadUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_RequestReadProcInfo, GetCurrentArchitecture()) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_RequestReadProcInfo, (stream), (range)) + +#else + +typedef NPError (* NP_LOADDS NPN_RequestReadUPP)(NPStream* stream, NPByteRange* rangeList); +#define NewNPN_RequestReadProc(FUNC) \ + ((NPN_RequestReadUPP) (FUNC)) +#define CallNPN_RequestReadProc(FUNC, stream, range) \ + (*(FUNC))((stream), (range)) + +#endif + + +/* NPN_NewStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_NewStreamUPP; +enum { + uppNPN_NewStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPMIMEType))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(const char *))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(NPStream **))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_NewStreamProc(FUNC) \ + (NPN_NewStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_NewStreamProcInfo, GetCurrentArchitecture()) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_NewStreamProcInfo, (npp), (type), (window), (stream)) + +#else + +typedef NPError (* NP_LOADDS NPN_NewStreamUPP)(NPP instance, NPMIMEType type, const char* window, NPStream** stream); +#define NewNPN_NewStreamProc(FUNC) \ + ((NPN_NewStreamUPP) (FUNC)) +#define CallNPN_NewStreamProc(FUNC, npp, type, window, stream) \ + (*(FUNC))((npp), (type), (window), (stream)) + +#endif + + +/* NPN_Write */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_WriteUPP; +enum { + uppNPN_WriteProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(int32))) + | STACK_ROUTINE_PARAMETER(4, SIZE_CODE(sizeof(void*))) + | RESULT_SIZE(SIZE_CODE(sizeof(int32))) +}; +#define NewNPN_WriteProc(FUNC) \ + (NPN_WriteUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_WriteProcInfo, GetCurrentArchitecture()) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (int32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_WriteProcInfo, (npp), (stream), (len), (buffer)) + +#else + +typedef int32 (* NP_LOADDS NPN_WriteUPP)(NPP instance, NPStream* stream, int32 len, void* buffer); +#define NewNPN_WriteProc(FUNC) \ + ((NPN_WriteUPP) (FUNC)) +#define CallNPN_WriteProc(FUNC, npp, stream, len, buffer) \ + (*(FUNC))((npp), (stream), (len), (buffer)) + +#endif + + +/* NPN_DestroyStream */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_DestroyStreamUPP; +enum { + uppNPN_DestroyStreamProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP ))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPStream *))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPReason))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPN_DestroyStreamProc(FUNC) \ + (NPN_DestroyStreamUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, GetCurrentArchitecture()) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (NPError)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_DestroyStreamProcInfo, (npp), (stream), (reason)) + +#else + +typedef NPError (* NP_LOADDS NPN_DestroyStreamUPP)(NPP instance, NPStream* stream, NPReason reason); +#define NewNPN_DestroyStreamProc(FUNC) \ + ((NPN_DestroyStreamUPP) (FUNC)) +#define CallNPN_DestroyStreamProc(FUNC, npp, stream, reason) \ + (*(FUNC))((npp), (stream), (reason)) + +#endif + + +/* NPN_Status */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_StatusUPP; +enum { + uppNPN_StatusProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(char *))) +}; + +#define NewNPN_StatusProc(FUNC) \ + (NPN_StatusUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_StatusProcInfo, GetCurrentArchitecture()) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_StatusProcInfo, (npp), (msg)) + +#else + +typedef void (* NP_LOADDS NPN_StatusUPP)(NPP instance, const char* message); +#define NewNPN_StatusProc(FUNC) \ + ((NPN_StatusUPP) (FUNC)) +#define CallNPN_StatusProc(FUNC, npp, msg) \ + (*(FUNC))((npp), (msg)) + +#endif + + +/* NPN_UserAgent */ +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_UserAgentUPP; +enum { + uppNPN_UserAgentProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(const char *))) +}; + +#define NewNPN_UserAgentProc(FUNC) \ + (NPN_UserAgentUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_UserAgentProcInfo, GetCurrentArchitecture()) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (const char*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_UserAgentProcInfo, (ARG1)) + +#else + +typedef const char* (* NP_LOADDS NPN_UserAgentUPP)(NPP instance); +#define NewNPN_UserAgentProc(FUNC) \ + ((NPN_UserAgentUPP) (FUNC)) +#define CallNPN_UserAgentProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_MemAlloc */ +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemAllocUPP; +enum { + uppNPN_MemAllocProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) + | RESULT_SIZE(SIZE_CODE(sizeof(void *))) +}; + +#define NewNPN_MemAllocProc(FUNC) \ + (NPN_MemAllocUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemAllocProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (void*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemAllocProcInfo, (ARG1)) + +#else + +typedef void* (* NP_LOADDS NPN_MemAllocUPP)(uint32 size); +#define NewNPN_MemAllocProc(FUNC) \ + ((NPN_MemAllocUPP) (FUNC)) +#define CallNPN_MemAllocProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN__MemFree */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemFreeUPP; +enum { + uppNPN_MemFreeProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(void *))) +}; + +#define NewNPN_MemFreeProc(FUNC) \ + (NPN_MemFreeUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFreeProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFreeProcInfo, (ARG1)) + +#else + +typedef void (* NP_LOADDS NPN_MemFreeUPP)(void* ptr); +#define NewNPN_MemFreeProc(FUNC) \ + ((NPN_MemFreeUPP) (FUNC)) +#define CallNPN_MemFreeProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_MemFlush */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_MemFlushUPP; +enum { + uppNPN_MemFlushProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(uint32))) + | RESULT_SIZE(SIZE_CODE(sizeof(uint32))) +}; + +#define NewNPN_MemFlushProc(FUNC) \ + (NPN_MemFlushUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_MemFlushProcInfo, GetCurrentArchitecture()) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (uint32)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_MemFlushProcInfo, (ARG1)) + +#else + +typedef uint32 (* NP_LOADDS NPN_MemFlushUPP)(uint32 size); +#define NewNPN_MemFlushProc(FUNC) \ + ((NPN_MemFlushUPP) (FUNC)) +#define CallNPN_MemFlushProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + + +/* NPN_ReloadPlugins */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_ReloadPluginsUPP; +enum { + uppNPN_ReloadPluginsProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPBool))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_ReloadPluginsProc(FUNC) \ + (NPN_ReloadPluginsUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, GetCurrentArchitecture()) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_ReloadPluginsProcInfo, (ARG1)) + +#else + +typedef void (* NP_LOADDS NPN_ReloadPluginsUPP)(NPBool reloadPages); +#define NewNPN_ReloadPluginsProc(FUNC) \ + ((NPN_ReloadPluginsUPP) (FUNC)) +#define CallNPN_ReloadPluginsProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_GetJavaEnv */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetJavaEnvUPP; +enum { + uppNPN_GetJavaEnvProcInfo = kThinkCStackBased + | RESULT_SIZE(SIZE_CODE(sizeof(JRIEnv*))) +}; + +#define NewNPN_GetJavaEnvProc(FUNC) \ + (NPN_GetJavaEnvUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (JRIEnv*)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaEnvProcInfo) + +#else +typedef JRIEnv* (* NP_LOADDS NPN_GetJavaEnvUPP)(void); +#define NewNPN_GetJavaEnvProc(FUNC) \ + ((NPN_GetJavaEnvUPP) (FUNC)) +#define CallNPN_GetJavaEnvProc(FUNC) \ + (*(FUNC))() + +#endif + + +/* NPN_GetJavaPeer */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_GetJavaPeerUPP; +enum { + uppNPN_GetJavaPeerProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(jref))) +}; + +#define NewNPN_GetJavaPeerProc(FUNC) \ + (NPN_GetJavaPeerUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, GetCurrentArchitecture()) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_GetJavaPeerProcInfo, (ARG1)) + +#else + +typedef jref (* NP_LOADDS NPN_GetJavaPeerUPP)(NPP instance); +#define NewNPN_GetJavaPeerProc(FUNC) \ + ((NPN_GetJavaPeerUPP) (FUNC)) +#define CallNPN_GetJavaPeerProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/* NPN_InvalidateRect */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_InvalidateRectUPP; +enum { + uppNPN_InvalidateRectProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPRect *))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_InvalidateRectProc(FUNC) \ + (NPN_InvalidateRectUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_InvalidateRectProcInfo, GetCurrentArchitecture()) +#define CallNPN_InvalidateRectProc(FUNC, ARG1, ARG2) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_InvalidateRectProcInfo, (ARG1), (ARG2)) + +#else + +typedef void (* NP_LOADDS NPN_InvalidateRectUPP)(NPP instance, NPRect *rect); +#define NewNPN_InvalidateRectProc(FUNC) \ + ((NPN_InvalidateRectUPP) (FUNC)) +#define CallNPN_InvalidateRectProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + + +/* NPN_InvalidateRegion */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_InvalidateRegionUPP; +enum { + uppNPN_InvalidateRegionProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPRegion))) + | RESULT_SIZE(SIZE_CODE(0)) +}; + +#define NewNPN_InvalidateRegionProc(FUNC) \ + (NPN_InvalidateRegionUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_InvalidateRegionProcInfo, GetCurrentArchitecture()) +#define CallNPN_InvalidateRegionProc(FUNC, ARG1, ARG2) \ + (void)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_InvalidateRegionProcInfo, (ARG1), (ARG2)) + +#else + +typedef void (* NP_LOADDS NPN_InvalidateRegionUPP)(NPP instance, NPRegion region); +#define NewNPN_InvalidateRegionProc(FUNC) \ + ((NPN_InvalidateRegionUPP) (FUNC)) +#define CallNPN_InvalidateRegionProc(FUNC, ARG1, ARG2) \ + (*(FUNC))((ARG1), (ARG2)) + +#endif + +/* NPN_ForceRedraw */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPN_ForceRedrawUPP; +enum { + uppNPN_ForceRedrawProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPP))) + | RESULT_SIZE(SIZE_CODE(sizeof(0))) +}; + +#define NewNPN_ForceRedrawProc(FUNC) \ + (NPN_ForceRedrawUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPN_ForceRedrawProcInfo, GetCurrentArchitecture()) +#define CallNPN_ForceRedrawProc(FUNC, ARG1) \ + (jref)CallUniversalProc((UniversalProcPtr)(FUNC), uppNPN_ForceRedrawProcInfo, (ARG1)) + +#else + +typedef void (* NP_LOADDS NPN_ForceRedrawUPP)(NPP instance); +#define NewNPN_ForceRedrawProc(FUNC) \ + ((NPN_ForceRedrawUPP) (FUNC)) +#define CallNPN_ForceRedrawProc(FUNC, ARG1) \ + (*(FUNC))((ARG1)) + +#endif + + +/****************************************************************************************** + * The actual plugin function table definitions + *******************************************************************************************/ + +#ifdef XP_MAC +#if PRAGMA_ALIGN_SUPPORTED +#pragma options align=mac68k +#endif +#endif + +typedef struct _NPPluginFuncs { + uint16 size; + uint16 version; + NPP_NewUPP newp; + NPP_DestroyUPP destroy; + NPP_SetWindowUPP setwindow; + NPP_NewStreamUPP newstream; + NPP_DestroyStreamUPP destroystream; + NPP_StreamAsFileUPP asfile; + NPP_WriteReadyUPP writeready; + NPP_WriteUPP write; + NPP_PrintUPP print; + NPP_HandleEventUPP event; + NPP_URLNotifyUPP urlnotify; + JRIGlobalRef javaClass; + NPP_GetValueUPP getvalue; + NPP_SetValueUPP setvalue; +} NPPluginFuncs; + +typedef struct _NPNetscapeFuncs { + uint16 size; + uint16 version; + NPN_GetURLUPP geturl; + NPN_PostURLUPP posturl; + NPN_RequestReadUPP requestread; + NPN_NewStreamUPP newstream; + NPN_WriteUPP write; + NPN_DestroyStreamUPP destroystream; + NPN_StatusUPP status; + NPN_UserAgentUPP uagent; + NPN_MemAllocUPP memalloc; + NPN_MemFreeUPP memfree; + NPN_MemFlushUPP memflush; + NPN_ReloadPluginsUPP reloadplugins; + NPN_GetJavaEnvUPP getJavaEnv; + NPN_GetJavaPeerUPP getJavaPeer; + NPN_GetURLNotifyUPP geturlnotify; + NPN_PostURLNotifyUPP posturlnotify; + NPN_GetValueUPP getvalue; + NPN_SetValueUPP setvalue; + NPN_InvalidateRectUPP invalidaterect; + NPN_InvalidateRegionUPP invalidateregion; + NPN_ForceRedrawUPP forceredraw; +} NPNetscapeFuncs; + +#ifdef XP_MAC +#if PRAGMA_ALIGN_SUPPORTED +#pragma options align=reset +#endif +#endif + + +#ifdef XP_MAC +/****************************************************************************************** + * Mac platform-specific plugin glue stuff + *******************************************************************************************/ + +/* + * Main entry point of the plugin. + * This routine will be called when the plugin is loaded. The function + * tables are passed in and the plugin fills in the NPPluginFuncs table + * and NPPShutdownUPP for Netscape's use. + */ + +#if GENERATINGCFM + +typedef UniversalProcPtr NPP_MainEntryUPP; +enum { + uppNPP_MainEntryProcInfo = kThinkCStackBased + | STACK_ROUTINE_PARAMETER(1, SIZE_CODE(sizeof(NPNetscapeFuncs*))) + | STACK_ROUTINE_PARAMETER(2, SIZE_CODE(sizeof(NPPluginFuncs*))) + | STACK_ROUTINE_PARAMETER(3, SIZE_CODE(sizeof(NPP_ShutdownUPP*))) + | RESULT_SIZE(SIZE_CODE(sizeof(NPError))) +}; +#define NewNPP_MainEntryProc(FUNC) \ + (NPP_MainEntryUPP) NewRoutineDescriptor((ProcPtr)(FUNC), uppNPP_MainEntryProcInfo, GetCurrentArchitecture()) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + CallUniversalProc((UniversalProcPtr)(FUNC), (ProcInfoType)uppNPP_MainEntryProcInfo, (netscapeFunc), (pluginFunc), (shutdownUPP)) + +#else + +typedef NPError (* NP_LOADDS NPP_MainEntryUPP)(NPNetscapeFuncs*, NPPluginFuncs*, NPP_ShutdownUPP*); +#define NewNPP_MainEntryProc(FUNC) \ + ((NPP_MainEntryUPP) (FUNC)) +#define CallNPP_MainEntryProc(FUNC, netscapeFunc, pluginFunc, shutdownUPP) \ + (*(FUNC))((netscapeFunc), (pluginFunc), (shutdownUPP)) + +#endif +#endif /* MAC */ + +#if defined(_WINDOWS) +#define OSCALL WINAPI +#else +#if defined(__OS2__) +#define OSCALL _System +#else +#define OSCALL +#endif +#endif + +#if defined( _WINDOWS ) || defined (__OS2__) + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ +#if defined(__OS2__) + +typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */ + char *pMimeTypes; + char *pFileExtents; + char *pFileOpenTemplate; + char *pProductName; + char *pProductDescription; + unsigned long dwProductVersionMS; + unsigned long dwProductVersionLS; +} NPPluginData; + +NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData); + +#endif + +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs); + +NPError OSCALL NP_Initialize(NPNetscapeFuncs* pFuncs); + +NPError OSCALL NP_Shutdown(); + +#ifdef __cplusplus +} +#endif + +#endif /* _WINDOWS || __OS2__ */ + +#if defined(__OS2__) +#pragma pack() +#endif + +#ifdef XP_UNIX + +#ifdef __cplusplus +extern "C" { +#endif + +/* plugin meta member functions */ + +char* NP_GetMIMEDescription(void); +NPError NP_Initialize(NPNetscapeFuncs*, NPPluginFuncs*); +NPError NP_Shutdown(void); + +#ifdef __cplusplus +} +#endif + +#endif /* XP_UNIX */ + +#endif /* _NPUPP_H_ */ diff --git a/mozilla/modules/plugin/base/public/nsIEventHandler.h b/mozilla/modules/plugin/base/public/nsIEventHandler.h new file mode 100644 index 00000000000..1e6be85041f --- /dev/null +++ b/mozilla/modules/plugin/base/public/nsIEventHandler.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsIEventHandler_h___ +#define nsIEventHandler_h___ + +#include "nsplugindefs.h" + +//////////////////////////////////////////////////////////////////////////////// +// Plugin Instance Interface + +/** + * The nsIEventHandler interface provides the callback to handle events. + * It is implemented by the plugin, and is the superclass for nsIPluginInstance. + */ +class nsIEventHandler : public nsISupports { +public: + + /** + * Handles an event. An nsIEventHandler can also get registered with with + * nsIPluginManager2::RegisterWindow and will be called whenever an event + * comes in for that window. + * + * Note that for Unix and Mac the nsPluginEvent structure is different + * from the old NPEvent structure -- it's no longer the native event + * record, but is instead a struct. This was done for future extensibility, + * and so that the Mac could receive the window argument too. For Windows + * and OS2, it's always been a struct, so there's no change for them. + * + * (Corresponds to NPP_HandleEvent.) + * + * @param event - the event to be handled + * @param handled - set to PR_TRUE if event was handled + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + HandleEvent(nsPluginEvent* event, PRBool* handled) = 0; + +}; + +#define NS_IEVENTHANDLER_IID \ +{ /* a447ddf0-1a99-11d2-815f-006008119d7a */ \ + 0xa447ddf0, \ + 0x1a99, \ + 0x11d2, \ + {0x81, 0x5f, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIEventHandler_h___ */ diff --git a/mozilla/modules/plugin/base/public/nsIJRILiveConnectPlugInstPeer.h b/mozilla/modules/plugin/base/public/nsIJRILiveConnectPlugInstPeer.h new file mode 100644 index 00000000000..434858b943e --- /dev/null +++ b/mozilla/modules/plugin/base/public/nsIJRILiveConnectPlugInstPeer.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsIJRILiveConnectPluginInstancePeer_h__ +#define nsIJRILiveConnectPluginInstancePeer_h__ + +#include "nsplugindefs.h" +#include "nsISupports.h" + +//////////////////////////////////////////////////////////////////////////////// +// JRI-Based LiveConnect Classes +//////////////////////////////////////////////////////////////////////////////// +// +// This stuff is here so that the browser can support older JRI-based +// LiveConnected plugins (when using old plugin to new C++-style plugin +// adapter code). +// +// Warning: Don't use this anymore, unless you're sure that you have to! +//////////////////////////////////////////////////////////////////////////////// + +#include "jri.h" + +/** + * The nsIJRILiveConnectPluginInstancePeer interface is implemented by browsers + * that support JRI-based LiveConnect. Note that for 5.0, LiveConnect support + * has become JNI-based, so this interface is effectively deprecated. + * + * To obtain: QueryInterface on nsIPluginInstancePeer + */ +class nsIJRILiveConnectPluginInstancePeer : public nsISupports { +public: + + /** + * Returns a JRI reference to the Java peer object associated with the + * plugin instance. This object is an instance of the class specified + * by nsIJRILiveConnectPlugin::GetJavaClass. + * + * (Corresponds to NPN_GetJavaPeer.) + * + * @param resultingJavaPeer - a resulting reference to the Java instance + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + GetJavaPeer(jref *resultingJavaPeer) = 0; + +}; + +#define NS_IJRILIVECONNECTPLUGININSTANCEPEER_IID \ +{ /* 25b63f40-f773-11d1-815b-006008119d7a */ \ + 0x25b63f40, \ + 0xf773, \ + 0x11d1, \ + {0x81, 0x5b, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +// QueryInterface for this IID on nsIPluginManager to get a JRIEnv +// XXX change this +#define NS_IJRIENV_IID \ +{ /* f9d4ea00-a1bc-11d1-85b1-00805f0e4dfe */ \ + 0xf9d4ea00, \ + 0xa1bc, \ + 0x11d1, \ + {0x85, 0xb1, 0x00, 0x80, 0x5f, 0x0e, 0x4d, 0xfe} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIJRILiveConnectPluginInstancePeer_h__ */ diff --git a/mozilla/modules/plugin/base/public/nsILiveConnectPlugInstPeer.h b/mozilla/modules/plugin/base/public/nsILiveConnectPlugInstPeer.h new file mode 100644 index 00000000000..fd4b600dcab --- /dev/null +++ b/mozilla/modules/plugin/base/public/nsILiveConnectPlugInstPeer.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsILiveConnectPluginInstancePeer_h___ +#define nsILiveConnectPluginInstancePeer_h___ + +#include "nsplugindefs.h" +#include "nsISupports.h" +#include "jni.h" // standard JVM API + +/** + * The nsILiveConnectPluginInstancePeer interface is implemented by browsers + * that support LiveConnect, i.e. scriptability via JavaScript. Note that this + * LiveConnect interface is now JNI-based (since 5.0). + * + * To obtain: QueryInterface on nsIPluginInstancePeer + */ +class nsILiveConnectPluginInstancePeer : public nsISupports { +public: + + /** + * Returns a JNI reference to the Java peer object associated with the + * plugin instance. This object is an instance of the class specified + * by nsIJRILiveConnectPlugin::GetJavaClass. + * + * (New JNI-based entry point, roughly corresponds to NPN_GetJavaPeer.) + * + * @param resultingJavaPeer - a resulting reference to the Java instance + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + GetJavaPeer(jobject *resultingJavaPeer) = 0; + +}; + +#define NS_ILIVECONNECTPLUGININSTANCEPEER_IID \ +{ /* 1e3502a0-a1bd-11d1-85b1-00805f0e4dfe */ \ + 0x1e3502a0, \ + 0xa1bd, \ + 0x11d1, \ + {0x85, 0xb1, 0x00, 0x80, 0x5f, 0x0e, 0x4d, 0xfe} \ +} + +// QueryInterface for this IID on nsIPluginManager to get a JNIEnv +// XXX change this +#define NS_IJNIENV_IID \ +{ /* 04610650-a1bd-11d1-85b1-00805f0e4dfe */ \ + 0x04610650, \ + 0xa1bd, \ + 0x11d1, \ + {0x85, 0xb1, 0x00, 0x80, 0x5f, 0x0e, 0x4d, 0xfe} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsILiveConnectPluginInstancePeer_h___ */ diff --git a/mozilla/modules/plugin/base/public/nsINetworkManager.h b/mozilla/modules/plugin/base/public/nsINetworkManager.h new file mode 100644 index 00000000000..0e67c56e6f0 --- /dev/null +++ b/mozilla/modules/plugin/base/public/nsINetworkManager.h @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsINetworkManager_h___ +#define nsINetworkManager_h___ + +#include "nsplugindefs.h" +#include "nsISupports.h" + +/** + * The nsINetworkManager interface provides access to the network for URL get + * and post operations. + */ +class nsINetworkManager : public nsISupports { +public: + + /** + * Fetches a URL. + * + * (Corresponds to NPN_GetURL and NPN_GetURLNotify.) + * + * @param url - the URL to fetch + * @param target - the target window into which to load the URL + * @param notifyData - when present, URLNotify is called passing the + * notifyData back to the client. When NULL, this call behaves like + * NPN_GetURL. + * @param altHost - an IP-address string that will be used instead of the + * host specified in the URL. This is used to prevent DNS-spoofing + * attacks. Can be defaulted to NULL meaning use the host in the URL. + * @param referrer - the referring URL (may be NULL) + * @param forceJSEnabled - forces JavaScript to be enabled for 'javascript:' + * URLs, even if the user currently has JavaScript disabled (usually + * specify PR_FALSE) + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + GetURL(nsISupports* peer, const char* url, const char* target, + void* notifyData = NULL, const char* altHost = NULL, + const char* referrer = NULL, PRBool forceJSEnabled = PR_FALSE) = 0; + + /** + * Posts to a URL with post data and/or post headers. + * + * (Corresponds to NPN_PostURL and NPN_PostURLNotify.) + * + * @param url - the URL to fetch + * @param target - the target window into which to load the URL + * @param postDataLength - the length of postData (if non-NULL) + * @param postData - the data to POST. NULL specifies that there is not post + * data + * @param isFile - whether the postData specifies the name of a file to + * post instead of data. The file will be deleted afterwards. + * @param notifyData - when present, URLNotify is called passing the + * notifyData back to the client. When NULL, this call behaves like + * NPN_GetURL. + * @param altHost - an IP-address string that will be used instead of the + * host specified in the URL. This is used to prevent DNS-spoofing + * attacks. Can be defaulted to NULL meaning use the host in the URL. + * @param referrer - the referring URL (may be NULL) + * @param forceJSEnabled - forces JavaScript to be enabled for 'javascript:' + * URLs, even if the user currently has JavaScript disabled (usually + * specify PR_FALSE) + * @param postHeadersLength - the length of postHeaders (if non-NULL) + * @param postHeaders - the headers to POST. NULL specifies that there + * are no post headers + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + PostURL(nsISupports* peer, const char* url, const char* target, + PRUint32 postDataLen, const char* postData, + PRBool isFile = PR_FALSE, void* notifyData = NULL, + const char* altHost = NULL, const char* referrer = NULL, + PRBool forceJSEnabled = PR_FALSE, + PRUint32 postHeadersLength = 0, const char* postHeaders = NULL) = 0; + +}; + +#define NS_INETWORKMANAGER_IID \ +{ /* fc2eede0-20fe-11d2-8160-006008119d7a */ \ + 0xfc2eede0, \ + 0x20fe, \ + 0x11d2, \ + {0x81, 0x60, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsINetworkManager_h___ */ diff --git a/mozilla/modules/plugin/base/public/nsIWindowlessPlugInstPeer.h b/mozilla/modules/plugin/base/public/nsIWindowlessPlugInstPeer.h new file mode 100644 index 00000000000..973c072499c --- /dev/null +++ b/mozilla/modules/plugin/base/public/nsIWindowlessPlugInstPeer.h @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsIWindowlessPluginInstancePeer_h___ +#define nsIWindowlessPluginInstancePeer_h___ + +#include "nsplugindefs.h" +#include "nsISupports.h" + +//////////////////////////////////////////////////////////////////////////////// +// Windowless Plugin Instance Peer Interface + +class nsIWindowlessPluginInstancePeer : public nsISupports { +public: + + // (Corresponds to NPN_InvalidateRect.) + NS_IMETHOD + InvalidateRect(nsPluginRect *invalidRect) = 0; + + // (Corresponds to NPN_InvalidateRegion.) + NS_IMETHOD + InvalidateRegion(nsPluginRegion invalidRegion) = 0; + + // (Corresponds to NPN_ForceRedraw.) + NS_IMETHOD + ForceRedraw(void) = 0; + +}; + +#define NS_IWINDOWLESSPLUGININSTANCEPEER_IID \ +{ /* 57b4e2f0-019b-11d2-815b-006008119d7a */ \ + 0x57b4e2f0, \ + 0x019b, \ + 0x11d2, \ + {0x81, 0x5b, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIWindowlessPluginInstancePeer_h___ */ diff --git a/mozilla/modules/plugin/base/src/Makefile b/mozilla/modules/plugin/base/src/Makefile new file mode 100644 index 00000000000..5d054a68240 --- /dev/null +++ b/mozilla/modules/plugin/base/src/Makefile @@ -0,0 +1,44 @@ +#!nmake +# +# 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. + +DEPTH=../../.. + +include $(DEPTH)/config/config.mk + +MODULE=raptor + +LIBRARY_NAME=raptorplugin + +EXPORTS = \ + nsPluginsCID.h \ + nsIPluginHost.h + +CPPSRCS = \ + nsPluginHostImpl.cpp \ + nsPluginFactory.cpp \ + ns4xPlugin.cpp \ + $(NULL) + +REQUIRES = raptor plugin java xpcom + +LCFLAGS =-D_IMPL_NS_PLUGIN + +TARGETS = $(LIBRARY) + +INCLUDES += -I. + +include $(DEPTH)/config/rules.mk diff --git a/mozilla/modules/plugin/base/src/makefile.win b/mozilla/modules/plugin/base/src/makefile.win new file mode 100644 index 00000000000..fcdaec4c366 --- /dev/null +++ b/mozilla/modules/plugin/base/src/makefile.win @@ -0,0 +1,71 @@ +#!nmake +# +# 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. + +DEPTH=..\..\.. +IGNORE_MANIFEST=1 + +EXPORTS = \ + nsPluginsCID.h \ + nsIPluginHost.h + +MAKE_OBJ_TYPE = DLL +DLLNAME = raptorplugin +DLL=.\$(OBJDIR)\$(DLLNAME).dll +MISCDEP = $(OURLIBS) + +MODULE=raptor + +DEFINES =-D_IMPL_NS_PLUGIN -DWIN32_LEAN_AND_MEAN + +OBJS = \ + .\$(OBJDIR)\nsPluginHostImpl.obj \ + .\$(OBJDIR)\nsPluginFactory.obj \ + .\$(OBJDIR)\ns4xPlugin.obj \ + $(NULL) + +LINCS= \ + -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\xpcom \ + -I$(PUBLIC)\plugin \ + -I$(PUBLIC)\java \ + $(NULL) + + +LCFLAGS = \ + $(LCFLAGS) \ + -D_IMPL_NS_PLUGIN \ + $(NULL) + +OURLIBS= \ + $(DIST)\lib\xpcom32.lib \ + $(DIST)\lib\raptorbase.lib \ + $(LIBNSPR) + +LLIBS= \ + $(OURLIBS) \ + version.lib + +include <$(DEPTH)\config\rules.mak> + +it: + echo $(LLIBS) + +install:: $(DLL) + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin + +clobber:: + rm -f $(DIST)\bin\$(DLLNAME).dll diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp new file mode 100644 index 00000000000..c0de5348bde --- /dev/null +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -0,0 +1,737 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +// TODO: Implement Java callbacks + +#include "xp_core.h" +#include "nsplugin.h" +#include "ns4xPlugin.h" +//#include "ns4xPluginInstance.h" + +//////////////////////////////////////////////////////////////////////// + +// XXX These are defined in platform specific FE directories right now :-/ +typedef NPError (*NP_GETENTRYPOINTS)(NPPluginFuncs* pCallbacks); +typedef NPError (*NP_PLUGININIT)(const NPNetscapeFuncs* pCallbacks); +typedef NPError (*NP_PLUGINSHUTDOWN)(); + + +//////////////////////////////////////////////////////////////////////// + +NPNetscapeFuncs ns4xPlugin::CALLBACKS; +nsIPluginManager * ns4xPlugin::mManager; + +void +ns4xPlugin::CheckClassInitialized(void) +{ + static PRBool initialized = FALSE; + + if (initialized) + return; + + mManager = nsnull; + + // XXX It'd be nice to make this const and initialize it + // statically... + CALLBACKS.size = sizeof(CALLBACKS); + CALLBACKS.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; + + CALLBACKS.geturl = NewNPN_GetURLProc(_geturl); + CALLBACKS.posturl = NewNPN_PostURLProc(_posturl); +// CALLBACKS.requestread = NewNPN_RequestReadProc(_requestread); +// CALLBACKS.newstream = NewNPN_NewStreamProc(_newstream); +// CALLBACKS.write = NewNPN_WriteProc(_write); +// CALLBACKS.destroystream = NewNPN_DestroyStreamProc(_destroystream); +// CALLBACKS.status = NewNPN_StatusProc(_status); +// CALLBACKS.uagent = NewNPN_UserAgentProc(_useragent); +// CALLBACKS.memalloc = NewNPN_MemAllocProc(_memalloc); +// CALLBACKS.memfree = NewNPN_MemFreeProc(_memfree); +// CALLBACKS.memflush = NewNPN_MemFlushProc(_memflush); +// CALLBACKS.reloadplugins = NewNPN_ReloadPluginsProc(_reloadplugins); +// CALLBACKS.getJavaEnv = NewNPN_GetJavaEnvProc(_getJavaEnv); +// CALLBACKS.getJavaPeer = NewNPN_GetJavaPeerProc(_getJavaPeer); + CALLBACKS.geturlnotify = NewNPN_GetURLNotifyProc(_geturlnotify); + CALLBACKS.posturlnotify = NewNPN_PostURLNotifyProc(_posturlnotify); +// CALLBACKS.getvalue = NewNPN_GetValueProc(_getvalue); +// CALLBACKS.setvalue = NewNPN_SetValueProc(_setvalue); +// CALLBACKS.invalidaterect = NewNPN_InvalidateRectProc(_invalidaterect); +// CALLBACKS.invalidateregion = NewNPN_InvalidateRegionProc(_invalidateregion); +// CALLBACKS.forceredraw = NewNPN_ForceRedrawProc(_forceredraw); + + initialized = TRUE; +}; + +//////////////////////////////////////////////////////////////////////// + + +ns4xPlugin::ns4xPlugin(NPPluginFuncs* callbacks) +{ + NS_INIT_REFCNT(); + memcpy((void*) &fCallbacks, (void*) callbacks, sizeof(fCallbacks)); + mManager = nsnull; +} + + +ns4xPlugin::~ns4xPlugin(void) +{ + NS_IF_RELEASE(mManager); +} + + +//////////////////////////////////////////////////////////////////////// +// nsISupports stuff + +NS_IMPL_ADDREF(ns4xPlugin); +NS_IMPL_RELEASE(ns4xPlugin); + +static NS_DEFINE_IID(kILiveConnectPluginIID, NS_ILIVECONNECTPLUGIN_IID); +static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +nsresult +ns4xPlugin::QueryInterface(const nsIID& iid, void** instance) +{ + if (instance == NULL) + return NS_ERROR_NULL_POINTER; + + if (iid.Equals(kIPluginIID) || + iid.Equals(kISupportsIID)) { + *instance = (void*) this; + AddRef(); + return NS_OK; + } + + if (iid.Equals(kILiveConnectPluginIID)) { + // Check the 4.x plugin callbacks to see if it supports + // LiveConnect... + if (fCallbacks.javaClass == NULL) + return NS_NOINTERFACE; + + *instance = (void*) this; + AddRef(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + + +//////////////////////////////////////////////////////////////////////// +// Static factory method. +// + +nsresult +ns4xPlugin::CreatePlugin(PRLibrary *library, + nsIPlugin **result) +{ + CheckClassInitialized(); + + NP_GETENTRYPOINTS pfnGetEntryPoints = + (NP_GETENTRYPOINTS)PR_FindSymbol(library, "NP_GetEntryPoints"); + + if (pfnGetEntryPoints == NULL) + return NS_ERROR_FAILURE; + + NPPluginFuncs callbacks; + memset((void*) &callbacks, 0, sizeof(callbacks)); + + callbacks.size = sizeof(callbacks); + + if (pfnGetEntryPoints(&callbacks) != NS_OK) + return NS_ERROR_FAILURE; // XXX + +#ifdef XP_WIN // XXX This is really XP, but we need to figure out how to do HIBYTE() + if (HIBYTE(callbacks.version) < NP_VERSION_MAJOR) + return NS_ERROR_FAILURE; +#endif + + // the NP_Initialize entry point was misnamed as NP_PluginInit, + // early in plugin project development. Its correct name is + // documented now, and new developers expect it to work. However, + // I don't want to break the plugins already in the field, so + // we'll accept either name + NP_PLUGININIT pfnInitialize = + (NP_PLUGININIT)PR_FindSymbol(library, "NP_Initialize"); + + if (!pfnInitialize) { + pfnInitialize = + (NP_PLUGININIT)PR_FindSymbol(library, "NP_PluginInit"); + } + + if (pfnInitialize == NULL) + return NS_ERROR_UNEXPECTED; // XXX Right error? + + if (pfnInitialize(&ns4xPlugin::CALLBACKS) != NS_OK) + return NS_ERROR_UNEXPECTED; // XXX shoudl convert the 4.x error... + + (*result) = new ns4xPlugin(&callbacks); + + if ((*result) == NULL) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} + +nsresult ns4xPlugin :: CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + *aResult = NULL; + + nsISupports *inst; + + inst = nsnull; +// inst = (nsISupports *)(nsIPluginInstance *)new ns4xPluginInstance(); + + if (inst == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsresult res = inst->QueryInterface(aIID, aResult); + + if (res != NS_OK) { + // We didn't get the right interface, so clean up + delete inst; + } + + return res; +} + +nsresult ns4xPlugin :: LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); + +nsresult +ns4xPlugin::Initialize(nsISupports* browserInterfaces) +{ + if (nsnull == mManager) + return browserInterfaces->QueryInterface(kIPluginManagerIID, (void **)&mManager); + else + return NS_OK; +} + +nsresult +ns4xPlugin::Shutdown(void) +{ + NS_IF_RELEASE(mManager); + return NS_OK; +} + +nsresult +ns4xPlugin::GetMIMEDescription(const char* *resultingDesc) +{ + *resultingDesc = ""; + return NS_OK; // XXX make a callback, etc. +} + +nsresult +ns4xPlugin::GetValue(nsPluginVariable variable, void *value) +{ + return NS_OK; +} + +nsresult +ns4xPlugin::SetValue(nsPluginVariable variable, void *value) +{ + return NS_OK; +} + +nsresult +ns4xPlugin::GetJavaClass(jclass *resultingClass) +{ + *resultingClass = fCallbacks.javaClass; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// +// Static callbacks that get routed back through the new C++ API +// + +nsresult NP_EXPORT +ns4xPlugin::_geturl(NPP npp, const char* relativeURL, const char* target) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = nsnull; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = nsnull; + urlinfo.postDataLength = 0; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = PR_FALSE; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + +nsresult NP_EXPORT +ns4xPlugin::_geturlnotify(NPP npp, const char* relativeURL, const char* target, + void* notifyData) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = notifyData; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = nsnull; + urlinfo.postDataLength = 0; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = PR_FALSE; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + + +nsresult NP_EXPORT +ns4xPlugin::_posturlnotify(NPP npp, const char* relativeURL, const char *target, + uint32 len, const char *buf, NPBool file, + void* notifyData) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = notifyData; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = buf; + urlinfo.postDataLength = len; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = file; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + + +nsresult NP_EXPORT +ns4xPlugin::_posturl(NPP npp, const char* relativeURL, const char *target, uint32 len, + const char *buf, NPBool file) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = nsnull; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = buf; + urlinfo.postDataLength = len; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = file; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + +#if 0 + +//////////////////////////////////////////////////////////////////////// + +/** + * A little helper class used to wrap up plugin manager streams (that is, + * streams from the plugin to the browser). + */ +class ns4xStreamWrapper { +protected: + NPIPluginManagerStream* fStream; + NPStream fNPStream; + +public: + ns4xStreamWrapper(NPIPluginManagerStream* stream); + ~ns4xStreamWrapper(); + + NPIPluginManagerStream* + GetStream(void); + + NPStream* + GetNPStream(void) { + return &fNPStream; + }; +}; + +ns4xStreamWrapper::ns4xStreamWrapper(NPIPluginManagerStream* stream) + : fStream(stream) +{ + PR_ASSERT(stream != NULL); + fStream->AddRef(); + + memset(&fNPStream, 0, sizeof(fNPStream)); + fNPStream.ndata = (void*) this; +} + +ns4xStreamWrapper::~ns4xStreamWrapper(void) +{ + if (fStream != NULL) + fStream->Release(); +} + +NPIPluginManagerStream* +ns4xStreamWrapper::GetStream(void) +{ + if (fStream != NULL) + fStream->AddRef(); + + return fStream; +} + +//////////////////////////////////////////////////////////////////////// + + +nsresult NP_EXPORT +ns4xPlugin::_newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX + + nsresult error; + nsIPluginStream* stream; + if ((error = peer->NewStream((const char*) type, window, &stream)) + != NPPluginError_NoError) + return (NPError) error; + + ns4xStreamWrapper* wrapper = new ns4xStreamWrapper(stream); + + if (wrapper == NULL) { + stream->Release(); + return NPERR_OUT_OF_MEMORY_ERROR; + } + + (*result) = wrapper->GetNPStream(); + return NPERR_NO_ERROR; +} + + + +int32 NP_EXPORT +ns4xPlugin::_write(NPP npp, NPStream *pstream, int32 len, void *buffer) +{ + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) npp->ndata; + PR_ASSERT(wrapper != NULL); + if (wrapper == NULL) + return 0; + + NPIPluginManagerStream* stream = wrapper->GetStream(); + PRUint32 count = 0; + while (count < ((PRUint32) len)) { + PRUint32 ready = stream->WriteReady(); + ready = (ready > ((PRUint32) len)) ? ((PRUint32) len) : ready; + + PRUint32 written = stream->Write(ready, ((const char*) buffer) + count); + count += written; + } + + stream->Release(); + + return count; +} + + + +NPError NP_EXPORT +ns4xPlugin::_destroystream(NPP npp, NPStream *pstream, NPError reason) +{ + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) npp->ndata; + PR_ASSERT(wrapper != NULL); + if (wrapper == NULL) + return 0; + + // This will release the wrapped NPIPluginManagerStream. + delete wrapper; + + return NPERR_NO_ERROR; +} + + + +void NP_EXPORT +ns4xPlugin::_status(NPP npp, const char *message) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + peer->ShowStatus(message); +} + + + +void NP_EXPORT +ns4xPlugin::_memfree (void *ptr) +{ + thePluginManager->MemFree(ptr); +} + + + +uint32 NP_EXPORT +ns4xPlugin::_memflush(uint32 size) +{ + return thePluginManager->MemFlush(size); +} + + + +void NP_EXPORT +ns4xPlugin::_reloadplugins(NPBool reloadPages) +{ + thePluginManager->ReloadPlugins(reloadPages); +} + + + +void NP_EXPORT +ns4xPlugin::_invalidaterect(NPP npp, NPRect *invalidRect) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + // XXX nsRect & NPRect are structurally equivalent + peer->InvalidateRect((nsRect*) invalidRect); +} + + + +void NP_EXPORT +ns4xPlugin::_invalidateregion(NPP npp, NPRegion invalidRegion) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + // XXX nsRegion & NPRegion are typedef'd to the same thing + peer->InvalidateRegion((nsRegion*) invalidRegion); +} + + + +void NP_EXPORT +ns4xPlugin::_forceredraw(NPP npp) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + peer->ForceRedraw(); +} + + + +NPError NP_EXPORT +ns4xPlugin::_getvalue(NPP npp, NPNVariable variable, void *result) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NPERR_INVALID_PLUGIN_ERROR; // XXX + + // XXX Note that for backwards compatibility, the old NPNVariables + // map correctly to NPPluginManagerVariables. + return (NPError) peer->GetValue((NPPluginManagerVariable) variable, result); +} + + + +NPError NP_EXPORT +ns4xPlugin::_setvalue(NPP npp, NPPVariable variable, void *result) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NPERR_INVALID_PLUGIN_ERROR; // XXX + + // XXX Note that for backwards compatibility, the old NPPVariables + // map correctly to NPPluginVariables. + return (NPError) peer->SetValue((NPPluginVariable) variable, result); +} + + + +NPError NP_EXPORT +ns4xPlugin::_requestread(NPStream *pstream, NPByteRange *rangeList) +{ + NPIPluginStreamPeer* streamPeer = (NPIPluginStreamPeer*) pstream->ndata; + PR_ASSERT(streamPeer != NULL); + if (streamPeer == NULL) + return NPERR_INVALID_PLUGIN_ERROR; // XXX + + NPISeekablePluginStreamPeer* seekablePeer = NULL; + static NS_DEFINE_IID(kISeekablePluginStreamPeerIID, NP_ISEEKABLEPLUGINSTREAMPEER_IID); + if (streamPeer->QueryInterface(kISeekablePluginStreamPeerIID, + (void**) seekablePeer) == NS_OK) { + NPError error; + + // XXX nsByteRange & NPByteRange are structurally equivalent. + error = (NPError) seekablePeer->RequestRead((nsByteRange*) rangeList); + seekablePeer->Release(); + return error; + } + + return NPERR_STREAM_NOT_SEEKABLE; +} + + +//////////////////////////////////////////////////////////////////////// +// +// On 68K Mac (XXX still supported?), we need to make sure that the +// pointers are in D0 for the following functions that return pointers. +// + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_D0 +#endif + + +JRIEnv* NP_EXPORT +ns4xPlugin::_getJavaEnv(void) +{ + return NULL; +} + + +const char * NP_EXPORT +ns4xPlugin::_useragent(NPP npp) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NULL; + + return peer->UserAgent(); +} + + +void * NP_EXPORT +ns4xPlugin::_memalloc (uint32 size) +{ + return thePluginManager->MemAlloc(size); +} + + +#ifdef JAVA +java_lang_Class* NP_EXPORT +ns4xPlugin::_getJavaClass(void* handle) +{ + // Is this just a generic call into the Java VM? + return NULL; +} +#endif + + + +jref NP_EXPORT +ns4xPlugin::_getJavaPeer(NPP npp) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NULL; + + static NS_DEFINE_IID(kILiveConnectPluginInstancePeerIID, + NP_ILIVECONNECTPLUGININSTANCEPEER_IID); + + NPILiveConnectPluginInstancePeer* lcPeer = NULL; + if (peer->QueryInterface(kILiveConnectPluginInstancePeerIID, + (void**) &lcPeer) == NS_OK) { + jobject result = lcPeer->GetJavaPeer(); + lcPeer->Release(); + return result; + } + + return NULL; +} + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_A0 +#endif + +// +//////////////////////////////////////////////////////////////////////// + +#endif diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.h b/mozilla/modules/plugin/base/src/ns4xPlugin.h new file mode 100644 index 00000000000..5819deb434c --- /dev/null +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.h @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef ns4xPlugin_h__ +#define ns4xPlugin_h__ + +#include "nsplugin.h" +#include "prlink.h" // for PRLibrary +#include "../src/npupp.h" + +//////////////////////////////////////////////////////////////////////// + +/* + * Use this macro before each exported function + * (between the return address and the function + * itself), to ensure that the function has the + * right calling conventions on Win16. + */ + +#ifdef XP_WIN16 +#define NP_EXPORT __export +#elif defined(XP_OS2) +#define NP_EXPORT _System +#else +#define NP_EXPORT +#endif + +//////////////////////////////////////////////////////////////////////// + +/** + * A 5.0 wrapper for a 4.x style plugin. + */ +class ns4xPlugin : public nsILiveConnectPlugin +{ +public: + ns4xPlugin(NPPluginFuncs* callbacks); + ~ns4xPlugin(void); + + NS_DECL_ISUPPORTS + + //nsIFactory interface + + NS_IMETHOD CreateInstance(nsISupports *aOuter, + REFNSIID aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + + //nsIPlugin interface + + NS_IMETHOD + Initialize(nsISupports* browserInterfaces); + + NS_IMETHOD + Shutdown(void); + + NS_IMETHOD + GetMIMEDescription(const char* *resultingDesc); + + NS_IMETHOD + GetValue(nsPluginVariable variable, void *value); + + NS_IMETHOD + SetValue(nsPluginVariable variable, void *value); + + //nsILiveConnectPlugin interface + + NS_IMETHOD + GetJavaClass(jclass *resultingClass); + + //////////////////////////////////////////////////////////////////// + // ns4xPlugin-specific methods + + /** + * A static factory method for constructing 4.x plugins. Constructs + * and initializes an ns4xPlugin object, and returns it in + * result. + */ + static nsresult + CreatePlugin(PRLibrary *library, + nsIPlugin **result); + +protected: + /** + * Ensures that the static CALLBACKS is properly initialized + */ + static void CheckClassInitialized(void); + + //////////////////////////////////////////////////////////////////////// + // Static stub functions that are exported to the 4.x plugin as entry + // points via the CALLBACKS variable. + // + static nsresult NP_EXPORT + _requestread(NPStream *pstream, NPByteRange *rangeList); + + static nsresult NP_EXPORT + _geturlnotify(NPP npp, const char* relativeURL, const char* target, void* notifyData); + + static nsresult NP_EXPORT + _getvalue(NPP npp, NPNVariable variable, void *r_value); + + static nsresult NP_EXPORT + _setvalue(NPP npp, NPPVariable variable, void *r_value); + + static nsresult NP_EXPORT + _geturl(NPP npp, const char* relativeURL, const char* target); + + static nsresult NP_EXPORT + _posturlnotify(NPP npp, const char* relativeURL, const char *target, + uint32 len, const char *buf, NPBool file, void* notifyData); + + static nsresult NP_EXPORT + _posturl(NPP npp, const char* relativeURL, const char *target, uint32 len, + const char *buf, NPBool file); + +#if 0 + + static nsresult NP_EXPORT + _newstream(NPP npp, NPMIMEType type, const char* window, NPStream** pstream); + + static int32 NP_EXPORT + _write(NPP npp, NPStream *pstream, int32 len, void *buffer); + + static nsresult NP_EXPORT + _destroystream(NPP npp, NPStream *pstream, NPError reason); + + static void NP_EXPORT + _status(NPP npp, const char *message); + + static void NP_EXPORT + _registerwindow(NPP npp, void* window); + + static void NP_EXPORT + _unregisterwindow(NPP npp, void* window); + + static int16 NP_EXPORT + _allocateMenuID(NPP npp, NPBool isSubmenu); + + static void NP_EXPORT + _memfree (void *ptr); + + static uint32 NP_EXPORT + _memflush(uint32 size); + + static void NP_EXPORT + _reloadplugins(NPBool reloadPages); + + static void NP_EXPORT + _invalidaterect(NPP npp, NPRect *invalidRect); + + static void NP_EXPORT + _invalidateregion(NPP npp, NPRegion invalidRegion); + + static void NP_EXPORT + _forceredraw(NPP npp); + + //////////////////////////////////////////////////////////////////////// + // Anything that returns a pointer needs to be _HERE_ for 68K Mac to + // work. + // + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_D0 +#endif + + static const char* NP_EXPORT + _useragent(NPP npp); + + static void* NP_EXPORT + _memalloc (uint32 size); + + static JRIEnv* NP_EXPORT + _getJavaEnv(void); + + static jref NP_EXPORT + _getJavaPeer(NPP npp); + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_A0 +#endif + +#endif + + /** + * The plugin-side callbacks that the browser calls. One set of + * plugin callbacks for each plugin. + */ + NPPluginFuncs fCallbacks; + + /** + * The browser-side callbacks that a 4.x-style plugin calls. + */ + static NPNetscapeFuncs CALLBACKS; + + static nsIPluginManager *mManager; +}; + +#endif // ns4xPlugin_h__ diff --git a/mozilla/modules/plugin/base/src/nsIPluginHost.h b/mozilla/modules/plugin/base/src/nsIPluginHost.h new file mode 100644 index 00000000000..a2f541676e2 --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsIPluginHost.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef nsIPluginHost_h___ +#define nsIPluginHost_h___ + +#include "nsplugindefs.h" + +#define NS_IPLUGINHOST_IID \ +{ 0x264c0640, 0x1c31, 0x11d2, \ +{ 0xa8, 0x2e, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } + +struct nsIPluginHost : public nsISupports +{ +public: + + NS_IMETHOD + Init(void) = 0; + + NS_IMETHOD + LoadPlugins(void) = 0; + + NS_IMETHOD + InstantiatePlugin(char *aMimeType, nsISupports ** aPluginInst) = 0; +}; + +#endif diff --git a/mozilla/modules/plugin/base/src/nsPluginFactory.cpp b/mozilla/modules/plugin/base/src/nsPluginFactory.cpp new file mode 100644 index 00000000000..78a0601874c --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsPluginFactory.cpp @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#include "nscore.h" +#include "nsIFactory.h" +#include "nsISupports.h" + +#include "nsPluginsCID.h" +#include "nsPluginHostImpl.h" + +static NS_DEFINE_IID(kCPluginHost, NS_PLUGIN_HOST_CID); + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + +class nsPluginFactory : public nsIFactory +{ + public: + // nsISupports methods + NS_IMETHOD QueryInterface(const nsIID &aIID, + void **aResult); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + + nsPluginFactory(const nsCID &aClass); + + protected: + virtual ~nsPluginFactory(); + + private: + nsrefcnt mRefCnt; + nsCID mClassID; +}; + +nsPluginFactory :: nsPluginFactory(const nsCID &aClass) +{ + mRefCnt = 0; + mClassID = aClass; +} + +nsPluginFactory :: ~nsPluginFactory() +{ + NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction"); +} + +nsresult nsPluginFactory :: QueryInterface(const nsIID &aIID, + void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + // Always NULL result, in case of failure + *aResult = NULL; + + if (aIID.Equals(kISupportsIID)) { + *aResult = (void *)(nsISupports*)this; + } else if (aIID.Equals(kIFactoryIID)) { + *aResult = (void *)(nsIFactory*)this; + } + + if (*aResult == NULL) { + return NS_NOINTERFACE; + } + + AddRef(); // Increase reference count for caller + return NS_OK; +} + +nsrefcnt nsPluginFactory :: AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt nsPluginFactory :: Release() +{ + if (--mRefCnt == 0) { + delete this; + return 0; // Don't access mRefCnt after deleting! + } + return mRefCnt; +} + +nsresult nsPluginFactory :: CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + *aResult = NULL; + + nsISupports *inst = nsnull; + + if (mClassID.Equals(kCPluginHost)) { + inst = (nsISupports *)(nsIPluginManager *)new nsPluginHostImpl(); + } + + if (inst == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsresult res = inst->QueryInterface(aIID, aResult); + + if (res != NS_OK) { + // We didn't get the right interface, so clean up + delete inst; + } + + return res; +} + +nsresult nsPluginFactory :: LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +// return the proper factory to the caller +extern "C" NS_PLUGIN nsresult NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) +{ + if (nsnull == aFactory) { + return NS_ERROR_NULL_POINTER; + } + + *aFactory = new nsPluginFactory(aClass); + + if (nsnull == aFactory) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory); +} diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp new file mode 100644 index 00000000000..10a50d39e46 --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#include "nsPluginHostImpl.h" +#include +#include "prio.h" +#include "prmem.h" +#include "ns4xPlugin.h" + +#ifdef XP_PC +#include "windows.h" +#endif + +nsPluginTag :: nsPluginTag() +{ + mNext = nsnull; + mName = nsnull; + mDescription = nsnull; + mMimeType = nsnull; + mMimeDescription = nsnull; + mExtensions = nsnull; + mVariants = 0; + mMimeTypeArray = nsnull; + mMimeDescriptionArray = nsnull; + mExtensionsArray = nsnull; + mLibrary = nsnull; + mEntryPoint = nsnull; + mFlags = NS_PLUGIN_FLAG_ENABLED; +} + +nsPluginTag :: ~nsPluginTag() +{ + if (nsnull != mName) + { + PR_Free(mName); + mName = nsnull; + } + + if (nsnull != mDescription) + { + PR_Free(mDescription); + mDescription = nsnull; + } + + if (nsnull != mMimeType) + { + PR_Free(mMimeType); + mMimeType = nsnull; + } + + if (nsnull != mMimeDescription) + { + PR_Free(mMimeDescription); + mMimeDescription = nsnull; + } + + if (nsnull != mExtensions) + { + PR_Free(mExtensions); + mExtensions = nsnull; + } + + if (nsnull != mMimeTypeArray) + { + PR_Free(mMimeTypeArray); + mMimeTypeArray = nsnull; + } + + if (nsnull != mMimeDescriptionArray) + { + PR_Free(mMimeDescriptionArray); + mMimeDescriptionArray = nsnull; + } + + if (nsnull != mExtensionsArray) + { + PR_Free(mExtensionsArray); + mExtensionsArray = nsnull; + } + + if (nsnull != mLibrary) + { + PR_UnloadLibrary(mLibrary); + mLibrary = nsnull; + } + + mEntryPoint = nsnull; +} + +static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); +static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +nsPluginHostImpl :: nsPluginHostImpl() +{ +} + +nsPluginHostImpl :: ~nsPluginHostImpl() +{ + if (nsnull != mPluginPath) + { + PR_Free(mPluginPath); + mPluginPath = nsnull; + } + + while (nsnull != mPlugins) + { + nsPluginTag *temp = mPlugins->mNext; + delete mPlugins; + mPlugins = temp; + } +} + +NS_IMPL_ADDREF(nsPluginHostImpl) +NS_IMPL_RELEASE(nsPluginHostImpl) + +nsresult nsPluginHostImpl :: QueryInterface(const nsIID& aIID, + void** aInstancePtrResult) +{ + NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer"); + + if (nsnull == aInstancePtrResult) + return NS_ERROR_NULL_POINTER; + + if (aIID.Equals(kIPluginManagerIID)) + { + *aInstancePtrResult = (void *)((nsIPluginManager *)this); + AddRef(); + return NS_OK; + } + + if (aIID.Equals(kIPluginHostIID)) + { + *aInstancePtrResult = (void *)((nsIPluginHost *)this); + AddRef(); + return NS_OK; + } + + if (aIID.Equals(kISupportsIID)) + { + *aInstancePtrResult = (void *)((nsISupports *)((nsIPluginHost *)this)); + AddRef(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + +nsresult nsPluginHostImpl :: ReloadPlugins(PRBool reloadPages) +{ + return LoadPlugins(); +} + +//XXX need to find out score on this one... MMP +nsresult nsPluginHostImpl :: UserAgent(const char **retstring) +{ + *retstring = "NGLayout"; + return NS_OK; +} + +nsresult nsPluginHostImpl :: GetValue(nsPluginManagerVariable variable, void *value) +{ + return NS_OK; +} + +nsresult nsPluginHostImpl :: SetValue(nsPluginManagerVariable variable, void *value) +{ + return NS_OK; +} + +//nsresult nsPluginHostImpl :: FetchURL(nsISupports* peer, nsURLInfo* urlInfo) +//{ +// return NS_OK; +//} + +nsresult nsPluginHostImpl :: Init(void) +{ + return NS_OK; +} + +nsresult nsPluginHostImpl :: LoadPlugins(void) +{ +#ifdef XP_PC + long result; + HKEY keyloc; + DWORD type, pathlen; + char path[2000]; + + path[0] = 0; + + result = ::RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Netscape\\Netscape Navigator\\Main", + 0, KEY_READ, &keyloc); + + if (result == ERROR_SUCCESS) + { + pathlen = sizeof(path); + + result = ::RegQueryValueEx(keyloc, "Install Directory", + NULL, &type, (LPBYTE)&path, &pathlen); + + if (result == ERROR_SUCCESS) + { + strcat(path, "\\Program\\Plugins"); + printf("plugins at: %s\n", path); + } + + ::RegCloseKey(keyloc); + } + + PRDir *dir; + + dir = PR_OpenDir(path); + + if (nsnull != dir) + { + PRDirEntry *dent; + char *verbuf = NULL; + DWORD verbufsize = 0; + + pathlen = strlen(path); + mPluginPath = (char *)PR_Malloc(pathlen + 2); + + if (nsnull != mPluginPath) + { + strcpy(mPluginPath, path); + + mPluginPath[pathlen] = '\\'; + mPluginPath[pathlen + 1] = 0; + } + + while (nsnull != mPlugins) + { + nsPluginTag *temp = mPlugins->mNext; + delete mPlugins; + mPlugins = temp; + } + + while (dent = PR_ReadDir(dir, PR_SKIP_BOTH)) + { + PRInt32 len = strlen(dent->name); + + if (len > 6) //np*.dll + { + if ((0 == stricmp(&dent->name[len - 4], ".dll")) && //ends in '.dll' + (0 == strnicmp(dent->name, "np", 2))) //starts with 'np' + { + PRLibrary *plugin; + + strcpy(path, mPluginPath); + strcat(path, dent->name); + + plugin = PR_LoadLibrary(path); + + if (NULL != plugin) + { + DWORD zerome, versionsize; + + versionsize = ::GetFileVersionInfoSize(path, &zerome); + + if (versionsize > 0) + { + if (versionsize > verbufsize) + { + if (nsnull != verbuf) + PR_Free(verbuf); + + verbuf = (char *)PR_Malloc(versionsize); + verbufsize = versionsize; + } + + if ((nsnull != verbuf) && ::GetFileVersionInfo(path, NULL, verbufsize, verbuf)) + { + char *buf = NULL; + UINT blen; + nsPluginTag *plugintag; + PRBool completetag = PR_FALSE; + PRInt32 variants; + + plugintag = new nsPluginTag(); + + while (nsnull != plugintag) + { + plugintag->mName = (char *)PR_Malloc(strlen(dent->name) + 1); + + if (nsnull == plugintag->mName) + break; + else + strcpy(plugintag->mName, dent->name); + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\FileDescription"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mDescription = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mDescription) + break; + else + strcpy(plugintag->mDescription, buf); + } + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\MIMEType"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mMimeType = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mMimeType) + break; + else + strcpy(plugintag->mMimeType, buf); + + buf = plugintag->mMimeType; + + variants = 1; + + while (*buf) + { + if (*buf == '|') + variants++; + + buf++; + } + + plugintag->mVariants = variants; + + plugintag->mMimeTypeArray = (char **)PR_Malloc(variants * sizeof(char *)); + + if (nsnull == plugintag->mMimeTypeArray) + break; + else + { + variants = 0; + + plugintag->mMimeTypeArray[variants++] = plugintag->mMimeType; + + buf = plugintag->mMimeType; + + while (*buf) + { + if (*buf == '|') + { + plugintag->mMimeTypeArray[variants++] = buf + 1; + *buf = 0; + } + + buf++; + } + } + } + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\FileOpenName"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mMimeDescription = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mMimeDescription) + break; + else + strcpy(plugintag->mMimeDescription, buf); + + buf = plugintag->mMimeDescription; + + variants = 1; + + while (*buf) + { + if (*buf == '|') + variants++; + + buf++; + } + + if (variants != plugintag->mVariants) + break; + + plugintag->mMimeDescriptionArray = (char **)PR_Malloc(variants * sizeof(char *)); + + if (nsnull == plugintag->mMimeDescriptionArray) + break; + else + { + variants = 0; + + plugintag->mMimeDescriptionArray[variants++] = plugintag->mMimeDescription; + + buf = plugintag->mMimeDescription; + + while (*buf) + { + if (*buf == '|') + { + plugintag->mMimeDescriptionArray[variants++] = buf + 1; + *buf = 0; + } + + buf++; + } + } + } + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\FileExtents"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mExtensions = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mExtensions) + break; + else + strcpy(plugintag->mExtensions, buf); + + buf = plugintag->mExtensions; + + variants = 1; + + while (*buf) + { + if (*buf == '|') + variants++; + + buf++; + } + + if (variants != plugintag->mVariants) + break; + + plugintag->mExtensionsArray = (char **)PR_Malloc(variants * sizeof(char *)); + + if (nsnull == plugintag->mExtensionsArray) + break; + else + { + variants = 0; + + plugintag->mExtensionsArray[variants++] = plugintag->mExtensions; + + buf = plugintag->mExtensions; + + while (*buf) + { + if (*buf == '|') + { + plugintag->mExtensionsArray[variants++] = buf + 1; + *buf = 0; + } + + buf++; + } + } + } + + completetag = PR_TRUE; + break; + } + + if (PR_FALSE == completetag) + delete plugintag; + else + { + if (nsnull == PR_FindSymbol(plugin, "NSGetFactory")) + plugintag->mFlags |= NS_PLUGIN_FLAG_OLDSCHOOL; + +printf("plugin %s added to list %s\n", plugintag->mName, (plugintag->mFlags & NS_PLUGIN_FLAG_OLDSCHOOL) ? "(old school)" : ""); + plugintag->mNext = mPlugins; + mPlugins = plugintag; + } + } + } + + PR_UnloadLibrary(plugin); + } + } + } + } + + if (nsnull != verbuf) + PR_Free(verbuf); + + PR_CloseDir(dir); + } + +#else + printf("Don't know how to locate plugins directory on Unix yet...\n"); +#endif + + return NS_OK; +} + +nsresult nsPluginHostImpl :: InstantiatePlugin(char *aMimeType, nsISupports ** aPluginInst) +{ + nsPluginTag *plugins = mPlugins; + PRInt32 variants, cnt; + + while (nsnull != plugins) + { + variants = plugins->mVariants; + + for (cnt = 0; cnt < variants; cnt++) + { + if (0 == strcmp(plugins->mMimeTypeArray[cnt], aMimeType)) + break; + } + + if (cnt < variants) + break; + + plugins = plugins->mNext; + } + + if (nsnull != plugins) + { + if (nsnull == plugins->mLibrary) + { + char path[2000]; + + strcpy(path, mPluginPath); + strcat(path, plugins->mName); + + plugins->mLibrary = PR_LoadLibrary(path); +printf("loaded plugin %s for mime type %s\n", plugins->mName, aMimeType); + } + + if (nsnull != plugins->mLibrary) + { + if (nsnull == plugins->mEntryPoint) + { + if (plugins->mFlags & NS_PLUGIN_FLAG_OLDSCHOOL) + plugins->mEntryPoint = PR_FindSymbol(plugins->mLibrary, "NP_Initialize"); + else + plugins->mEntryPoint = PR_FindSymbol(plugins->mLibrary, "NSGetFactory"); + } + } + else + return NS_ERROR_UNEXPECTED; + + return NS_OK; + } + else + { +printf("unable to find plugin to handle %s\n", aMimeType); + + return NS_ERROR_FAILURE; + } +} diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h new file mode 100644 index 00000000000..f45b16c50f3 --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef nsPluginHostImpl_h__ +#define nsPluginHostImpl_h__ + +#include "xp_core.h" +#include "nsIPluginManager.h" +#include "nsIPluginHost.h" +#include "nsCRT.h" +#include "prlink.h" + +class ns4xPlugin; + +class nsPluginTag +{ +public: + nsPluginTag(); + ~nsPluginTag(); + + nsPluginTag *mNext; + char *mName; + char *mDescription; + char *mMimeType; + char *mMimeDescription; + char *mExtensions; + PRInt32 mVariants; + char **mMimeTypeArray; + char **mMimeDescriptionArray; + char **mExtensionsArray; + PRLibrary *mLibrary; + void *mEntryPoint; + ns4xPlugin *mAdapter; + PRUint32 mFlags; +}; + +#define NS_PLUGIN_FLAG_ENABLED 0x0001 //is this plugin enabled? +#define NS_PLUGIN_FLAG_OLDSCHOOL 0x0002 //is this a pre-xpcom plugin? + +class nsPluginHostImpl : public nsIPluginManager, public nsIPluginHost +{ +public: + nsPluginHostImpl(); + ~nsPluginHostImpl(); + + void* operator new(size_t sz) { + void* rv = new char[sz]; + nsCRT::zero(rv, sz); + return rv; + } + + NS_DECL_ISUPPORTS + + //nsIPluginManager interface + + NS_IMETHOD + ReloadPlugins(PRBool reloadPages); + + NS_IMETHOD + UserAgent(const char* *resultingAgentString); + + NS_IMETHOD + GetValue(nsPluginManagerVariable variable, void *value); + + NS_IMETHOD + SetValue(nsPluginManagerVariable variable, void *value); + +// NS_IMETHOD +// FetchURL(nsISupports* peer, nsURLInfo* urlInfo); + + //nsIPluginHost interface + + NS_IMETHOD + Init(void); + + NS_IMETHOD + LoadPlugins(void); + + NS_IMETHOD + InstantiatePlugin(char *aMimeType, nsISupports ** aPluginInst); + +private: + char *mPluginPath; + nsPluginTag *mPlugins; +}; + +#endif diff --git a/mozilla/modules/plugin/base/src/nsPluginsCID.h b/mozilla/modules/plugin/base/src/nsPluginsCID.h new file mode 100644 index 00000000000..dc547fc32f3 --- /dev/null +++ b/mozilla/modules/plugin/base/src/nsPluginsCID.h @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#ifndef nsPluginsCID_h__ +#define nsPluginsCID_h__ + +#include "nsISupports.h" +#include "nsIFactory.h" +#include "nsRepository.h" + +#define NS_PLUGIN_HOST_CID \ +{ 0xadea1880, 0x1a8e, 0x11d2, \ +{ 0xa8, 0x2e, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } + +#endif // nsPluginsCID_h__ diff --git a/mozilla/modules/plugin/nglsrc/Makefile b/mozilla/modules/plugin/nglsrc/Makefile new file mode 100644 index 00000000000..5d054a68240 --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/Makefile @@ -0,0 +1,44 @@ +#!nmake +# +# 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. + +DEPTH=../../.. + +include $(DEPTH)/config/config.mk + +MODULE=raptor + +LIBRARY_NAME=raptorplugin + +EXPORTS = \ + nsPluginsCID.h \ + nsIPluginHost.h + +CPPSRCS = \ + nsPluginHostImpl.cpp \ + nsPluginFactory.cpp \ + ns4xPlugin.cpp \ + $(NULL) + +REQUIRES = raptor plugin java xpcom + +LCFLAGS =-D_IMPL_NS_PLUGIN + +TARGETS = $(LIBRARY) + +INCLUDES += -I. + +include $(DEPTH)/config/rules.mk diff --git a/mozilla/modules/plugin/nglsrc/makefile.win b/mozilla/modules/plugin/nglsrc/makefile.win new file mode 100644 index 00000000000..fcdaec4c366 --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/makefile.win @@ -0,0 +1,71 @@ +#!nmake +# +# 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. + +DEPTH=..\..\.. +IGNORE_MANIFEST=1 + +EXPORTS = \ + nsPluginsCID.h \ + nsIPluginHost.h + +MAKE_OBJ_TYPE = DLL +DLLNAME = raptorplugin +DLL=.\$(OBJDIR)\$(DLLNAME).dll +MISCDEP = $(OURLIBS) + +MODULE=raptor + +DEFINES =-D_IMPL_NS_PLUGIN -DWIN32_LEAN_AND_MEAN + +OBJS = \ + .\$(OBJDIR)\nsPluginHostImpl.obj \ + .\$(OBJDIR)\nsPluginFactory.obj \ + .\$(OBJDIR)\ns4xPlugin.obj \ + $(NULL) + +LINCS= \ + -I$(PUBLIC)\raptor \ + -I$(PUBLIC)\xpcom \ + -I$(PUBLIC)\plugin \ + -I$(PUBLIC)\java \ + $(NULL) + + +LCFLAGS = \ + $(LCFLAGS) \ + -D_IMPL_NS_PLUGIN \ + $(NULL) + +OURLIBS= \ + $(DIST)\lib\xpcom32.lib \ + $(DIST)\lib\raptorbase.lib \ + $(LIBNSPR) + +LLIBS= \ + $(OURLIBS) \ + version.lib + +include <$(DEPTH)\config\rules.mak> + +it: + echo $(LLIBS) + +install:: $(DLL) + $(MAKE_INSTALL) .\$(OBJDIR)\$(DLLNAME).dll $(DIST)\bin + +clobber:: + rm -f $(DIST)\bin\$(DLLNAME).dll diff --git a/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp b/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp new file mode 100644 index 00000000000..c0de5348bde --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp @@ -0,0 +1,737 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +// TODO: Implement Java callbacks + +#include "xp_core.h" +#include "nsplugin.h" +#include "ns4xPlugin.h" +//#include "ns4xPluginInstance.h" + +//////////////////////////////////////////////////////////////////////// + +// XXX These are defined in platform specific FE directories right now :-/ +typedef NPError (*NP_GETENTRYPOINTS)(NPPluginFuncs* pCallbacks); +typedef NPError (*NP_PLUGININIT)(const NPNetscapeFuncs* pCallbacks); +typedef NPError (*NP_PLUGINSHUTDOWN)(); + + +//////////////////////////////////////////////////////////////////////// + +NPNetscapeFuncs ns4xPlugin::CALLBACKS; +nsIPluginManager * ns4xPlugin::mManager; + +void +ns4xPlugin::CheckClassInitialized(void) +{ + static PRBool initialized = FALSE; + + if (initialized) + return; + + mManager = nsnull; + + // XXX It'd be nice to make this const and initialize it + // statically... + CALLBACKS.size = sizeof(CALLBACKS); + CALLBACKS.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR; + + CALLBACKS.geturl = NewNPN_GetURLProc(_geturl); + CALLBACKS.posturl = NewNPN_PostURLProc(_posturl); +// CALLBACKS.requestread = NewNPN_RequestReadProc(_requestread); +// CALLBACKS.newstream = NewNPN_NewStreamProc(_newstream); +// CALLBACKS.write = NewNPN_WriteProc(_write); +// CALLBACKS.destroystream = NewNPN_DestroyStreamProc(_destroystream); +// CALLBACKS.status = NewNPN_StatusProc(_status); +// CALLBACKS.uagent = NewNPN_UserAgentProc(_useragent); +// CALLBACKS.memalloc = NewNPN_MemAllocProc(_memalloc); +// CALLBACKS.memfree = NewNPN_MemFreeProc(_memfree); +// CALLBACKS.memflush = NewNPN_MemFlushProc(_memflush); +// CALLBACKS.reloadplugins = NewNPN_ReloadPluginsProc(_reloadplugins); +// CALLBACKS.getJavaEnv = NewNPN_GetJavaEnvProc(_getJavaEnv); +// CALLBACKS.getJavaPeer = NewNPN_GetJavaPeerProc(_getJavaPeer); + CALLBACKS.geturlnotify = NewNPN_GetURLNotifyProc(_geturlnotify); + CALLBACKS.posturlnotify = NewNPN_PostURLNotifyProc(_posturlnotify); +// CALLBACKS.getvalue = NewNPN_GetValueProc(_getvalue); +// CALLBACKS.setvalue = NewNPN_SetValueProc(_setvalue); +// CALLBACKS.invalidaterect = NewNPN_InvalidateRectProc(_invalidaterect); +// CALLBACKS.invalidateregion = NewNPN_InvalidateRegionProc(_invalidateregion); +// CALLBACKS.forceredraw = NewNPN_ForceRedrawProc(_forceredraw); + + initialized = TRUE; +}; + +//////////////////////////////////////////////////////////////////////// + + +ns4xPlugin::ns4xPlugin(NPPluginFuncs* callbacks) +{ + NS_INIT_REFCNT(); + memcpy((void*) &fCallbacks, (void*) callbacks, sizeof(fCallbacks)); + mManager = nsnull; +} + + +ns4xPlugin::~ns4xPlugin(void) +{ + NS_IF_RELEASE(mManager); +} + + +//////////////////////////////////////////////////////////////////////// +// nsISupports stuff + +NS_IMPL_ADDREF(ns4xPlugin); +NS_IMPL_RELEASE(ns4xPlugin); + +static NS_DEFINE_IID(kILiveConnectPluginIID, NS_ILIVECONNECTPLUGIN_IID); +static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +nsresult +ns4xPlugin::QueryInterface(const nsIID& iid, void** instance) +{ + if (instance == NULL) + return NS_ERROR_NULL_POINTER; + + if (iid.Equals(kIPluginIID) || + iid.Equals(kISupportsIID)) { + *instance = (void*) this; + AddRef(); + return NS_OK; + } + + if (iid.Equals(kILiveConnectPluginIID)) { + // Check the 4.x plugin callbacks to see if it supports + // LiveConnect... + if (fCallbacks.javaClass == NULL) + return NS_NOINTERFACE; + + *instance = (void*) this; + AddRef(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + + +//////////////////////////////////////////////////////////////////////// +// Static factory method. +// + +nsresult +ns4xPlugin::CreatePlugin(PRLibrary *library, + nsIPlugin **result) +{ + CheckClassInitialized(); + + NP_GETENTRYPOINTS pfnGetEntryPoints = + (NP_GETENTRYPOINTS)PR_FindSymbol(library, "NP_GetEntryPoints"); + + if (pfnGetEntryPoints == NULL) + return NS_ERROR_FAILURE; + + NPPluginFuncs callbacks; + memset((void*) &callbacks, 0, sizeof(callbacks)); + + callbacks.size = sizeof(callbacks); + + if (pfnGetEntryPoints(&callbacks) != NS_OK) + return NS_ERROR_FAILURE; // XXX + +#ifdef XP_WIN // XXX This is really XP, but we need to figure out how to do HIBYTE() + if (HIBYTE(callbacks.version) < NP_VERSION_MAJOR) + return NS_ERROR_FAILURE; +#endif + + // the NP_Initialize entry point was misnamed as NP_PluginInit, + // early in plugin project development. Its correct name is + // documented now, and new developers expect it to work. However, + // I don't want to break the plugins already in the field, so + // we'll accept either name + NP_PLUGININIT pfnInitialize = + (NP_PLUGININIT)PR_FindSymbol(library, "NP_Initialize"); + + if (!pfnInitialize) { + pfnInitialize = + (NP_PLUGININIT)PR_FindSymbol(library, "NP_PluginInit"); + } + + if (pfnInitialize == NULL) + return NS_ERROR_UNEXPECTED; // XXX Right error? + + if (pfnInitialize(&ns4xPlugin::CALLBACKS) != NS_OK) + return NS_ERROR_UNEXPECTED; // XXX shoudl convert the 4.x error... + + (*result) = new ns4xPlugin(&callbacks); + + if ((*result) == NULL) + return NS_ERROR_OUT_OF_MEMORY; + + return NS_OK; +} + +nsresult ns4xPlugin :: CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + *aResult = NULL; + + nsISupports *inst; + + inst = nsnull; +// inst = (nsISupports *)(nsIPluginInstance *)new ns4xPluginInstance(); + + if (inst == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsresult res = inst->QueryInterface(aIID, aResult); + + if (res != NS_OK) { + // We didn't get the right interface, so clean up + delete inst; + } + + return res; +} + +nsresult ns4xPlugin :: LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); + +nsresult +ns4xPlugin::Initialize(nsISupports* browserInterfaces) +{ + if (nsnull == mManager) + return browserInterfaces->QueryInterface(kIPluginManagerIID, (void **)&mManager); + else + return NS_OK; +} + +nsresult +ns4xPlugin::Shutdown(void) +{ + NS_IF_RELEASE(mManager); + return NS_OK; +} + +nsresult +ns4xPlugin::GetMIMEDescription(const char* *resultingDesc) +{ + *resultingDesc = ""; + return NS_OK; // XXX make a callback, etc. +} + +nsresult +ns4xPlugin::GetValue(nsPluginVariable variable, void *value) +{ + return NS_OK; +} + +nsresult +ns4xPlugin::SetValue(nsPluginVariable variable, void *value) +{ + return NS_OK; +} + +nsresult +ns4xPlugin::GetJavaClass(jclass *resultingClass) +{ + *resultingClass = fCallbacks.javaClass; + return NS_OK; +} + +//////////////////////////////////////////////////////////////////////// +// +// Static callbacks that get routed back through the new C++ API +// + +nsresult NP_EXPORT +ns4xPlugin::_geturl(NPP npp, const char* relativeURL, const char* target) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = nsnull; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = nsnull; + urlinfo.postDataLength = 0; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = PR_FALSE; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + +nsresult NP_EXPORT +ns4xPlugin::_geturlnotify(NPP npp, const char* relativeURL, const char* target, + void* notifyData) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = notifyData; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = nsnull; + urlinfo.postDataLength = 0; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = PR_FALSE; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + + +nsresult NP_EXPORT +ns4xPlugin::_posturlnotify(NPP npp, const char* relativeURL, const char *target, + uint32 len, const char *buf, NPBool file, + void* notifyData) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = notifyData; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = buf; + urlinfo.postDataLength = len; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = file; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + + +nsresult NP_EXPORT +ns4xPlugin::_posturl(NPP npp, const char* relativeURL, const char *target, uint32 len, + const char *buf, NPBool file) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + NS_ASSERTION(mManager != NULL, "null manager"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX +#if 0 + nsURLInfo urlinfo; + + urlinfo.version = nsURLInfo_Version; + urlinfo.url = relativeURL; + urlinfo.target = target; + urlinfo.notifyData = nsnull; + urlinfo.altHost = nsnull; + urlinfo.referrer = nsnull; + urlinfo.forceJSEnabled = PR_FALSE; + urlinfo.postData = buf; + urlinfo.postDataLength = len; + urlinfo.postHeaders = nsnull; + urlinfo.postHeadersLength = 0; + urlinfo.postFile = file; + + return mManager->FetchURL(peer, &urlinfo); +#endif + return NS_OK; +} + +#if 0 + +//////////////////////////////////////////////////////////////////////// + +/** + * A little helper class used to wrap up plugin manager streams (that is, + * streams from the plugin to the browser). + */ +class ns4xStreamWrapper { +protected: + NPIPluginManagerStream* fStream; + NPStream fNPStream; + +public: + ns4xStreamWrapper(NPIPluginManagerStream* stream); + ~ns4xStreamWrapper(); + + NPIPluginManagerStream* + GetStream(void); + + NPStream* + GetNPStream(void) { + return &fNPStream; + }; +}; + +ns4xStreamWrapper::ns4xStreamWrapper(NPIPluginManagerStream* stream) + : fStream(stream) +{ + PR_ASSERT(stream != NULL); + fStream->AddRef(); + + memset(&fNPStream, 0, sizeof(fNPStream)); + fNPStream.ndata = (void*) this; +} + +ns4xStreamWrapper::~ns4xStreamWrapper(void) +{ + if (fStream != NULL) + fStream->Release(); +} + +NPIPluginManagerStream* +ns4xStreamWrapper::GetStream(void) +{ + if (fStream != NULL) + fStream->AddRef(); + + return fStream; +} + +//////////////////////////////////////////////////////////////////////// + + +nsresult NP_EXPORT +ns4xPlugin::_newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result) +{ + nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata; + + NS_ASSERTION(peer != NULL, "null peer"); + + if (peer == NULL) + return NS_ERROR_UNEXPECTED; // XXX + + nsresult error; + nsIPluginStream* stream; + if ((error = peer->NewStream((const char*) type, window, &stream)) + != NPPluginError_NoError) + return (NPError) error; + + ns4xStreamWrapper* wrapper = new ns4xStreamWrapper(stream); + + if (wrapper == NULL) { + stream->Release(); + return NPERR_OUT_OF_MEMORY_ERROR; + } + + (*result) = wrapper->GetNPStream(); + return NPERR_NO_ERROR; +} + + + +int32 NP_EXPORT +ns4xPlugin::_write(NPP npp, NPStream *pstream, int32 len, void *buffer) +{ + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) npp->ndata; + PR_ASSERT(wrapper != NULL); + if (wrapper == NULL) + return 0; + + NPIPluginManagerStream* stream = wrapper->GetStream(); + PRUint32 count = 0; + while (count < ((PRUint32) len)) { + PRUint32 ready = stream->WriteReady(); + ready = (ready > ((PRUint32) len)) ? ((PRUint32) len) : ready; + + PRUint32 written = stream->Write(ready, ((const char*) buffer) + count); + count += written; + } + + stream->Release(); + + return count; +} + + + +NPError NP_EXPORT +ns4xPlugin::_destroystream(NPP npp, NPStream *pstream, NPError reason) +{ + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) npp->ndata; + PR_ASSERT(wrapper != NULL); + if (wrapper == NULL) + return 0; + + // This will release the wrapped NPIPluginManagerStream. + delete wrapper; + + return NPERR_NO_ERROR; +} + + + +void NP_EXPORT +ns4xPlugin::_status(NPP npp, const char *message) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + peer->ShowStatus(message); +} + + + +void NP_EXPORT +ns4xPlugin::_memfree (void *ptr) +{ + thePluginManager->MemFree(ptr); +} + + + +uint32 NP_EXPORT +ns4xPlugin::_memflush(uint32 size) +{ + return thePluginManager->MemFlush(size); +} + + + +void NP_EXPORT +ns4xPlugin::_reloadplugins(NPBool reloadPages) +{ + thePluginManager->ReloadPlugins(reloadPages); +} + + + +void NP_EXPORT +ns4xPlugin::_invalidaterect(NPP npp, NPRect *invalidRect) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + // XXX nsRect & NPRect are structurally equivalent + peer->InvalidateRect((nsRect*) invalidRect); +} + + + +void NP_EXPORT +ns4xPlugin::_invalidateregion(NPP npp, NPRegion invalidRegion) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + // XXX nsRegion & NPRegion are typedef'd to the same thing + peer->InvalidateRegion((nsRegion*) invalidRegion); +} + + + +void NP_EXPORT +ns4xPlugin::_forceredraw(NPP npp) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return; + + peer->ForceRedraw(); +} + + + +NPError NP_EXPORT +ns4xPlugin::_getvalue(NPP npp, NPNVariable variable, void *result) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NPERR_INVALID_PLUGIN_ERROR; // XXX + + // XXX Note that for backwards compatibility, the old NPNVariables + // map correctly to NPPluginManagerVariables. + return (NPError) peer->GetValue((NPPluginManagerVariable) variable, result); +} + + + +NPError NP_EXPORT +ns4xPlugin::_setvalue(NPP npp, NPPVariable variable, void *result) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NPERR_INVALID_PLUGIN_ERROR; // XXX + + // XXX Note that for backwards compatibility, the old NPPVariables + // map correctly to NPPluginVariables. + return (NPError) peer->SetValue((NPPluginVariable) variable, result); +} + + + +NPError NP_EXPORT +ns4xPlugin::_requestread(NPStream *pstream, NPByteRange *rangeList) +{ + NPIPluginStreamPeer* streamPeer = (NPIPluginStreamPeer*) pstream->ndata; + PR_ASSERT(streamPeer != NULL); + if (streamPeer == NULL) + return NPERR_INVALID_PLUGIN_ERROR; // XXX + + NPISeekablePluginStreamPeer* seekablePeer = NULL; + static NS_DEFINE_IID(kISeekablePluginStreamPeerIID, NP_ISEEKABLEPLUGINSTREAMPEER_IID); + if (streamPeer->QueryInterface(kISeekablePluginStreamPeerIID, + (void**) seekablePeer) == NS_OK) { + NPError error; + + // XXX nsByteRange & NPByteRange are structurally equivalent. + error = (NPError) seekablePeer->RequestRead((nsByteRange*) rangeList); + seekablePeer->Release(); + return error; + } + + return NPERR_STREAM_NOT_SEEKABLE; +} + + +//////////////////////////////////////////////////////////////////////// +// +// On 68K Mac (XXX still supported?), we need to make sure that the +// pointers are in D0 for the following functions that return pointers. +// + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_D0 +#endif + + +JRIEnv* NP_EXPORT +ns4xPlugin::_getJavaEnv(void) +{ + return NULL; +} + + +const char * NP_EXPORT +ns4xPlugin::_useragent(NPP npp) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NULL; + + return peer->UserAgent(); +} + + +void * NP_EXPORT +ns4xPlugin::_memalloc (uint32 size) +{ + return thePluginManager->MemAlloc(size); +} + + +#ifdef JAVA +java_lang_Class* NP_EXPORT +ns4xPlugin::_getJavaClass(void* handle) +{ + // Is this just a generic call into the Java VM? + return NULL; +} +#endif + + + +jref NP_EXPORT +ns4xPlugin::_getJavaPeer(NPP npp) +{ + NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata; + PR_ASSERT(peer != NULL); + if (peer == NULL) + return NULL; + + static NS_DEFINE_IID(kILiveConnectPluginInstancePeerIID, + NP_ILIVECONNECTPLUGININSTANCEPEER_IID); + + NPILiveConnectPluginInstancePeer* lcPeer = NULL; + if (peer->QueryInterface(kILiveConnectPluginInstancePeerIID, + (void**) &lcPeer) == NS_OK) { + jobject result = lcPeer->GetJavaPeer(); + lcPeer->Release(); + return result; + } + + return NULL; +} + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_A0 +#endif + +// +//////////////////////////////////////////////////////////////////////// + +#endif diff --git a/mozilla/modules/plugin/nglsrc/ns4xPlugin.h b/mozilla/modules/plugin/nglsrc/ns4xPlugin.h new file mode 100644 index 00000000000..5819deb434c --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/ns4xPlugin.h @@ -0,0 +1,213 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef ns4xPlugin_h__ +#define ns4xPlugin_h__ + +#include "nsplugin.h" +#include "prlink.h" // for PRLibrary +#include "../src/npupp.h" + +//////////////////////////////////////////////////////////////////////// + +/* + * Use this macro before each exported function + * (between the return address and the function + * itself), to ensure that the function has the + * right calling conventions on Win16. + */ + +#ifdef XP_WIN16 +#define NP_EXPORT __export +#elif defined(XP_OS2) +#define NP_EXPORT _System +#else +#define NP_EXPORT +#endif + +//////////////////////////////////////////////////////////////////////// + +/** + * A 5.0 wrapper for a 4.x style plugin. + */ +class ns4xPlugin : public nsILiveConnectPlugin +{ +public: + ns4xPlugin(NPPluginFuncs* callbacks); + ~ns4xPlugin(void); + + NS_DECL_ISUPPORTS + + //nsIFactory interface + + NS_IMETHOD CreateInstance(nsISupports *aOuter, + REFNSIID aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + + //nsIPlugin interface + + NS_IMETHOD + Initialize(nsISupports* browserInterfaces); + + NS_IMETHOD + Shutdown(void); + + NS_IMETHOD + GetMIMEDescription(const char* *resultingDesc); + + NS_IMETHOD + GetValue(nsPluginVariable variable, void *value); + + NS_IMETHOD + SetValue(nsPluginVariable variable, void *value); + + //nsILiveConnectPlugin interface + + NS_IMETHOD + GetJavaClass(jclass *resultingClass); + + //////////////////////////////////////////////////////////////////// + // ns4xPlugin-specific methods + + /** + * A static factory method for constructing 4.x plugins. Constructs + * and initializes an ns4xPlugin object, and returns it in + * result. + */ + static nsresult + CreatePlugin(PRLibrary *library, + nsIPlugin **result); + +protected: + /** + * Ensures that the static CALLBACKS is properly initialized + */ + static void CheckClassInitialized(void); + + //////////////////////////////////////////////////////////////////////// + // Static stub functions that are exported to the 4.x plugin as entry + // points via the CALLBACKS variable. + // + static nsresult NP_EXPORT + _requestread(NPStream *pstream, NPByteRange *rangeList); + + static nsresult NP_EXPORT + _geturlnotify(NPP npp, const char* relativeURL, const char* target, void* notifyData); + + static nsresult NP_EXPORT + _getvalue(NPP npp, NPNVariable variable, void *r_value); + + static nsresult NP_EXPORT + _setvalue(NPP npp, NPPVariable variable, void *r_value); + + static nsresult NP_EXPORT + _geturl(NPP npp, const char* relativeURL, const char* target); + + static nsresult NP_EXPORT + _posturlnotify(NPP npp, const char* relativeURL, const char *target, + uint32 len, const char *buf, NPBool file, void* notifyData); + + static nsresult NP_EXPORT + _posturl(NPP npp, const char* relativeURL, const char *target, uint32 len, + const char *buf, NPBool file); + +#if 0 + + static nsresult NP_EXPORT + _newstream(NPP npp, NPMIMEType type, const char* window, NPStream** pstream); + + static int32 NP_EXPORT + _write(NPP npp, NPStream *pstream, int32 len, void *buffer); + + static nsresult NP_EXPORT + _destroystream(NPP npp, NPStream *pstream, NPError reason); + + static void NP_EXPORT + _status(NPP npp, const char *message); + + static void NP_EXPORT + _registerwindow(NPP npp, void* window); + + static void NP_EXPORT + _unregisterwindow(NPP npp, void* window); + + static int16 NP_EXPORT + _allocateMenuID(NPP npp, NPBool isSubmenu); + + static void NP_EXPORT + _memfree (void *ptr); + + static uint32 NP_EXPORT + _memflush(uint32 size); + + static void NP_EXPORT + _reloadplugins(NPBool reloadPages); + + static void NP_EXPORT + _invalidaterect(NPP npp, NPRect *invalidRect); + + static void NP_EXPORT + _invalidateregion(NPP npp, NPRegion invalidRegion); + + static void NP_EXPORT + _forceredraw(NPP npp); + + //////////////////////////////////////////////////////////////////////// + // Anything that returns a pointer needs to be _HERE_ for 68K Mac to + // work. + // + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_D0 +#endif + + static const char* NP_EXPORT + _useragent(NPP npp); + + static void* NP_EXPORT + _memalloc (uint32 size); + + static JRIEnv* NP_EXPORT + _getJavaEnv(void); + + static jref NP_EXPORT + _getJavaPeer(NPP npp); + +#if defined(XP_MAC) && !defined(powerc) +#pragma pointers_in_A0 +#endif + +#endif + + /** + * The plugin-side callbacks that the browser calls. One set of + * plugin callbacks for each plugin. + */ + NPPluginFuncs fCallbacks; + + /** + * The browser-side callbacks that a 4.x-style plugin calls. + */ + static NPNetscapeFuncs CALLBACKS; + + static nsIPluginManager *mManager; +}; + +#endif // ns4xPlugin_h__ diff --git a/mozilla/modules/plugin/nglsrc/nsIPluginHost.h b/mozilla/modules/plugin/nglsrc/nsIPluginHost.h new file mode 100644 index 00000000000..a2f541676e2 --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/nsIPluginHost.h @@ -0,0 +1,42 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef nsIPluginHost_h___ +#define nsIPluginHost_h___ + +#include "nsplugindefs.h" + +#define NS_IPLUGINHOST_IID \ +{ 0x264c0640, 0x1c31, 0x11d2, \ +{ 0xa8, 0x2e, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } + +struct nsIPluginHost : public nsISupports +{ +public: + + NS_IMETHOD + Init(void) = 0; + + NS_IMETHOD + LoadPlugins(void) = 0; + + NS_IMETHOD + InstantiatePlugin(char *aMimeType, nsISupports ** aPluginInst) = 0; +}; + +#endif diff --git a/mozilla/modules/plugin/nglsrc/nsPluginFactory.cpp b/mozilla/modules/plugin/nglsrc/nsPluginFactory.cpp new file mode 100644 index 00000000000..78a0601874c --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/nsPluginFactory.cpp @@ -0,0 +1,156 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#include "nscore.h" +#include "nsIFactory.h" +#include "nsISupports.h" + +#include "nsPluginsCID.h" +#include "nsPluginHostImpl.h" + +static NS_DEFINE_IID(kCPluginHost, NS_PLUGIN_HOST_CID); + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID); + +class nsPluginFactory : public nsIFactory +{ + public: + // nsISupports methods + NS_IMETHOD QueryInterface(const nsIID &aIID, + void **aResult); + NS_IMETHOD_(nsrefcnt) AddRef(void); + NS_IMETHOD_(nsrefcnt) Release(void); + + // nsIFactory methods + NS_IMETHOD CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult); + + NS_IMETHOD LockFactory(PRBool aLock); + + nsPluginFactory(const nsCID &aClass); + + protected: + virtual ~nsPluginFactory(); + + private: + nsrefcnt mRefCnt; + nsCID mClassID; +}; + +nsPluginFactory :: nsPluginFactory(const nsCID &aClass) +{ + mRefCnt = 0; + mClassID = aClass; +} + +nsPluginFactory :: ~nsPluginFactory() +{ + NS_ASSERTION(mRefCnt == 0, "non-zero refcnt at destruction"); +} + +nsresult nsPluginFactory :: QueryInterface(const nsIID &aIID, + void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + // Always NULL result, in case of failure + *aResult = NULL; + + if (aIID.Equals(kISupportsIID)) { + *aResult = (void *)(nsISupports*)this; + } else if (aIID.Equals(kIFactoryIID)) { + *aResult = (void *)(nsIFactory*)this; + } + + if (*aResult == NULL) { + return NS_NOINTERFACE; + } + + AddRef(); // Increase reference count for caller + return NS_OK; +} + +nsrefcnt nsPluginFactory :: AddRef() +{ + return ++mRefCnt; +} + +nsrefcnt nsPluginFactory :: Release() +{ + if (--mRefCnt == 0) { + delete this; + return 0; // Don't access mRefCnt after deleting! + } + return mRefCnt; +} + +nsresult nsPluginFactory :: CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + if (aResult == NULL) { + return NS_ERROR_NULL_POINTER; + } + + *aResult = NULL; + + nsISupports *inst = nsnull; + + if (mClassID.Equals(kCPluginHost)) { + inst = (nsISupports *)(nsIPluginManager *)new nsPluginHostImpl(); + } + + if (inst == NULL) { + return NS_ERROR_OUT_OF_MEMORY; + } + + nsresult res = inst->QueryInterface(aIID, aResult); + + if (res != NS_OK) { + // We didn't get the right interface, so clean up + delete inst; + } + + return res; +} + +nsresult nsPluginFactory :: LockFactory(PRBool aLock) +{ + // Not implemented in simplest case. + return NS_OK; +} + +// return the proper factory to the caller +extern "C" NS_PLUGIN nsresult NSGetFactory(const nsCID &aClass, nsIFactory **aFactory) +{ + if (nsnull == aFactory) { + return NS_ERROR_NULL_POINTER; + } + + *aFactory = new nsPluginFactory(aClass); + + if (nsnull == aFactory) { + return NS_ERROR_OUT_OF_MEMORY; + } + + return (*aFactory)->QueryInterface(kIFactoryIID, (void**)aFactory); +} diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp new file mode 100644 index 00000000000..10a50d39e46 --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp @@ -0,0 +1,578 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#include "nsPluginHostImpl.h" +#include +#include "prio.h" +#include "prmem.h" +#include "ns4xPlugin.h" + +#ifdef XP_PC +#include "windows.h" +#endif + +nsPluginTag :: nsPluginTag() +{ + mNext = nsnull; + mName = nsnull; + mDescription = nsnull; + mMimeType = nsnull; + mMimeDescription = nsnull; + mExtensions = nsnull; + mVariants = 0; + mMimeTypeArray = nsnull; + mMimeDescriptionArray = nsnull; + mExtensionsArray = nsnull; + mLibrary = nsnull; + mEntryPoint = nsnull; + mFlags = NS_PLUGIN_FLAG_ENABLED; +} + +nsPluginTag :: ~nsPluginTag() +{ + if (nsnull != mName) + { + PR_Free(mName); + mName = nsnull; + } + + if (nsnull != mDescription) + { + PR_Free(mDescription); + mDescription = nsnull; + } + + if (nsnull != mMimeType) + { + PR_Free(mMimeType); + mMimeType = nsnull; + } + + if (nsnull != mMimeDescription) + { + PR_Free(mMimeDescription); + mMimeDescription = nsnull; + } + + if (nsnull != mExtensions) + { + PR_Free(mExtensions); + mExtensions = nsnull; + } + + if (nsnull != mMimeTypeArray) + { + PR_Free(mMimeTypeArray); + mMimeTypeArray = nsnull; + } + + if (nsnull != mMimeDescriptionArray) + { + PR_Free(mMimeDescriptionArray); + mMimeDescriptionArray = nsnull; + } + + if (nsnull != mExtensionsArray) + { + PR_Free(mExtensionsArray); + mExtensionsArray = nsnull; + } + + if (nsnull != mLibrary) + { + PR_UnloadLibrary(mLibrary); + mLibrary = nsnull; + } + + mEntryPoint = nsnull; +} + +static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID); +static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID); +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); + +nsPluginHostImpl :: nsPluginHostImpl() +{ +} + +nsPluginHostImpl :: ~nsPluginHostImpl() +{ + if (nsnull != mPluginPath) + { + PR_Free(mPluginPath); + mPluginPath = nsnull; + } + + while (nsnull != mPlugins) + { + nsPluginTag *temp = mPlugins->mNext; + delete mPlugins; + mPlugins = temp; + } +} + +NS_IMPL_ADDREF(nsPluginHostImpl) +NS_IMPL_RELEASE(nsPluginHostImpl) + +nsresult nsPluginHostImpl :: QueryInterface(const nsIID& aIID, + void** aInstancePtrResult) +{ + NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer"); + + if (nsnull == aInstancePtrResult) + return NS_ERROR_NULL_POINTER; + + if (aIID.Equals(kIPluginManagerIID)) + { + *aInstancePtrResult = (void *)((nsIPluginManager *)this); + AddRef(); + return NS_OK; + } + + if (aIID.Equals(kIPluginHostIID)) + { + *aInstancePtrResult = (void *)((nsIPluginHost *)this); + AddRef(); + return NS_OK; + } + + if (aIID.Equals(kISupportsIID)) + { + *aInstancePtrResult = (void *)((nsISupports *)((nsIPluginHost *)this)); + AddRef(); + return NS_OK; + } + + return NS_NOINTERFACE; +} + +nsresult nsPluginHostImpl :: ReloadPlugins(PRBool reloadPages) +{ + return LoadPlugins(); +} + +//XXX need to find out score on this one... MMP +nsresult nsPluginHostImpl :: UserAgent(const char **retstring) +{ + *retstring = "NGLayout"; + return NS_OK; +} + +nsresult nsPluginHostImpl :: GetValue(nsPluginManagerVariable variable, void *value) +{ + return NS_OK; +} + +nsresult nsPluginHostImpl :: SetValue(nsPluginManagerVariable variable, void *value) +{ + return NS_OK; +} + +//nsresult nsPluginHostImpl :: FetchURL(nsISupports* peer, nsURLInfo* urlInfo) +//{ +// return NS_OK; +//} + +nsresult nsPluginHostImpl :: Init(void) +{ + return NS_OK; +} + +nsresult nsPluginHostImpl :: LoadPlugins(void) +{ +#ifdef XP_PC + long result; + HKEY keyloc; + DWORD type, pathlen; + char path[2000]; + + path[0] = 0; + + result = ::RegOpenKeyEx(HKEY_CURRENT_USER, + "Software\\Netscape\\Netscape Navigator\\Main", + 0, KEY_READ, &keyloc); + + if (result == ERROR_SUCCESS) + { + pathlen = sizeof(path); + + result = ::RegQueryValueEx(keyloc, "Install Directory", + NULL, &type, (LPBYTE)&path, &pathlen); + + if (result == ERROR_SUCCESS) + { + strcat(path, "\\Program\\Plugins"); + printf("plugins at: %s\n", path); + } + + ::RegCloseKey(keyloc); + } + + PRDir *dir; + + dir = PR_OpenDir(path); + + if (nsnull != dir) + { + PRDirEntry *dent; + char *verbuf = NULL; + DWORD verbufsize = 0; + + pathlen = strlen(path); + mPluginPath = (char *)PR_Malloc(pathlen + 2); + + if (nsnull != mPluginPath) + { + strcpy(mPluginPath, path); + + mPluginPath[pathlen] = '\\'; + mPluginPath[pathlen + 1] = 0; + } + + while (nsnull != mPlugins) + { + nsPluginTag *temp = mPlugins->mNext; + delete mPlugins; + mPlugins = temp; + } + + while (dent = PR_ReadDir(dir, PR_SKIP_BOTH)) + { + PRInt32 len = strlen(dent->name); + + if (len > 6) //np*.dll + { + if ((0 == stricmp(&dent->name[len - 4], ".dll")) && //ends in '.dll' + (0 == strnicmp(dent->name, "np", 2))) //starts with 'np' + { + PRLibrary *plugin; + + strcpy(path, mPluginPath); + strcat(path, dent->name); + + plugin = PR_LoadLibrary(path); + + if (NULL != plugin) + { + DWORD zerome, versionsize; + + versionsize = ::GetFileVersionInfoSize(path, &zerome); + + if (versionsize > 0) + { + if (versionsize > verbufsize) + { + if (nsnull != verbuf) + PR_Free(verbuf); + + verbuf = (char *)PR_Malloc(versionsize); + verbufsize = versionsize; + } + + if ((nsnull != verbuf) && ::GetFileVersionInfo(path, NULL, verbufsize, verbuf)) + { + char *buf = NULL; + UINT blen; + nsPluginTag *plugintag; + PRBool completetag = PR_FALSE; + PRInt32 variants; + + plugintag = new nsPluginTag(); + + while (nsnull != plugintag) + { + plugintag->mName = (char *)PR_Malloc(strlen(dent->name) + 1); + + if (nsnull == plugintag->mName) + break; + else + strcpy(plugintag->mName, dent->name); + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\FileDescription"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mDescription = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mDescription) + break; + else + strcpy(plugintag->mDescription, buf); + } + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\MIMEType"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mMimeType = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mMimeType) + break; + else + strcpy(plugintag->mMimeType, buf); + + buf = plugintag->mMimeType; + + variants = 1; + + while (*buf) + { + if (*buf == '|') + variants++; + + buf++; + } + + plugintag->mVariants = variants; + + plugintag->mMimeTypeArray = (char **)PR_Malloc(variants * sizeof(char *)); + + if (nsnull == plugintag->mMimeTypeArray) + break; + else + { + variants = 0; + + plugintag->mMimeTypeArray[variants++] = plugintag->mMimeType; + + buf = plugintag->mMimeType; + + while (*buf) + { + if (*buf == '|') + { + plugintag->mMimeTypeArray[variants++] = buf + 1; + *buf = 0; + } + + buf++; + } + } + } + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\FileOpenName"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mMimeDescription = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mMimeDescription) + break; + else + strcpy(plugintag->mMimeDescription, buf); + + buf = plugintag->mMimeDescription; + + variants = 1; + + while (*buf) + { + if (*buf == '|') + variants++; + + buf++; + } + + if (variants != plugintag->mVariants) + break; + + plugintag->mMimeDescriptionArray = (char **)PR_Malloc(variants * sizeof(char *)); + + if (nsnull == plugintag->mMimeDescriptionArray) + break; + else + { + variants = 0; + + plugintag->mMimeDescriptionArray[variants++] = plugintag->mMimeDescription; + + buf = plugintag->mMimeDescription; + + while (*buf) + { + if (*buf == '|') + { + plugintag->mMimeDescriptionArray[variants++] = buf + 1; + *buf = 0; + } + + buf++; + } + } + } + + ::VerQueryValue(verbuf, + TEXT("\\StringFileInfo\\040904E4\\FileExtents"), + (void **)&buf, &blen); + + if (NULL == buf) + break; + else + { + plugintag->mExtensions = (char *)PR_Malloc(blen + 1); + + if (nsnull == plugintag->mExtensions) + break; + else + strcpy(plugintag->mExtensions, buf); + + buf = plugintag->mExtensions; + + variants = 1; + + while (*buf) + { + if (*buf == '|') + variants++; + + buf++; + } + + if (variants != plugintag->mVariants) + break; + + plugintag->mExtensionsArray = (char **)PR_Malloc(variants * sizeof(char *)); + + if (nsnull == plugintag->mExtensionsArray) + break; + else + { + variants = 0; + + plugintag->mExtensionsArray[variants++] = plugintag->mExtensions; + + buf = plugintag->mExtensions; + + while (*buf) + { + if (*buf == '|') + { + plugintag->mExtensionsArray[variants++] = buf + 1; + *buf = 0; + } + + buf++; + } + } + } + + completetag = PR_TRUE; + break; + } + + if (PR_FALSE == completetag) + delete plugintag; + else + { + if (nsnull == PR_FindSymbol(plugin, "NSGetFactory")) + plugintag->mFlags |= NS_PLUGIN_FLAG_OLDSCHOOL; + +printf("plugin %s added to list %s\n", plugintag->mName, (plugintag->mFlags & NS_PLUGIN_FLAG_OLDSCHOOL) ? "(old school)" : ""); + plugintag->mNext = mPlugins; + mPlugins = plugintag; + } + } + } + + PR_UnloadLibrary(plugin); + } + } + } + } + + if (nsnull != verbuf) + PR_Free(verbuf); + + PR_CloseDir(dir); + } + +#else + printf("Don't know how to locate plugins directory on Unix yet...\n"); +#endif + + return NS_OK; +} + +nsresult nsPluginHostImpl :: InstantiatePlugin(char *aMimeType, nsISupports ** aPluginInst) +{ + nsPluginTag *plugins = mPlugins; + PRInt32 variants, cnt; + + while (nsnull != plugins) + { + variants = plugins->mVariants; + + for (cnt = 0; cnt < variants; cnt++) + { + if (0 == strcmp(plugins->mMimeTypeArray[cnt], aMimeType)) + break; + } + + if (cnt < variants) + break; + + plugins = plugins->mNext; + } + + if (nsnull != plugins) + { + if (nsnull == plugins->mLibrary) + { + char path[2000]; + + strcpy(path, mPluginPath); + strcat(path, plugins->mName); + + plugins->mLibrary = PR_LoadLibrary(path); +printf("loaded plugin %s for mime type %s\n", plugins->mName, aMimeType); + } + + if (nsnull != plugins->mLibrary) + { + if (nsnull == plugins->mEntryPoint) + { + if (plugins->mFlags & NS_PLUGIN_FLAG_OLDSCHOOL) + plugins->mEntryPoint = PR_FindSymbol(plugins->mLibrary, "NP_Initialize"); + else + plugins->mEntryPoint = PR_FindSymbol(plugins->mLibrary, "NSGetFactory"); + } + } + else + return NS_ERROR_UNEXPECTED; + + return NS_OK; + } + else + { +printf("unable to find plugin to handle %s\n", aMimeType); + + return NS_ERROR_FAILURE; + } +} diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h new file mode 100644 index 00000000000..f45b16c50f3 --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h @@ -0,0 +1,102 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef nsPluginHostImpl_h__ +#define nsPluginHostImpl_h__ + +#include "xp_core.h" +#include "nsIPluginManager.h" +#include "nsIPluginHost.h" +#include "nsCRT.h" +#include "prlink.h" + +class ns4xPlugin; + +class nsPluginTag +{ +public: + nsPluginTag(); + ~nsPluginTag(); + + nsPluginTag *mNext; + char *mName; + char *mDescription; + char *mMimeType; + char *mMimeDescription; + char *mExtensions; + PRInt32 mVariants; + char **mMimeTypeArray; + char **mMimeDescriptionArray; + char **mExtensionsArray; + PRLibrary *mLibrary; + void *mEntryPoint; + ns4xPlugin *mAdapter; + PRUint32 mFlags; +}; + +#define NS_PLUGIN_FLAG_ENABLED 0x0001 //is this plugin enabled? +#define NS_PLUGIN_FLAG_OLDSCHOOL 0x0002 //is this a pre-xpcom plugin? + +class nsPluginHostImpl : public nsIPluginManager, public nsIPluginHost +{ +public: + nsPluginHostImpl(); + ~nsPluginHostImpl(); + + void* operator new(size_t sz) { + void* rv = new char[sz]; + nsCRT::zero(rv, sz); + return rv; + } + + NS_DECL_ISUPPORTS + + //nsIPluginManager interface + + NS_IMETHOD + ReloadPlugins(PRBool reloadPages); + + NS_IMETHOD + UserAgent(const char* *resultingAgentString); + + NS_IMETHOD + GetValue(nsPluginManagerVariable variable, void *value); + + NS_IMETHOD + SetValue(nsPluginManagerVariable variable, void *value); + +// NS_IMETHOD +// FetchURL(nsISupports* peer, nsURLInfo* urlInfo); + + //nsIPluginHost interface + + NS_IMETHOD + Init(void); + + NS_IMETHOD + LoadPlugins(void); + + NS_IMETHOD + InstantiatePlugin(char *aMimeType, nsISupports ** aPluginInst); + +private: + char *mPluginPath; + nsPluginTag *mPlugins; +}; + +#endif diff --git a/mozilla/modules/plugin/nglsrc/nsPluginsCID.h b/mozilla/modules/plugin/nglsrc/nsPluginsCID.h new file mode 100644 index 00000000000..dc547fc32f3 --- /dev/null +++ b/mozilla/modules/plugin/nglsrc/nsPluginsCID.h @@ -0,0 +1,30 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * 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. + */ + +#ifndef nsPluginsCID_h__ +#define nsPluginsCID_h__ + +#include "nsISupports.h" +#include "nsIFactory.h" +#include "nsRepository.h" + +#define NS_PLUGIN_HOST_CID \ +{ 0xadea1880, 0x1a8e, 0x11d2, \ +{ 0xa8, 0x2e, 0x00, 0x40, 0x95, 0x9a, 0x28, 0xc9 } } + +#endif // nsPluginsCID_h__ diff --git a/mozilla/modules/plugin/public/nsIEventHandler.h b/mozilla/modules/plugin/public/nsIEventHandler.h new file mode 100644 index 00000000000..1e6be85041f --- /dev/null +++ b/mozilla/modules/plugin/public/nsIEventHandler.h @@ -0,0 +1,81 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsIEventHandler_h___ +#define nsIEventHandler_h___ + +#include "nsplugindefs.h" + +//////////////////////////////////////////////////////////////////////////////// +// Plugin Instance Interface + +/** + * The nsIEventHandler interface provides the callback to handle events. + * It is implemented by the plugin, and is the superclass for nsIPluginInstance. + */ +class nsIEventHandler : public nsISupports { +public: + + /** + * Handles an event. An nsIEventHandler can also get registered with with + * nsIPluginManager2::RegisterWindow and will be called whenever an event + * comes in for that window. + * + * Note that for Unix and Mac the nsPluginEvent structure is different + * from the old NPEvent structure -- it's no longer the native event + * record, but is instead a struct. This was done for future extensibility, + * and so that the Mac could receive the window argument too. For Windows + * and OS2, it's always been a struct, so there's no change for them. + * + * (Corresponds to NPP_HandleEvent.) + * + * @param event - the event to be handled + * @param handled - set to PR_TRUE if event was handled + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + HandleEvent(nsPluginEvent* event, PRBool* handled) = 0; + +}; + +#define NS_IEVENTHANDLER_IID \ +{ /* a447ddf0-1a99-11d2-815f-006008119d7a */ \ + 0xa447ddf0, \ + 0x1a99, \ + 0x11d2, \ + {0x81, 0x5f, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIEventHandler_h___ */ diff --git a/mozilla/modules/plugin/public/nsIJRILiveConnectPlugInstPeer.h b/mozilla/modules/plugin/public/nsIJRILiveConnectPlugInstPeer.h new file mode 100644 index 00000000000..434858b943e --- /dev/null +++ b/mozilla/modules/plugin/public/nsIJRILiveConnectPlugInstPeer.h @@ -0,0 +1,98 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsIJRILiveConnectPluginInstancePeer_h__ +#define nsIJRILiveConnectPluginInstancePeer_h__ + +#include "nsplugindefs.h" +#include "nsISupports.h" + +//////////////////////////////////////////////////////////////////////////////// +// JRI-Based LiveConnect Classes +//////////////////////////////////////////////////////////////////////////////// +// +// This stuff is here so that the browser can support older JRI-based +// LiveConnected plugins (when using old plugin to new C++-style plugin +// adapter code). +// +// Warning: Don't use this anymore, unless you're sure that you have to! +//////////////////////////////////////////////////////////////////////////////// + +#include "jri.h" + +/** + * The nsIJRILiveConnectPluginInstancePeer interface is implemented by browsers + * that support JRI-based LiveConnect. Note that for 5.0, LiveConnect support + * has become JNI-based, so this interface is effectively deprecated. + * + * To obtain: QueryInterface on nsIPluginInstancePeer + */ +class nsIJRILiveConnectPluginInstancePeer : public nsISupports { +public: + + /** + * Returns a JRI reference to the Java peer object associated with the + * plugin instance. This object is an instance of the class specified + * by nsIJRILiveConnectPlugin::GetJavaClass. + * + * (Corresponds to NPN_GetJavaPeer.) + * + * @param resultingJavaPeer - a resulting reference to the Java instance + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + GetJavaPeer(jref *resultingJavaPeer) = 0; + +}; + +#define NS_IJRILIVECONNECTPLUGININSTANCEPEER_IID \ +{ /* 25b63f40-f773-11d1-815b-006008119d7a */ \ + 0x25b63f40, \ + 0xf773, \ + 0x11d1, \ + {0x81, 0x5b, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +// QueryInterface for this IID on nsIPluginManager to get a JRIEnv +// XXX change this +#define NS_IJRIENV_IID \ +{ /* f9d4ea00-a1bc-11d1-85b1-00805f0e4dfe */ \ + 0xf9d4ea00, \ + 0xa1bc, \ + 0x11d1, \ + {0x85, 0xb1, 0x00, 0x80, 0x5f, 0x0e, 0x4d, 0xfe} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIJRILiveConnectPluginInstancePeer_h__ */ diff --git a/mozilla/modules/plugin/public/nsILiveConnectPlugInstPeer.h b/mozilla/modules/plugin/public/nsILiveConnectPlugInstPeer.h new file mode 100644 index 00000000000..fd4b600dcab --- /dev/null +++ b/mozilla/modules/plugin/public/nsILiveConnectPlugInstPeer.h @@ -0,0 +1,86 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsILiveConnectPluginInstancePeer_h___ +#define nsILiveConnectPluginInstancePeer_h___ + +#include "nsplugindefs.h" +#include "nsISupports.h" +#include "jni.h" // standard JVM API + +/** + * The nsILiveConnectPluginInstancePeer interface is implemented by browsers + * that support LiveConnect, i.e. scriptability via JavaScript. Note that this + * LiveConnect interface is now JNI-based (since 5.0). + * + * To obtain: QueryInterface on nsIPluginInstancePeer + */ +class nsILiveConnectPluginInstancePeer : public nsISupports { +public: + + /** + * Returns a JNI reference to the Java peer object associated with the + * plugin instance. This object is an instance of the class specified + * by nsIJRILiveConnectPlugin::GetJavaClass. + * + * (New JNI-based entry point, roughly corresponds to NPN_GetJavaPeer.) + * + * @param resultingJavaPeer - a resulting reference to the Java instance + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + GetJavaPeer(jobject *resultingJavaPeer) = 0; + +}; + +#define NS_ILIVECONNECTPLUGININSTANCEPEER_IID \ +{ /* 1e3502a0-a1bd-11d1-85b1-00805f0e4dfe */ \ + 0x1e3502a0, \ + 0xa1bd, \ + 0x11d1, \ + {0x85, 0xb1, 0x00, 0x80, 0x5f, 0x0e, 0x4d, 0xfe} \ +} + +// QueryInterface for this IID on nsIPluginManager to get a JNIEnv +// XXX change this +#define NS_IJNIENV_IID \ +{ /* 04610650-a1bd-11d1-85b1-00805f0e4dfe */ \ + 0x04610650, \ + 0xa1bd, \ + 0x11d1, \ + {0x85, 0xb1, 0x00, 0x80, 0x5f, 0x0e, 0x4d, 0xfe} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsILiveConnectPluginInstancePeer_h___ */ diff --git a/mozilla/modules/plugin/public/nsINetworkManager.h b/mozilla/modules/plugin/public/nsINetworkManager.h new file mode 100644 index 00000000000..0e67c56e6f0 --- /dev/null +++ b/mozilla/modules/plugin/public/nsINetworkManager.h @@ -0,0 +1,118 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsINetworkManager_h___ +#define nsINetworkManager_h___ + +#include "nsplugindefs.h" +#include "nsISupports.h" + +/** + * The nsINetworkManager interface provides access to the network for URL get + * and post operations. + */ +class nsINetworkManager : public nsISupports { +public: + + /** + * Fetches a URL. + * + * (Corresponds to NPN_GetURL and NPN_GetURLNotify.) + * + * @param url - the URL to fetch + * @param target - the target window into which to load the URL + * @param notifyData - when present, URLNotify is called passing the + * notifyData back to the client. When NULL, this call behaves like + * NPN_GetURL. + * @param altHost - an IP-address string that will be used instead of the + * host specified in the URL. This is used to prevent DNS-spoofing + * attacks. Can be defaulted to NULL meaning use the host in the URL. + * @param referrer - the referring URL (may be NULL) + * @param forceJSEnabled - forces JavaScript to be enabled for 'javascript:' + * URLs, even if the user currently has JavaScript disabled (usually + * specify PR_FALSE) + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + GetURL(nsISupports* peer, const char* url, const char* target, + void* notifyData = NULL, const char* altHost = NULL, + const char* referrer = NULL, PRBool forceJSEnabled = PR_FALSE) = 0; + + /** + * Posts to a URL with post data and/or post headers. + * + * (Corresponds to NPN_PostURL and NPN_PostURLNotify.) + * + * @param url - the URL to fetch + * @param target - the target window into which to load the URL + * @param postDataLength - the length of postData (if non-NULL) + * @param postData - the data to POST. NULL specifies that there is not post + * data + * @param isFile - whether the postData specifies the name of a file to + * post instead of data. The file will be deleted afterwards. + * @param notifyData - when present, URLNotify is called passing the + * notifyData back to the client. When NULL, this call behaves like + * NPN_GetURL. + * @param altHost - an IP-address string that will be used instead of the + * host specified in the URL. This is used to prevent DNS-spoofing + * attacks. Can be defaulted to NULL meaning use the host in the URL. + * @param referrer - the referring URL (may be NULL) + * @param forceJSEnabled - forces JavaScript to be enabled for 'javascript:' + * URLs, even if the user currently has JavaScript disabled (usually + * specify PR_FALSE) + * @param postHeadersLength - the length of postHeaders (if non-NULL) + * @param postHeaders - the headers to POST. NULL specifies that there + * are no post headers + * @result - NS_OK if this operation was successful + */ + NS_IMETHOD + PostURL(nsISupports* peer, const char* url, const char* target, + PRUint32 postDataLen, const char* postData, + PRBool isFile = PR_FALSE, void* notifyData = NULL, + const char* altHost = NULL, const char* referrer = NULL, + PRBool forceJSEnabled = PR_FALSE, + PRUint32 postHeadersLength = 0, const char* postHeaders = NULL) = 0; + +}; + +#define NS_INETWORKMANAGER_IID \ +{ /* fc2eede0-20fe-11d2-8160-006008119d7a */ \ + 0xfc2eede0, \ + 0x20fe, \ + 0x11d2, \ + {0x81, 0x60, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsINetworkManager_h___ */ diff --git a/mozilla/modules/plugin/public/nsIWindowlessPlugInstPeer.h b/mozilla/modules/plugin/public/nsIWindowlessPlugInstPeer.h new file mode 100644 index 00000000000..973c072499c --- /dev/null +++ b/mozilla/modules/plugin/public/nsIWindowlessPlugInstPeer.h @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +/** + * INTERFACE TO NETSCAPE COMMUNICATOR PLUGINS (NEW C++ API). + * + *

    This superscedes the old plugin API (npapi.h, npupp.h), and + * eliminates the need for glue files: npunix.c, npwin.cpp and npmac.cpp that + * get linked with the plugin. You will however need to link with the "backward + * adapter" (badapter.cpp) in order to allow your plugin to run in pre-5.0 + * browsers. + * + *

    See nsplugin.h for an overview of how this interface fits with the + * overall plugin architecture. + */ +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsIWindowlessPluginInstancePeer_h___ +#define nsIWindowlessPluginInstancePeer_h___ + +#include "nsplugindefs.h" +#include "nsISupports.h" + +//////////////////////////////////////////////////////////////////////////////// +// Windowless Plugin Instance Peer Interface + +class nsIWindowlessPluginInstancePeer : public nsISupports { +public: + + // (Corresponds to NPN_InvalidateRect.) + NS_IMETHOD + InvalidateRect(nsPluginRect *invalidRect) = 0; + + // (Corresponds to NPN_InvalidateRegion.) + NS_IMETHOD + InvalidateRegion(nsPluginRegion invalidRegion) = 0; + + // (Corresponds to NPN_ForceRedraw.) + NS_IMETHOD + ForceRedraw(void) = 0; + +}; + +#define NS_IWINDOWLESSPLUGININSTANCEPEER_IID \ +{ /* 57b4e2f0-019b-11d2-815b-006008119d7a */ \ + 0x57b4e2f0, \ + 0x019b, \ + 0x11d2, \ + {0x81, 0x5b, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIWindowlessPluginInstancePeer_h___ */ diff --git a/mozilla/nsprpub/lib/ds/plvector.c b/mozilla/nsprpub/lib/ds/plvector.c new file mode 100644 index 00000000000..e37dff40ffb --- /dev/null +++ b/mozilla/nsprpub/lib/ds/plvector.c @@ -0,0 +1,318 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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. + */ + +#include "plvector.h" +#include "prmem.h" +#include + +#ifdef XP_WIN16 +#define SIZE_T_MAX 0xFF80 /* a little less than 64K, the max alloc size on win16. */ +#define MAX_ARR_ELEMS SIZE_T_MAX/sizeof(void*) +#endif + +PR_IMPLEMENT(PLVector*) +PL_NewVector(PRUint32 initialSize, PRInt32 initialGrowBy) +{ + PLVector* v = (PLVector*)PR_Malloc(sizeof(PLVector*)); + if (v == NULL) + return NULL; + PL_VectorInitialize(v, initialSize, initialGrowBy); + return v; +} + +PR_IMPLEMENT(void) +PL_VectorDestroy(PLVector* v) +{ + PL_VectorFinalize(v); + PR_Free(v); +} + +/* Initializes an existing vector */ +PR_IMPLEMENT(void) +PL_VectorInitialize(PLVector* v, PRUint32 initialSize, PRInt32 initialGrowBy) +{ + v->data = NULL; + v->size = v->maxSize = v->growBy = 0; + if (initialSize > 0 || initialGrowBy > 0) + PL_VectorSetSize(v, initialSize, initialGrowBy); +} + +/* Destroys the elements, but doesn't free the vector */ +PR_IMPLEMENT(void) +PL_VectorFinalize(PLVector* v) +{ + /* This implementation doesn't do anything to delete the elements + in the vector -- that's up to the caller. (Don't shoot me, + I just copied the code from libmsg.) */ + PR_Free(v->data); +} + +PR_IMPLEMENT(PRBool) +PL_VectorSetSize(PLVector* v, PRUint32 newSize, PRInt32 growBy) +{ + if (growBy != -1) + v->growBy = growBy; /* set new size */ + + if (newSize == 0) { + /* shrink to nothing */ + PR_Free(v->data); + v->data = NULL; + v->size = v->maxSize = 0; + } + else if (v->data == NULL) { + /* create one with exact size */ +#ifdef SIZE_T_MAX + PR_ASSERT(newSize <= SIZE_T_MAX/sizeof(void*)); /* no overflow */ +#endif + v->data = (void**)PR_Malloc(newSize * sizeof(void *)); + if (v->data == NULL) { + v->size = 0; + return PR_FALSE; + } + + memset(v->data, 0, newSize * sizeof(void *)); /* zero fill */ + + v->size = v->maxSize = newSize; + } + else if (newSize <= v->maxSize) { + /* it fits */ + if (newSize > v->size) { + /* initialize the new elements */ + + memset(&v->data[v->size], 0, (newSize-v->size) * sizeof(void *)); + } + v->size = newSize; + } + else { + /* otherwise, grow array */ + PRUint32 newMax; + void** newData; + PRInt32 growBy = v->growBy; + if (growBy == 0) { + /* heuristically determine growth when growBy == 0 + (this avoids heap fragmentation in many situations) */ + growBy = PR_MIN(1024, PR_MAX(4, v->size / 8)); + } +#ifdef MAX_ARR_ELEMS + if (v->size + growBy > MAX_ARR_ELEMS) + growBy = MAX_ARR_ELEMS - v->size; +#endif + if (newSize < v->maxSize + growBy) + newMax = v->maxSize + growBy; /* granularity */ + else + newMax = newSize; /* no slush */ + +#ifdef SIZE_T_MAX + if (newMax >= SIZE_T_MAX/sizeof(void*)) + return PR_FALSE; + PR_ASSERT(newMax <= SIZE_T_MAX/sizeof(void*)); /* no overflow */ +#endif + PR_ASSERT(newMax >= v->maxSize); /* no wrap around */ + newData = (void**)PR_Malloc(newMax * sizeof(void*)); + + if (newData != NULL) { + /* copy new data from old */ + memcpy(newData, v->data, v->size * sizeof(void*)); + + /* construct remaining elements */ + PR_ASSERT(newSize > v->size); + + memset(&newData[v->size], 0, (newSize-v->size) * sizeof(void*)); + + /* get rid of old stuff (note: no destructors called) */ + PR_Free(v->data); + v->data = newData; + v->size = newSize; + v->maxSize = newMax; + } + else { + return PR_FALSE; + } + } + return PR_TRUE; +} + +PR_IMPLEMENT(PRBool) +PL_VectorIsValidIndex(PLVector* v, PRUint32 index) +{ + return (index < v->size) ? PR_TRUE : PR_FALSE; +} + + +PR_IMPLEMENT(void) +PL_VectorCompact(PLVector* v) +{ + if (v->size != v->maxSize) { + /* shrink to desired size */ +#ifdef SIZE_T_MAX + PR_ASSERT(v->size <= SIZE_T_MAX/sizeof(void *)); /* no overflow */ +#endif + void ** newData = NULL; + if (v->size != 0) { + newData = (void **)PR_Malloc(v->size * sizeof(void *)); + /* copy new data from old */ + memcpy(newData, v->data, v->size * sizeof(void *)); + } + + /* get rid of old stuff (note: no destructors called) */ + PR_Free(v->data); + v->data = newData; + v->maxSize = v->size; + } +} + +#if 0 /* becomes Copy */ +PR_IMPLEMENT(void) +PL_VectorSplice(PLVector* v, PRUint32 startIndex, PLVector* newVector) +{ + PRUint32 i; + PR_ASSERT(newVector != NULL); + + if (PL_VectorGetSize(newVector) > 0) { + PL_VectorInsert(v, startIndex, PL_VectorGet(newVector, 0), + PL_VectorGetSize(newVector)); + for (i = 0; i < PL_VectorGetSize(newVector); i++) + PL_VectorSet(v, startIndex + i, PL_VectorGet(newVector, i)); + } +} +#endif + +PR_IMPLEMENT(void) +PL_VectorCopy(PLVector* dstVector, PRUint32 dstPosition, + PLVector* srcVector, PRUint32 srcPosition, PRUint32 length) +{ + PR_ASSERT(0); /* XXX not implemented yet */ +#if 0 + PL_VectorSetSize(dstVector, PR_MAX(PL_VectorGetSize(dstVector), + PL_VectorGetSize(srcVector)), + PL_VECTOR_GROW_DEFAULT); + + if (v->data) + PR_Free(v->data); + v->size = oldA->v->size; + v->maxSize = oldA->v->maxSize; + v->growBy = oldA->v->growBy; + v->data = (void**)PR_Malloc(v->size * sizeof(void *)); + if (v->data == NULL) { + v->size = 0; + } + else { + memcpy(v->data, oldA->v->data, v->size * sizeof(void *)); + } +#endif +} + +PR_IMPLEMENT(PLVector*) +PL_VectorClone(PLVector* v) +{ + PLVector* newVec = PL_NewVector(v->size, v->growBy); + PL_VectorCopy(newVec, 0, v, 0, v->size); + return newVec; +} + +/* Accessing elements */ + +PR_IMPLEMENT(void) +PL_VectorSet(PLVector* v, PRUint32 index, void* newElement) +{ + if (index >= v->size) { + if (!PL_VectorSetSize(v, index+1, PL_VECTOR_GROW_DEFAULT)) + return; + } + v->data[index] = newElement; +} + +/* Adds at the end */ +PR_IMPLEMENT(PRInt32) +PL_VectorAdd(PLVector* v, void* newElement) +{ + PRUint32 index = v->size; +#ifdef XP_WIN16 + if (index >= SIZE_T_MAX / 4L) { + return -1; + } +#endif + PL_VectorSet(v, index, newElement); + return (PRInt32)index; +} + +/* Inserts new element count times at index */ +PR_IMPLEMENT(void) +PL_VectorInsert(PLVector* v, PRUint32 index, void* newElement, PRUint32 count) +{ + PR_ASSERT(count > 0); /* zero or negative size not allowed */ + + if (index >= v->size) { + /* adding after the end of the array */ + if (!PL_VectorSetSize(v, index + count, PL_VECTOR_GROW_DEFAULT)) + return; /* grow so index is valid */ + } + else { + /* inserting in the middle of the array */ + PRUint32 nOldSize = v->size; + if (!PL_VectorSetSize(v, v->size + count, PL_VECTOR_GROW_DEFAULT)) + return; /* grow it to new size */ + /* shift old data up to fill gap */ + memmove(&v->data[index+count], &v->data[index], + (nOldSize-index) * sizeof(void *)); + + /* re-init slots we copied from */ + memset(&v->data[index], 0, count * sizeof(void *)); + } + + /* insert new value in the gap */ + PR_ASSERT(index + count <= v->size); + while (count--) + v->data[index++] = newElement; +} + +/* Removes count elements at index */ +PR_IMPLEMENT(void) +PL_VectorRemove(PLVector* v, PRUint32 index, PRUint32 count) +{ + PRUint32 moveCount; + PR_ASSERT(count >= 0); + PR_ASSERT(index + count <= v->size); + + /* just remove a range */ + moveCount = v->size - (index + count); + + if (moveCount) + memmove(&v->data[index], &v->data[index + count], + moveCount * sizeof(void *)); + v->size -= count; +} + +#ifdef DEBUG + +PR_IMPLEMENT(void) +PL_VectorAssertValid(PLVector* v) +{ + if (v->data == NULL) { + PR_ASSERT(v->size == 0); + PR_ASSERT(v->maxSize == 0); + } + else { + PR_ASSERT(v->size >= 0); + PR_ASSERT(v->maxSize >= 0); + PR_ASSERT(v->size <= v->maxSize); + } +} + +#endif + diff --git a/mozilla/nsprpub/lib/ds/plvector.h b/mozilla/nsprpub/lib/ds/plvector.h new file mode 100644 index 00000000000..e71a152fd6a --- /dev/null +++ b/mozilla/nsprpub/lib/ds/plvector.h @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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. + */ + +#ifndef plvector_h__ +#define plvector_h__ + +#include "prtypes.h" +#include "prlog.h" + +PR_BEGIN_EXTERN_C + +/* Vectors are extensible arrays */ + +typedef struct PLVector { + void** data; /* the actual array of data */ + PRUint32 size; /* # of elements (upperBound - 1) */ + PRUint32 maxSize; /* max allocated */ + PRInt32 growBy; /* grow amount */ +} PLVector; + +PR_EXTERN(PLVector*) +PL_NewVector(PRUint32 initialSize, PRInt32 initialGrowBy); + +PR_EXTERN(void) +PL_VectorDestroy(PLVector* v); + +/* Initializes an existing vector */ +PR_EXTERN(void) +PL_VectorInitialize(PLVector* v, PRUint32 initialSize, PRInt32 initialGrowBy); + +/* Destroys the elements, but doesn't free the vector */ +PR_EXTERN(void) +PL_VectorFinalize(PLVector* v); + +#define PL_VectorGetSize(v) ((v)->size) + +#define PL_VECTOR_GROW_DEFAULT (-1) + +PR_EXTERN(PRBool) +PL_VectorSetSize(PLVector* v, PRUint32 newSize, PRInt32 growBy); + +PR_EXTERN(PRBool) +PL_VectorIsValidIndex(PLVector* v, PRUint32 index); + +PR_EXTERN(void) +PL_VectorCompact(PLVector* v); + +PR_EXTERN(void) +PL_VectorCopy(PLVector* dstVector, PRUint32 dstPosition, + PLVector* srcVector, PRUint32 srcPosition, PRUint32 length); + +PR_EXTERN(PLVector*) +PL_VectorClone(PLVector* v); + +/* Accessing elements */ + +#define PL_VectorGetAddr(v, index) (PR_ASSERT((index) < (v)->size), &(v)->data[index]) + +#define PL_VectorGet(v, index) (*PL_VectorGetAddr(v, index)) + +PR_EXTERN(void) +PL_VectorSet(PLVector* v, PRUint32 index, void* newElement); + +/* Adds at the end */ +PR_EXTERN(PRInt32) +PL_VectorAdd(PLVector* v, void* newElement); + +/* Inserts new element count times at index */ +PR_EXTERN(void) +PL_VectorInsert(PLVector* v, PRUint32 index, void* newElement, PRUint32 count); + +/* Removes count elements at index */ +PR_EXTERN(void) +PL_VectorRemove(PLVector* v, PRUint32 index, PRUint32 count); + +#ifdef DEBUG + +PR_EXTERN(void) +PL_VectorAssertValid(PLVector* v); + +#endif + +PR_END_EXTERN_C + +#endif /* plvector_h__ */ diff --git a/mozilla/xpcom/src/nsIMalloc.h b/mozilla/xpcom/src/nsIMalloc.h new file mode 100644 index 00000000000..f936d72d8a4 --- /dev/null +++ b/mozilla/xpcom/src/nsIMalloc.h @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +#ifndef nsIMalloc_h___ +#define nsIMalloc_h___ + +#include "nsISupports.h" + +class nsIMalloc : public nsISupports { +public: + + /** + * Allocates a block of memory of a particular size. + * + * @param size - the size of the block to allocate + * @result the block of memory + */ + NS_IMETHOD_(void*) + Alloc(PRUint32 size) = 0; + + /** + * Reallocates a block of memory to a new size. + * + * @param ptr - the block of memory to reallocate + * @param size - the new size + * @result the rellocated block of memory + */ + NS_IMETHOD_(void*) + Realloc(void* ptr, PRUint32 size) = 0; + + /** + * Frees a block of memory. + * + * @param ptr - the block of memory to free + */ + NS_IMETHOD_(void) + Free(void* ptr) = 0; + + /** + * Returns the size of a block of memory. Returns -1 + * if the size is not available. + * + * @param ptr - the block of memory + * @result the size or -1 if not available + */ + NS_IMETHOD_(PRInt32) + GetSize(void* ptr) = 0; + + /** + * Returns whether the block of memory was allocated by this + * memory allocator. Returns PR_FALSE if this information is + * not available. + * + * @param ptr - the block of memory + * @result true if allocated by this nsIMalloc, false if not or + * if it can't be determined + */ + NS_IMETHOD_(PRBool) + DidAlloc(void* ptr) = 0; + + /** + * Attempts to shrink the heap. + */ + NS_IMETHOD_(void) + HeapMinimize(void) = 0; + +}; + +#define NS_IMALLOC_IID \ +{ /* c4744e60-1875-11d2-815f-006008119d7a */ \ + 0xc4744e60, \ + 0x1875, \ + 0x11d2, \ + {0x81, 0x5f, 0x00, 0x60, 0x08, 0x11, 0x9d, 0x7a} \ +} + +//////////////////////////////////////////////////////////////////////////////// + +#endif /* nsIMalloc_h___ */ diff --git a/mozilla/xpcom/src/nsMalloc.cpp b/mozilla/xpcom/src/nsMalloc.cpp new file mode 100644 index 00000000000..de5827fe7ff --- /dev/null +++ b/mozilla/xpcom/src/nsMalloc.cpp @@ -0,0 +1,117 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +// Implementation of nsIMalloc using NSPR +//////////////////////////////////////////////////////////////////////////////// + +#include "nsMalloc.h" + +static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID); +static NS_DEFINE_IID(kIMallocIID, NS_IMALLOC_IID); + +nsMalloc::nsMalloc(nsISupports* outer) +{ + NS_INIT_AGGREGATED(outer); +} + +nsMalloc::~nsMalloc(void) +{ +} + +NS_IMPL_AGGREGATED(nsMalloc); + +NS_METHOD +nsMalloc::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr) +{ + if (NULL == aInstancePtr) { + return NS_ERROR_NULL_POINTER; + } + if (aIID.Equals(kIMallocIID) || + aIID.Equals(kISupportsIID)) { + *aInstancePtr = (void*) this; + AddRef(); + return NS_OK; + } + return NS_NOINTERFACE; +} + +NS_METHOD +nsMalloc::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr) +{ + if (outer && !aIID.Equals(kISupportsIID)) + return NS_NOINTERFACE; // XXX right error? + nsMalloc* mm = new nsMalloc(outer); + nsresult result = mm->QueryInterface(aIID, aInstancePtr); + if (result != NS_OK) { + delete mm; + } + return result; +} + +//////////////////////////////////////////////////////////////////////////////// + +NS_METHOD_(void*) +nsMalloc::Alloc(PRUint32 size) +{ + return PR_Malloc(size); +} + +NS_METHOD_(void*) +nsMalloc::Realloc(void* ptr, PRUint32 size) +{ + return PR_Realloc(ptr, size); +} + +NS_METHOD_(void) +nsMalloc::Free(void* ptr) +{ + PR_Free(ptr); +} + +NS_METHOD_(PRInt32) +nsMalloc::GetSize(void* ptr) +{ + return -1; +} + +NS_METHOD_(PRBool) +nsMalloc::DidAlloc(void* ptr) +{ + return PR_TRUE; +} + +// For the definition of CallCacheFlushers() +#ifdef XP_MAC +# ifndef NSPR20 +# include "prmacos.h" +# else +# include "MacMemAllocator.h" +# endif +#endif + +NS_METHOD_(void) +nsMalloc::HeapMinimize(void) +{ +#ifdef XP_MAC + // something wonderful + CallCacheFlushers(0x7fffffff); +#endif +} + +//////////////////////////////////////////////////////////////////////////////// diff --git a/mozilla/xpcom/src/nsMalloc.h b/mozilla/xpcom/src/nsMalloc.h new file mode 100644 index 00000000000..2109ebc8369 --- /dev/null +++ b/mozilla/xpcom/src/nsMalloc.h @@ -0,0 +1,101 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * 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. + */ + +//////////////////////////////////////////////////////////////////////////////// +// Implementation of nsIMalloc using NSPR +//////////////////////////////////////////////////////////////////////////////// + +#ifndef nsMalloc_h__ +#define nsMalloc_h__ + +#include "nsIMalloc.h" +#include "prmem.h" +#include "nsAgg.h" + +class NS_COM nsMalloc : nsIMalloc { +public: + + /** + * Allocates a block of memory of a particular size. + * + * @param size - the size of the block to allocate + * @result the block of memory + */ + NS_IMETHOD_(void*) + Alloc(PRUint32 size); + + /** + * Reallocates a block of memory to a new size. + * + * @param ptr - the block of memory to reallocate + * @param size - the new size + * @result the rellocated block of memory + */ + NS_IMETHOD_(void*) + Realloc(void* ptr, PRUint32 size); + + /** + * Frees a block of memory. + * + * @param ptr - the block of memory to free + */ + NS_IMETHOD_(void) + Free(void* ptr); + + /** + * Returns the size of a block of memory. Returns -1 + * if the size is not available. + * + * @param ptr - the block of memory + * @result the size or -1 if not available + */ + NS_IMETHOD_(PRInt32) + GetSize(void* ptr); + + /** + * Returns whether the block of memory was allocated by this + * memory allocator. Returns PR_FALSE if this information is + * not available. + * + * @param ptr - the block of memory + * @result true if allocated by this nsIMalloc, false if not or + * if it can't be determined + */ + NS_IMETHOD_(PRBool) + DidAlloc(void* ptr); + + /** + * Attempts to shrink the heap. + */ + NS_IMETHOD_(void) + HeapMinimize(void); + + //////////////////////////////////////////////////////////////////////////// + + nsMalloc(nsISupports* outer); + virtual ~nsMalloc(void); + + NS_DECL_AGGREGATED + + static NS_METHOD + Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr); + +}; + +//////////////////////////////////////////////////////////////////////////////// +#endif // nsMalloc_h__ diff --git a/mozilla/xpcom/src/nsVector.h b/mozilla/xpcom/src/nsVector.h new file mode 100644 index 00000000000..d993691e36e --- /dev/null +++ b/mozilla/xpcom/src/nsVector.h @@ -0,0 +1,74 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * 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. + */ + +#ifndef nsVector_h__ +#define nsVector_h__ + +#include "plvector.h" +#include "nsCom.h" + +class nsVector : public PLVector { +public: +// Construction + nsVector(PRUint32 initialSize = 0, PRInt32 initialGrowBy = 0) { + PL_VectorInitialize(this, initialSize, initialGrowBy); + } + ~nsVector(void) { PL_VectorFinalize(this); } + +// Attributes + PRUint32 GetSize(void) const { return PL_VectorGetSize(this); } + PRUint32 GetUpperBound(void) const { return GetSize() - 1; } + PRBool SetSize(PRUint32 nNewSize, PRInt32 nGrowBy = PL_VECTOR_GROW_DEFAULT) { + return PL_VectorSetSize(this, nNewSize, nGrowBy); + } + PRBool IsValidIndex(PRUint32 index) { return PL_VectorIsValidIndex(this, index); } + +// Operations + // Clean up + void Compact(void) { PL_VectorCompact(this); } + void RemoveAll(void) { SetSize(0); } + void Copy(nsVector* src, PRUint32 len, PRUint32 dstPos = 0, PRUint32 srcPos = 0) { + PL_VectorCopy(this, dstPos, src, srcPos, len); + } + + // Accessing elements + void* Get(PRUint32 index) const { return PL_VectorGet(this, index); } + void Set(PRUint32 index, void* newElement) { PL_VectorSet(this, index, newElement); } + void*& ElementAt(PRUint32 index) { return *PL_VectorGetAddr(this, index); } + + // Potentially growing the array + PRInt32 Add(void* newElement) { return PL_VectorAdd(this, newElement); } + + // overloaded operator helpers + void* operator[](PRUint32 index) const { return Get(index); } + void*& operator[](PRUint32 index) { return ElementAt(index); } + + // Operations that move elements around + void Insert(PRUint32 index, void* newElement, PRInt32 count = 1) { + PL_VectorInsert(this, index, newElement, count); + } + void Remove(PRUint32 index, PRInt32 count = 1) { + PL_VectorRemove(this, index, count); + } + +#ifdef DEBUG + void AssertValid(void) const { PL_VectorAssertValid((PLVector*)this); } +#endif +}; + +#endif