From d6593bc7ef812eddfe646100e233034d6f11a523 Mon Sep 17 00:00:00 2001 From: "jst@mozilla.org" Date: Tue, 9 Oct 2007 18:24:28 -0700 Subject: [PATCH] Fixing bug 393928. Lazily initialize liveconnect, and only initialize it when we can't find a Java plugin that supports NPRuntime. When a Java plugin that supports NPRuntime is found, use NPRuntime to expose liveconnect functionality (i.e. window.java and window.Packages). r=cbiesinger@gmx.at, sr=bzbarsky@mit.edu, a=jonas@sicking.cc --- dom/src/base/nsDOMClassInfo.cpp | 70 +++++ dom/src/base/nsDOMClassInfo.h | 10 + dom/src/base/nsGlobalWindow.cpp | 254 ++++++++++++++++++ dom/src/base/nsGlobalWindow.h | 15 ++ dom/src/base/nsJSEnvironment.cpp | 54 ---- dom/src/base/nsJSEnvironment.h | 1 - modules/plugin/base/public/npruntime.h | 14 +- modules/plugin/base/public/npupp.h | 13 +- .../base/public/nsIPluginInstanceInternal.h | 6 +- modules/plugin/base/public/nsPIPluginHost.idl | 12 +- modules/plugin/base/src/ns4xPlugin.cpp | 21 ++ modules/plugin/base/src/ns4xPlugin.h | 4 + .../plugin/base/src/ns4xPluginInstance.cpp | 60 +++++ modules/plugin/base/src/ns4xPluginInstance.h | 2 + modules/plugin/base/src/nsJSNPRuntime.cpp | 136 ++++++++-- modules/plugin/base/src/nsJSNPRuntime.h | 2 + modules/plugin/base/src/nsPluginHostImpl.cpp | 225 ++++++++++------ modules/plugin/base/src/nsPluginHostImpl.h | 1 + 18 files changed, 725 insertions(+), 175 deletions(-) diff --git a/dom/src/base/nsDOMClassInfo.cpp b/dom/src/base/nsDOMClassInfo.cpp index a4feede2141..9dff7007856 100644 --- a/dom/src/base/nsDOMClassInfo.cpp +++ b/dom/src/base/nsDOMClassInfo.cpp @@ -1326,6 +1326,16 @@ jsval nsDOMClassInfo::sOnpaste_id = JSVAL_VOID; jsval nsDOMClassInfo::sOnbeforecopy_id = JSVAL_VOID; jsval nsDOMClassInfo::sOnbeforecut_id = JSVAL_VOID; jsval nsDOMClassInfo::sOnbeforepaste_id = JSVAL_VOID; +#ifdef OJI +jsval nsDOMClassInfo::sJava_id = JSVAL_VOID; +jsval nsDOMClassInfo::sPackages_id = JSVAL_VOID; +jsval nsDOMClassInfo::sNetscape_id = JSVAL_VOID; +jsval nsDOMClassInfo::sSun_id = JSVAL_VOID; +jsval nsDOMClassInfo::sJavaObject_id = JSVAL_VOID; +jsval nsDOMClassInfo::sJavaClass_id = JSVAL_VOID; +jsval nsDOMClassInfo::sJavaArray_id = JSVAL_VOID; +jsval nsDOMClassInfo::sJavaMember_id = JSVAL_VOID; +#endif const JSClass *nsDOMClassInfo::sObjectClass = nsnull; const JSClass *nsDOMClassInfo::sXPCNativeWrapperClass = nsnull; @@ -1511,6 +1521,16 @@ nsDOMClassInfo::DefineStaticJSVals(JSContext *cx) SET_JSVAL_TO_STRING(sOnbeforecopy_id, cx, "oncopy"); SET_JSVAL_TO_STRING(sOnbeforecut_id, cx, "oncut"); SET_JSVAL_TO_STRING(sOnbeforepaste_id, cx, "onpaste"); +#ifdef OJI + SET_JSVAL_TO_STRING(sJava_id, cx, "java"); + SET_JSVAL_TO_STRING(sPackages_id, cx, "Packages"); + SET_JSVAL_TO_STRING(sNetscape_id, cx, "netscape"); + SET_JSVAL_TO_STRING(sSun_id, cx, "sun"); + SET_JSVAL_TO_STRING(sJavaObject_id, cx, "JavaObject"); + SET_JSVAL_TO_STRING(sJavaClass_id, cx, "JavaClass"); + SET_JSVAL_TO_STRING(sJavaArray_id, cx, "JavaArray"); + SET_JSVAL_TO_STRING(sJavaMember_id, cx, "JavaMember"); +#endif return NS_OK; } @@ -4050,6 +4070,16 @@ nsDOMClassInfo::ShutDown() sOnbeforecopy_id = JSVAL_VOID; sOnbeforecut_id = JSVAL_VOID; sOnbeforepaste_id = JSVAL_VOID; +#ifdef OJI + sJava_id = JSVAL_VOID; + sPackages_id = JSVAL_VOID; + sNetscape_id = JSVAL_VOID; + sSun_id = JSVAL_VOID; + sJavaObject_id = JSVAL_VOID; + sJavaClass_id = JSVAL_VOID; + sJavaArray_id = JSVAL_VOID; + sJavaMember_id = JSVAL_VOID; +#endif NS_IF_RELEASE(sXPConnect); NS_IF_RELEASE(sSecMan); @@ -6032,6 +6062,46 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, return NS_OK; } + +#ifdef OJI + if (id == sJava_id || id == sPackages_id || id == sNetscape_id || + id == sSun_id || id == sJavaObject_id || id == sJavaClass_id || + id == sJavaArray_id || id == sJavaMember_id + ) { + static PRBool isResolvingJavaProperties; + + if (!isResolvingJavaProperties) { + isResolvingJavaProperties = PR_TRUE; + + PRBool oldVal = sDoSecurityCheckInAddProperty; + sDoSecurityCheckInAddProperty = PR_FALSE; + + // Tell the window to initialize the Java properties. The + // window needs to do this as we need to do this only once, + // and detecting that reliably from here is hard. + + win->InitJavaProperties(); + + sDoSecurityCheckInAddProperty = oldVal; + + PRBool hasProp; + PRBool ok = ::JS_HasProperty(cx, obj, ::JS_GetStringBytes(str), + &hasProp); + + isResolvingJavaProperties = PR_FALSE; + + if (!ok) { + return NS_ERROR_FAILURE; + } + + if (hasProp) { + *objp = obj; + + return NS_OK; + } + } + } +#endif } return nsEventReceiverSH::NewResolve(wrapper, cx, obj, id, flags, objp, diff --git a/dom/src/base/nsDOMClassInfo.h b/dom/src/base/nsDOMClassInfo.h index 34bbc96e51e..1131272443f 100644 --- a/dom/src/base/nsDOMClassInfo.h +++ b/dom/src/base/nsDOMClassInfo.h @@ -318,6 +318,16 @@ protected: static jsval sOnbeforecopy_id; static jsval sOnbeforecut_id; static jsval sOnbeforepaste_id; +#ifdef OJI + static jsval sJava_id; + static jsval sPackages_id; + static jsval sNetscape_id; + static jsval sSun_id; + static jsval sJavaObject_id; + static jsval sJavaClass_id; + static jsval sJavaArray_id; + static jsval sJavaMember_id; +#endif static const JSClass *sObjectClass; static const JSClass *sXPCNativeWrapperClass; diff --git a/dom/src/base/nsGlobalWindow.cpp b/dom/src/base/nsGlobalWindow.cpp index 6ea5ffa9183..3d5bd00e997 100644 --- a/dom/src/base/nsGlobalWindow.cpp +++ b/dom/src/base/nsGlobalWindow.cpp @@ -72,8 +72,10 @@ #include "nsICachingChannel.h" #include "nsPluginArray.h" #include "nsIPluginHost.h" +#include "nsPIPluginHost.h" #ifdef OJI #include "nsIJVMManager.h" +#include "nsILiveConnectManager.h" #endif #include "nsContentCID.h" #include "nsLayoutStatics.h" @@ -378,6 +380,153 @@ StripNullChars(const nsAString& aInStr, } } +#ifdef OJI +class nsDummyJavaPluginOwner : public nsIPluginInstanceOwner +{ +public: + nsDummyJavaPluginOwner(nsIDocument *aDocument) + : mDocument(aDocument) + { + } + + void Destroy(); + + NS_DECL_CYCLE_COLLECTING_ISUPPORTS + NS_DECL_NSIPLUGININSTANCEOWNER + + // XXXjst: What's up with nsIPluginInstanceOwner and these functions? + NS_IMETHOD GetURL(const char *aURL, const char *aTarget, void *aPostData, + PRUint32 aPostDataLen, void *aHeadersData, + PRUint32 aHeadersDataLen, PRBool aIsFile = PR_FALSE); + NS_IMETHOD ShowStatus(const PRUnichar *aStatusMsg); + + NS_DECL_CYCLE_COLLECTION_CLASS(nsDummyJavaPluginOwner) + +private: + nsCOMPtr mInstance; + nsCOMPtr mDocument; +}; + +NS_IMPL_CYCLE_COLLECTION_2(nsDummyJavaPluginOwner, mDocument, mInstance) + +// QueryInterface implementation for nsDummyJavaPluginOwner +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsDummyJavaPluginOwner) + NS_INTERFACE_MAP_ENTRY(nsISupports) + NS_INTERFACE_MAP_ENTRY(nsIPluginInstanceOwner) +NS_INTERFACE_MAP_END + +NS_IMPL_CYCLE_COLLECTING_ADDREF(nsDummyJavaPluginOwner) +NS_IMPL_CYCLE_COLLECTING_RELEASE(nsDummyJavaPluginOwner) + + +void +nsDummyJavaPluginOwner::Destroy() +{ + // If we have a plugin instance, stop it and destroy it now. + if (mInstance) { + mInstance->Stop(); + mInstance->Destroy(); + + mInstance = nsnull; + } + + mDocument = nsnull; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::SetInstance(nsIPluginInstance *aInstance) +{ + mInstance = aInstance; + + return NS_OK; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::GetInstance(nsIPluginInstance *&aInstance) +{ + NS_IF_ADDREF(aInstance = mInstance); + + return NS_OK; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::GetWindow(nsPluginWindow *&aWindow) +{ + aWindow = nsnull; + + return NS_OK; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::GetMode(nsPluginMode *aMode) +{ + // This is wrong, but there's no better alternative. + *aMode = nsPluginMode_Embedded; + + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::CreateWidget(void) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::GetURL(const char *aURL, const char *aTarget, + void *aPostData, PRUint32 aPostDataLen, + void *aHeadersData, PRUint32 aHeadersDataLen, + PRBool isFile) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::ShowStatus(const char *aStatusMsg) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::ShowStatus(const PRUnichar *aStatusMsg) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::GetDocument(nsIDocument **aDocument) +{ + NS_IF_ADDREF(*aDocument = mDocument); + + return NS_OK; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::InvalidateRect(nsPluginRect *invalidRect) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::InvalidateRegion(nsPluginRegion invalidRegion) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::ForceRedraw() +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +nsDummyJavaPluginOwner::GetValue(nsPluginInstancePeerVariable variable, + void *value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +#endif + /** * An indirect observer object that means we don't have to implement nsIObserver * on nsGlobalWindow, where any script could see it. @@ -436,6 +585,7 @@ nsTimeout::~nsTimeout() nsGlobalWindow::nsGlobalWindow(nsGlobalWindow *aOuterWindow) : nsPIDOMWindow(aOuterWindow), mIsFrozen(PR_FALSE), + mDidInitJavaProperties(PR_FALSE), mFullScreen(PR_FALSE), mIsClosed(PR_FALSE), mInClose(PR_FALSE), @@ -709,6 +859,19 @@ nsGlobalWindow::FreeInnerObjects(PRBool aClearScope) } } +#ifdef OJI + if (mDummyJavaPluginOwner) { + // Tear down the dummy java plugin. + + // XXXjst: On a general note, should windows with java stuff in + // them ever even make it into the fast-back cache? + + mDummyJavaPluginOwner->Destroy(); + + mDummyJavaPluginOwner = nsnull; + } +#endif + #ifdef DEBUG nsCycleCollector_DEBUG_shouldBeFreed(static_cast(this)); #endif @@ -789,6 +952,12 @@ NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(nsGlobalWindow) // Traverse stuff from nsPIDOMWindow NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mChromeEventHandler) NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDocument) + +#ifdef OJI + // Traverse mDummyJavaPluginOwner + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_NSCOMPTR(mDummyJavaPluginOwner) +#endif + NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) @@ -825,6 +994,15 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(nsGlobalWindow) // Unlink stuff from nsPIDOMWindow NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mChromeEventHandler) NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDocument) + +#ifdef OJI + // Unlink mDummyJavaPluginOwner + if (tmp->mDummyJavaPluginOwner) { + tmp->mDummyJavaPluginOwner->Destroy(); + NS_IMPL_CYCLE_COLLECTION_UNLINK_NSCOMPTR(mDummyJavaPluginOwner) + } +#endif + NS_IMPL_CYCLE_COLLECTION_UNLINK_END @@ -5073,6 +5251,82 @@ nsGlobalWindow::IsInModalState() (top.get()))->mModalStateDepth != 0; } +#ifdef OJI +void +nsGlobalWindow::InitJavaProperties() +{ + nsIScriptContext *scx = GetContextInternal(); + + if (mDidInitJavaProperties || IsOuterWindow() || !scx || !mJSObject) { + return; + } + + // Set mDidInitJavaProperties to true here even if initialization + // can fail. If it fails, we won't try again... + mDidInitJavaProperties = PR_TRUE; + + // Check whether the plugin supports NPRuntime, if so, init through + // it, else use liveconnect. + + nsCOMPtr host(do_GetService("@mozilla.org/plugin/host;1")); + if (!host) { + return; + } + + mDummyJavaPluginOwner = new nsDummyJavaPluginOwner(mDoc); + if (!mDummyJavaPluginOwner) { + return; + } + + host->InstantiateDummyJavaPlugin(mDummyJavaPluginOwner); + + nsCOMPtr dummyPlugin; + mDummyJavaPluginOwner->GetInstance(*getter_AddRefs(dummyPlugin)); + + if (dummyPlugin) { + // A dummy plugin was instantiated. This means we have a Java + // plugin that supports NPRuntime. For such a plugin, the plugin + // instantiation code defines the Java properties for us, so we're + // done here. + + return; + } + + // No NPRuntime enabled Java plugin found, null out the owner we + // would have used in that case as it's no longer needed. + mDummyJavaPluginOwner = nsnull; + + JSContext *cx = (JSContext *)scx->GetNativeContext(); + + nsCOMPtr manager = + do_GetService(nsIJVMManager::GetCID()); + + if (!manager) { + return; + } + + PRBool started = PR_FALSE; + manager->StartupLiveConnect(::JS_GetRuntime(cx), started); + + nsCOMPtr jvmManager(do_QueryInterface(manager)); + + if (!jvmManager) { + return; + } + + PRBool javaEnabled = PR_FALSE; + if (NS_FAILED(jvmManager->GetJavaEnabled(&javaEnabled)) || !javaEnabled) { + return; + } + + { + JSAutoRequest ar(cx); + + manager->InitLiveConnectClasses(cx, mJSObject); + } +} +#endif + NS_IMETHODIMP nsGlobalWindow::GetFrameElement(nsIDOMElement** aFrameElement) { diff --git a/dom/src/base/nsGlobalWindow.h b/dom/src/base/nsGlobalWindow.h index 7a11b0166e7..a6f73e9f042 100644 --- a/dom/src/base/nsGlobalWindow.h +++ b/dom/src/base/nsGlobalWindow.h @@ -118,6 +118,9 @@ class nsIDocShellLoadInfo; class WindowStateHolder; class nsGlobalWindowObserver; class nsGlobalWindow; +#ifdef OJI +class nsDummyJavaPluginOwner; +#endif class nsDOMOfflineResourceList; class nsDOMOfflineLoadStatusList; @@ -419,6 +422,10 @@ public: NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(nsGlobalWindow, nsIScriptGlobalObject) +#ifdef OJI + void InitJavaProperties(); +#endif + protected: // Object Management virtual ~nsGlobalWindow(); @@ -626,6 +633,10 @@ protected: // we're in the middle of doing just that. PRPackedBool mIsFrozen : 1; + // True if the Java properties have been initialized on this + // window. Only used on inner windows. + PRPackedBool mDidInitJavaProperties : 1; + // These members are only used on outer window objects. Make sure // you never set any of these on an inner object! PRPackedBool mFullScreen : 1; @@ -694,6 +705,10 @@ protected: PRUint32 mTimeoutFiringDepth; nsCOMPtr mSessionStorage; +#ifdef OJI + nsRefPtr mDummyJavaPluginOwner; +#endif + // These member variables are used on both inner and the outer windows. nsCOMPtr mDocumentPrincipal; nsCOMPtr mDoc; // For fast access to principals diff --git a/dom/src/base/nsJSEnvironment.cpp b/dom/src/base/nsJSEnvironment.cpp index db881ffc935..f920b4cf0cf 100644 --- a/dom/src/base/nsJSEnvironment.cpp +++ b/dom/src/base/nsJSEnvironment.cpp @@ -120,11 +120,6 @@ #include "prlog.h" #include "prthread.h" -#ifdef OJI -#include "nsIJVMManager.h" -#include "nsILiveConnectManager.h" -#endif - const size_t gStackSize = 8192; #ifdef PR_LOGGING @@ -2328,36 +2323,6 @@ nsJSContext::InitializeExternalClasses() return gNameSpaceManager->InitForContext(this); } -nsresult -nsJSContext::InitializeLiveConnectClasses(JSObject *aGlobalObj) -{ - nsresult rv = NS_OK; - -#ifdef OJI - nsCOMPtr jvmManager = - do_GetService(nsIJVMManager::GetCID(), &rv); - - if (NS_SUCCEEDED(rv) && jvmManager) { - PRBool javaEnabled = PR_FALSE; - - rv = jvmManager->GetJavaEnabled(&javaEnabled); - - if (NS_SUCCEEDED(rv) && javaEnabled) { - nsCOMPtr liveConnectManager = - do_QueryInterface(jvmManager); - - if (liveConnectManager) { - JSAutoRequest ar(mContext); - rv = liveConnectManager->InitLiveConnectClasses(mContext, aGlobalObj); - } - } - } -#endif /* OJI */ - - // return all is well until things are stable. - return NS_OK; -} - nsresult nsJSContext::SetProperty(void *aTarget, const char *aPropName, nsISupports *aArgs) { @@ -3022,9 +2987,6 @@ nsJSContext::InitClasses(void *aGlobalObj) rv = InitializeExternalClasses(); NS_ENSURE_SUCCESS(rv, rv); - rv = InitializeLiveConnectClasses(globalObj); - NS_ENSURE_SUCCESS(rv, rv); - JSAutoRequest ar(mContext); // Initialize the options object and set default options in mContext @@ -3520,22 +3482,6 @@ nsJSRuntime::Init() xpc->SetCollectGarbageOnMainThreadOnly(PR_TRUE); xpc->SetDeferReleasesUntilAfterGarbageCollection(PR_TRUE); -#ifdef OJI - // Initialize LiveConnect. XXXbe use contractid rather than GetCID - // NOTE: LiveConnect is optional so initialisation will still succeed - // even if the service is not present. - nsCOMPtr manager = - do_GetService(nsIJVMManager::GetCID()); - - // Should the JVM manager perhaps define methods for starting up - // LiveConnect? - if (manager) { - PRBool started = PR_FALSE; - rv = manager->StartupLiveConnect(sRuntime, started); - // XXX Did somebody mean to check |rv| ? - } -#endif /* OJI */ - nsContentUtils::RegisterPrefCallback("dom.max_script_run_time", MaxScriptRunTimePrefChangedCallback, nsnull); diff --git a/dom/src/base/nsJSEnvironment.h b/dom/src/base/nsJSEnvironment.h index 01d0187f8da..c1cefb86a41 100644 --- a/dom/src/base/nsJSEnvironment.h +++ b/dom/src/base/nsJSEnvironment.h @@ -172,7 +172,6 @@ public: protected: nsresult InitializeExternalClasses(); - nsresult InitializeLiveConnectClasses(JSObject *aGlobalObj); // aHolder should be holding our global object nsresult FindXPCNativeWrapperClass(nsIXPConnectJSObjectHolder *aHolder); diff --git a/modules/plugin/base/public/npruntime.h b/modules/plugin/base/public/npruntime.h index 29eae21db75..3e61396e849 100644 --- a/modules/plugin/base/public/npruntime.h +++ b/modules/plugin/base/public/npruntime.h @@ -294,6 +294,10 @@ typedef bool (*NPRemovePropertyFunctionPtr)(NPObject *npobj, NPIdentifier name); typedef bool (*NPEnumerationFunctionPtr)(NPObject *npobj, NPIdentifier **value, uint32_t *count); +typedef bool (*NPConstructFunctionPtr)(NPObject *npobj, + const NPVariant *args, + uint32_t argCount, + NPVariant *result); /* NPObjects returned by create, retain, invoke, and getProperty pass @@ -332,14 +336,20 @@ struct NPClass NPSetPropertyFunctionPtr setProperty; NPRemovePropertyFunctionPtr removeProperty; NPEnumerationFunctionPtr enumerate; + NPConstructFunctionPtr construct; }; -#define NP_CLASS_STRUCT_VERSION 2 +#define NP_CLASS_STRUCT_VERSION 3 + #define NP_CLASS_STRUCT_VERSION_ENUM 2 +#define NP_CLASS_STRUCT_VERSION_CTOR 3 #define NP_CLASS_STRUCT_VERSION_HAS_ENUM(npclass) \ ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_ENUM) +#define NP_CLASS_STRUCT_VERSION_HAS_CTOR(npclass) \ + ((npclass)->structVersion >= NP_CLASS_STRUCT_VERSION_CTOR) + struct NPObject { NPClass *_class; uint32_t referenceCount; @@ -395,6 +405,8 @@ bool NPN_HasProperty(NPP npp, NPObject *npobj, NPIdentifier propertyName); bool NPN_HasMethod(NPP npp, NPObject *npobj, NPIdentifier methodName); bool NPN_Enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count); +bool NPN_Construct(NPP npp, NPObject *npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result); /* NPN_SetException may be called to trigger a script exception upon diff --git a/modules/plugin/base/public/npupp.h b/modules/plugin/base/public/npupp.h index cc99c1565a2..f3e229fca92 100644 --- a/modules/plugin/base/public/npupp.h +++ b/modules/plugin/base/public/npupp.h @@ -37,7 +37,7 @@ /* - * npupp.h $Revision: 3.25 $ + * npupp.h $Revision: 3.26 $ * function call mecahnics needed by platform specific glue code. */ @@ -484,13 +484,21 @@ typedef bool (* NP_LOADDS NPN_EnumerateUPP)(NPP npp, NPObject *obj, NPIdentifier #define CallNPN_EnumerateProc(FUNC, ARG1, ARG2, ARG3, ARG4) \ (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4)) -/* NPN_Enumerate */ +/* NPN_PluginThreadAsyncCall */ typedef void (* NP_LOADDS NPN_PluginThreadAsyncCallUPP)(NPP instance, void (*func)(void *), void *userData); #define NewNPN_PluginThreadAsyncCallProc(FUNC) \ ((NPN_PluginThreadAsyncCallUPP) (FUNC)) #define CallNPN_PluginThreadAsyncCallProc(FUNC, ARG1, ARG2, ARG3) \ (*(FUNC))((ARG1), (ARG2), (ARG3)) +/* NPN_Construct */ +typedef bool (* NP_LOADDS NPN_ConstructUPP)(NPP npp, NPObject* obj, const NPVariant *args, uint32_t argCount, NPVariant *result); +#define NewNPN_ConstructProc(FUNC) \ + ((NPN_ConstructUPP) (FUNC)) +#define CallNPN_ConstructProc(FUNC, ARG1, ARG2, ARG3, ARG4, ARG5) \ + (*(FUNC))((ARG1), (ARG2), (ARG3), (ARG4), (ARG5)) + + /****************************************************************************************** * The actual plugin function table definitions @@ -562,6 +570,7 @@ typedef struct _NPNetscapeFuncs { NPN_PopPopupsEnabledStateUPP poppopupsenabledstate; NPN_EnumerateUPP enumerate; NPN_PluginThreadAsyncCallUPP pluginthreadasynccall; + NPN_ConstructUPP construct; } NPNetscapeFuncs; diff --git a/modules/plugin/base/public/nsIPluginInstanceInternal.h b/modules/plugin/base/public/nsIPluginInstanceInternal.h index d55c8c346d6..b9e2e8a1897 100644 --- a/modules/plugin/base/public/nsIPluginInstanceInternal.h +++ b/modules/plugin/base/public/nsIPluginInstanceInternal.h @@ -45,8 +45,8 @@ struct JSContext; #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class" #define NS_IPLUGININSTANCEINTERNAL_IID \ - { 0x301f13ed, 0x50f2, 0x4ed2, \ - { 0x83, 0x0d, 0x78, 0x36, 0x1d, 0x01, 0x76, 0xaf }} + {0x1a9c2ae8, 0xab75, 0x4296, \ + { 0xaf, 0xcb, 0x39, 0x54, 0x39, 0x96, 0x06, 0xa9 }} class NS_NO_VTABLE nsIPluginInstanceInternal : public nsISupports { @@ -61,6 +61,8 @@ public: virtual void PopPopupsEnabledState() = 0; virtual PRUint16 GetPluginAPIVersion() = 0; + + virtual void DefineJavaProperties() = 0; }; NS_DEFINE_STATIC_IID_ACCESSOR(nsIPluginInstanceInternal, diff --git a/modules/plugin/base/public/nsPIPluginHost.idl b/modules/plugin/base/public/nsPIPluginHost.idl index 9f03261dd64..cf0ea68091a 100644 --- a/modules/plugin/base/public/nsPIPluginHost.idl +++ b/modules/plugin/base/public/nsPIPluginHost.idl @@ -42,9 +42,11 @@ #include "nsPluginNativeWindow.h" %} +interface nsIPluginInstanceOwner; + [ptr] native nsPluginNativeWindowPtr(nsPluginNativeWindow); -[uuid(8e3d71e6-2319-11d5-9cf8-0060b0fbd8ac)] +[uuid(42338435-a38f-4901-97b9-d7cba643d28d)] interface nsPIPluginHost : nsISupports { /** @@ -93,4 +95,12 @@ interface nsPIPluginHost : nsISupports * Deletes plugin native window object created by NewPluginNativeWindow */ void deletePluginNativeWindow(in nsPluginNativeWindowPtr aPluginNativeWindow); + /** + * Instantiate a "dummy" java plugin if a java plugin that supports + * NPRuntime is installed. This plugin is used for exposing + * window.java and window.Packages. If the java plugin supports + * NPRuntime and instantiation was successful, aOwners instance will + * be non-null, if not, it will be null. + */ + [noscript] void instantiateDummyJavaPlugin(in nsIPluginInstanceOwner aOwner); }; diff --git a/modules/plugin/base/src/ns4xPlugin.cpp b/modules/plugin/base/src/ns4xPlugin.cpp index cc6703224fa..5db8ffc6af0 100644 --- a/modules/plugin/base/src/ns4xPlugin.cpp +++ b/modules/plugin/base/src/ns4xPlugin.cpp @@ -374,6 +374,9 @@ ns4xPlugin::CheckClassInitialized(void) CALLBACKS.enumerate = NewNPN_EnumerateProc(FP2TV(_enumerate)); + CALLBACKS.construct = + NewNPN_ConstructProc(FP2TV(_construct)); + CALLBACKS.releasevariantvalue = NewNPN_ReleaseVariantValueProc(FP2TV(_releasevariantvalue)); @@ -1734,6 +1737,22 @@ _enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, return npobj->_class->enumerate(npobj, identifier, count); } +bool NP_CALLBACK +_construct(NPP npp, NPObject* npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result) +{ + if (!npp || !npobj || !npobj->_class || + !NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) || + !npobj->_class->construct) { + return false; + } + + NPPExceptionAutoHolder nppExceptionHolder; + NPPAutoPusher nppPusher(npp); + + return npobj->_class->construct(npobj, args, argCount, result); +} + void NP_CALLBACK _releasevariantvalue(NPVariant* variant) { @@ -2344,6 +2363,8 @@ OnShutdown() if (sPluginThreadAsyncCallLock) { nsAutoLock::DestroyLock(sPluginThreadAsyncCallLock); + + sPluginThreadAsyncCallLock = nsnull; } } diff --git a/modules/plugin/base/src/ns4xPlugin.h b/modules/plugin/base/src/ns4xPlugin.h index 5f68f59d1dd..1f855b011db 100644 --- a/modules/plugin/base/src/ns4xPlugin.h +++ b/modules/plugin/base/src/ns4xPlugin.h @@ -239,6 +239,10 @@ bool NP_CALLBACK _enumerate(NPP npp, NPObject *npobj, NPIdentifier **identifier, uint32_t *count); +bool NP_CALLBACK +_construct(NPP npp, NPObject* npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result); + void NP_CALLBACK _releasevariantvalue(NPVariant *variant); diff --git a/modules/plugin/base/src/ns4xPluginInstance.cpp b/modules/plugin/base/src/ns4xPluginInstance.cpp index f7022a3adb9..d3fb8167308 100644 --- a/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -1425,6 +1425,66 @@ ns4xPluginInstance::GetJSObject(JSContext *cx) return obj; } +void +ns4xPluginInstance::DefineJavaProperties() +{ + // Enable this code only if OJI is defined, even though this is the + // code that does what OJI does in the case where a Java plugin with + // NPRuntime support is installed. We do this because OJI being + // defined also states whether or not window.java etc is defined, + // which this code is all about. + +#ifdef OJI + NPObject *plugin_obj = nsnull; + + // The dummy Java plugin's scriptable object is what we want to + // expose as window.Packages. And Window.Packages.java will be + // exposed as window.java. + + // Get the scriptable plugin object. + nsresult rv = GetValueInternal(NPPVpluginScriptableNPObject, &plugin_obj); + + if (NS_FAILED(rv) || !plugin_obj) { + return; + } + + // Get the NPObject wrapper for window. + NPObject *window_obj = _getwindowobject(&fNPP); + + if (!window_obj) { + _releaseobject(plugin_obj); + + return; + } + + NPIdentifier java_id = _getstringidentifier("java"); + NPIdentifier packages_id = _getstringidentifier("Packages"); + + NPObject *java_obj = nsnull; + NPVariant v; + OBJECT_TO_NPVARIANT(plugin_obj, v); + + // Define the properties. + + bool ok = _setproperty(&fNPP, window_obj, packages_id, &v); + if (ok) { + ok = _getproperty(&fNPP, plugin_obj, java_id, &v); + + if (ok && NPVARIANT_IS_OBJECT(v)) { + // Set java_obj so that we properly release it at the end of + // this function. + java_obj = NPVARIANT_TO_OBJECT(v); + + ok = _setproperty(&fNPP, window_obj, java_id, &v); + } + } + + _releaseobject(window_obj); + _releaseobject(plugin_obj); + _releaseobject(java_obj); +#endif +} + nsresult ns4xPluginInstance::GetFormValue(nsAString& aValue) { diff --git a/modules/plugin/base/src/ns4xPluginInstance.h b/modules/plugin/base/src/ns4xPluginInstance.h index d1a41815464..176a33b594e 100644 --- a/modules/plugin/base/src/ns4xPluginInstance.h +++ b/modules/plugin/base/src/ns4xPluginInstance.h @@ -99,6 +99,8 @@ public: virtual PRUint16 GetPluginAPIVersion(); + virtual void DefineJavaProperties(); + //////////////////////////////////////////////////////////////////////// // ns4xPluginInstance-specific methods diff --git a/modules/plugin/base/src/nsJSNPRuntime.cpp b/modules/plugin/base/src/nsJSNPRuntime.cpp index bbe511ec70a..74638f21736 100644 --- a/modules/plugin/base/src/nsJSNPRuntime.cpp +++ b/modules/plugin/base/src/nsJSNPRuntime.cpp @@ -91,7 +91,8 @@ NPClass nsJSObjWrapper::sJSObjWrapperNPClass = nsJSObjWrapper::NP_GetProperty, nsJSObjWrapper::NP_SetProperty, nsJSObjWrapper::NP_RemoveProperty, - nsJSObjWrapper::NP_Enumerate + nsJSObjWrapper::NP_Enumerate, + nsJSObjWrapper::NP_Construct }; JS_STATIC_DLL_CALLBACK(JSBool) @@ -114,6 +115,9 @@ JS_STATIC_DLL_CALLBACK(JSBool) NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, JSObject **objp); +JS_STATIC_DLL_CALLBACK(JSBool) +NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp); + JS_STATIC_DLL_CALLBACK(void) NPObjWrapper_Finalize(JSContext *cx, JSObject *obj); @@ -121,6 +125,10 @@ JS_STATIC_DLL_CALLBACK(JSBool) NPObjWrapper_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval); +JS_STATIC_DLL_CALLBACK(JSBool) +NPObjWrapper_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, + jsval *rval); + static bool CreateNPObjectMember(NPP npp, JSContext *cx, JSObject *obj, NPObject *npobj, jsval id, jsval *vp); @@ -132,9 +140,9 @@ static JSClass sNPObjectJSWrapperClass = NPObjWrapper_AddProperty, NPObjWrapper_DelProperty, NPObjWrapper_GetProperty, NPObjWrapper_SetProperty, (JSEnumerateOp)NPObjWrapper_newEnumerate, - (JSResolveOp)NPObjWrapper_NewResolve, JS_ConvertStub, - NPObjWrapper_Finalize, nsnull, nsnull, NPObjWrapper_Call, nsnull, nsnull, - nsnull + (JSResolveOp)NPObjWrapper_NewResolve, NPObjWrapper_Convert, + NPObjWrapper_Finalize, nsnull, nsnull, NPObjWrapper_Call, + NPObjWrapper_Construct, nsnull, nsnull }; typedef struct NPObjectMemberPrivate { @@ -537,7 +545,7 @@ nsJSObjWrapper::NP_HasMethod(NPObject *npobj, NPIdentifier identifier) static bool doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args, - uint32_t argCount, NPVariant *result) + uint32_t argCount, PRBool ctorCall, NPVariant *result) { NPP npp = NPPStack::Peek(); JSContext *cx = GetJSContext(npp); @@ -596,8 +604,23 @@ doInvoke(NPObject *npobj, NPIdentifier method, const NPVariant *args, } jsval v; - JSBool ok = ::JS_CallFunctionValue(cx, npjsobj->mJSObj, fv, argCount, jsargs, - &v); + JSBool ok; + + if (ctorCall) { + JSObject *global = ::JS_GetGlobalForObject(cx, npjsobj->mJSObj); + JSObject *newObj = + ::JS_ConstructObjectWithArguments(cx, JS_GET_CLASS(cx, npjsobj->mJSObj), + nsnull, global, argCount, jsargs); + + if (newObj) { + v = OBJECT_TO_JSVAL(newObj); + ok = JS_TRUE; + } else { + ok = JS_FALSE; + } + } else { + ok = ::JS_CallFunctionValue(cx, npjsobj->mJSObj, fv, argCount, jsargs, &v); + } JS_POP_TEMP_ROOT(cx, &tvr); @@ -622,7 +645,7 @@ nsJSObjWrapper::NP_Invoke(NPObject *npobj, NPIdentifier method, return PR_FALSE; } - return doInvoke(npobj, method, args, argCount, result); + return doInvoke(npobj, method, args, argCount, PR_FALSE, result); } // static @@ -630,7 +653,8 @@ bool nsJSObjWrapper::NP_InvokeDefault(NPObject *npobj, const NPVariant *args, uint32_t argCount, NPVariant *result) { - return doInvoke(npobj, (NPIdentifier)JSVAL_VOID, args, argCount, result); + return doInvoke(npobj, (NPIdentifier)JSVAL_VOID, args, argCount, PR_FALSE, + result); } // static @@ -866,6 +890,16 @@ nsJSObjWrapper::NP_Enumerate(NPObject *npobj, NPIdentifier **identifier, return PR_TRUE; } +//static +bool +nsJSObjWrapper::NP_Construct(NPObject *npobj, const NPVariant *args, + uint32_t argCount, NPVariant *result) +{ + return doInvoke(npobj, (NPIdentifier)JSVAL_VOID, args, argCount, PR_TRUE, + result); +} + + class JSObjWrapperHashEntry : public PLDHashEntryHdr { public: @@ -1164,19 +1198,12 @@ NPObjWrapper_GetProperty(JSContext *cx, JSObject *obj, jsval id, jsval *vp) return JS_TRUE; } - if (!hasMethod) { - ThrowJSException(cx, "Trying to get unsupported property on scriptable " - "plugin object!"); - - return JS_FALSE; - } - return ReportExceptionIfPending(cx); } JS_STATIC_DLL_CALLBACK(JSBool) -CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, - jsval *rval) +CallNPMethodInternal(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, + jsval *rval, PRBool ctorCall) { while (obj && JS_GET_CLASS(cx, obj) != &sNPObjectJSWrapperClass) { obj = ::JS_GetPrototype(cx, obj); @@ -1240,20 +1267,47 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, JSObject *funobj = JSVAL_TO_OBJECT(argv[-2]); JSBool ok; + const char *msg = "Error calling method on NPObject!"; - if (funobj != obj) { + if (ctorCall) { + // construct a new NPObject based on the NPClass in npobj. Fail if + // no construct method is available. + + if (NP_CLASS_STRUCT_VERSION_HAS_CTOR(npobj->_class) && + npobj->_class->construct) { + ok = npobj->_class->construct(npobj, npargs, argc, &v); + } else { + ok = JS_FALSE; + + msg = "Attempt to construct object from class with no constructor."; + } + } else if (funobj != obj) { // A obj.function() style call is made, get the method name from // the function object. - JSFunction *fun = (JSFunction *)::JS_GetPrivate(cx, funobj); - jsval method = STRING_TO_JSVAL(::JS_GetFunctionId(fun)); + if (npobj->_class->invoke) { + JSFunction *fun = (JSFunction *)::JS_GetPrivate(cx, funobj); + jsval method = STRING_TO_JSVAL(::JS_GetFunctionId(fun)); - ok = npobj->_class->invoke(npobj, (NPIdentifier)method, npargs, argc, &v); + ok = npobj->_class->invoke(npobj, (NPIdentifier)method, npargs, argc, + &v); + } else { + ok = JS_FALSE; + + msg = "Attempt to call a method on object with no invoke method."; + } } else { - // obj is a callable object that is being called, no method name - // available then. Invoke the default method. + if (npobj->_class->invokeDefault) { + // obj is a callable object that is being called, no method name + // available then. Invoke the default method. - ok = npobj->_class->invokeDefault(npobj, npargs, argc, &v); + ok = npobj->_class->invokeDefault(npobj, npargs, argc, &v); + } else { + ok = JS_FALSE; + + msg = "Attempt to call a default method on object with no " + "invokeDefault method."; + } } // Release arguments. @@ -1266,7 +1320,7 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, } if (!ok) { - ThrowJSException(cx, "Error calling method on NPObject!"); + ThrowJSException(cx, msg); return JS_FALSE; } @@ -1279,6 +1333,13 @@ CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, return ReportExceptionIfPending(cx); } +JS_STATIC_DLL_CALLBACK(JSBool) +CallNPMethod(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, + jsval *rval) +{ + return CallNPMethodInternal(cx, obj, argc, argv, rval, PR_FALSE); +} + struct NPObjectEnumerateState { PRUint32 index; PRUint32 length; @@ -1418,6 +1479,18 @@ NPObjWrapper_NewResolve(JSContext *cx, JSObject *obj, jsval id, uintN flags, return ReportExceptionIfPending(cx); } +JS_STATIC_DLL_CALLBACK(JSBool) +NPObjWrapper_Convert(JSContext *cx, JSObject *obj, JSType type, jsval *vp) +{ + // The sole reason we implement this hook is to prevent the JS + // engine from calling valueOf() on NPObject's. Some NPObject's may + // actually implement a method named valueOf, but it's unlikely to + // behave as the JS engine expects it to. IOW, this is an empty hook + // that overrides what the default hook does. + + return JS_TRUE; +} + JS_STATIC_DLL_CALLBACK(void) NPObjWrapper_Finalize(JSContext *cx, JSObject *obj) { @@ -1439,7 +1512,16 @@ JS_STATIC_DLL_CALLBACK(JSBool) NPObjWrapper_Call(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) { - return CallNPMethod(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval); + return CallNPMethodInternal(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval, + PR_FALSE); +} + +JS_STATIC_DLL_CALLBACK(JSBool) +NPObjWrapper_Construct(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, + jsval *rval) +{ + return CallNPMethodInternal(cx, JSVAL_TO_OBJECT(argv[-2]), argc, argv, rval, + PR_TRUE); } class NPObjWrapperHashEntry : public PLDHashEntryHdr diff --git a/modules/plugin/base/src/nsJSNPRuntime.h b/modules/plugin/base/src/nsJSNPRuntime.h index ac1f47e4995..ac5fd4a6225 100644 --- a/modules/plugin/base/src/nsJSNPRuntime.h +++ b/modules/plugin/base/src/nsJSNPRuntime.h @@ -90,6 +90,8 @@ protected: static bool NP_RemoveProperty(NPObject *obj, NPIdentifier property); static bool NP_Enumerate(NPObject *npobj, NPIdentifier **identifier, uint32_t *count); + static bool NP_Construct(NPObject *obj, const NPVariant *args, + uint32_t argCount, NPVariant *result); public: static NPClass sJSObjWrapperNPClass; diff --git a/modules/plugin/base/src/nsPluginHostImpl.cpp b/modules/plugin/base/src/nsPluginHostImpl.cpp index f131a2ac164..417bdbfa59a 100644 --- a/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -50,6 +50,7 @@ #include "ns4xPluginStreamListener.h" #include "nsPluginInstancePeer.h" #include "nsIPlugin.h" +#include "nsIPluginInstanceInternal.h" #ifdef OJI #include "nsIJVMPlugin.h" #include "nsIJVMPluginInstance.h" @@ -730,17 +731,24 @@ inline char* new_str(const char* str) //////////////////////////////////////////////////////////////////////// nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag) + : mPluginHost(nsnull), + mName(new_str(aPluginTag->mName)), + mDescription(new_str(aPluginTag->mDescription)), + mVariants(aPluginTag->mVariants), + mMimeTypeArray(nsnull), + mMimeDescriptionArray(nsnull), + mExtensionsArray(nsnull), + mLibrary(nsnull), + mEntryPoint(nsnull), + mCanUnloadLibrary(PR_TRUE), + mXPConnected(PR_FALSE), + mIsJavaPlugin(aPluginTag->mIsJavaPlugin), + mIsNPRuntimeEnabledJavaPlugin(aPluginTag->mIsNPRuntimeEnabledJavaPlugin), + mFileName(new_str(aPluginTag->mFileName)), + mFullPath(new_str(aPluginTag->mFullPath)), + mLastModifiedTime(0), + mFlags(NS_PLUGIN_FLAG_ENABLED) { - mPluginHost = nsnull; - mNext = nsnull; - mName = new_str(aPluginTag->mName); - mDescription = new_str(aPluginTag->mDescription); - mVariants = aPluginTag->mVariants; - - mMimeTypeArray = nsnull; - mMimeDescriptionArray = nsnull; - mExtensionsArray = nsnull; - if(aPluginTag->mMimeTypeArray != nsnull) { mMimeTypeArray = new char*[mVariants]; @@ -761,36 +769,49 @@ nsPluginTag::nsPluginTag(nsPluginTag* aPluginTag) for (int i = 0; i < mVariants; i++) mExtensionsArray[i] = new_str(aPluginTag->mExtensionsArray[i]); } - - mLibrary = nsnull; - mCanUnloadLibrary = PR_TRUE; - mEntryPoint = nsnull; - mFlags = NS_PLUGIN_FLAG_ENABLED; - mXPConnected = PR_FALSE; - mIsJavaPlugin = aPluginTag->mIsJavaPlugin; - mFileName = new_str(aPluginTag->mFileName); - mFullPath = new_str(aPluginTag->mFullPath); } //////////////////////////////////////////////////////////////////////// nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo) + : mPluginHost(nsnull), + mName(new_str(aPluginInfo->fName)), + mDescription(new_str(aPluginInfo->fDescription)), + mVariants(aPluginInfo->fVariantCount), + mMimeTypeArray(nsnull), + mMimeDescriptionArray(nsnull), + mExtensionsArray(nsnull), + mLibrary(nsnull), + mEntryPoint(nsnull), +#ifdef XP_MACOSX + mCanUnloadLibrary(!aPluginInfo->fBundle), +#else + mCanUnloadLibrary(PR_TRUE), +#endif + mXPConnected(PR_FALSE), + mIsJavaPlugin(PR_FALSE), + mIsNPRuntimeEnabledJavaPlugin(PR_FALSE), + mFileName(new_str(aPluginInfo->fFileName)), + mFullPath(new_str(aPluginInfo->fFullPath)), + mLastModifiedTime(0), + mFlags(NS_PLUGIN_FLAG_ENABLED) { - mPluginHost = nsnull; - mNext = nsnull; - mName = new_str(aPluginInfo->fName); - mDescription = new_str(aPluginInfo->fDescription); - mVariants = aPluginInfo->fVariantCount; - - mMimeTypeArray = nsnull; - mMimeDescriptionArray = nsnull; - mExtensionsArray = nsnull; - mIsJavaPlugin = PR_FALSE; - if(aPluginInfo->fMimeTypeArray != nsnull) { mMimeTypeArray = new char*[mVariants]; for (int i = 0; i < mVariants; i++) { + if (mIsJavaPlugin && aPluginInfo->fMimeTypeArray[i] && + strcmp(aPluginInfo->fMimeTypeArray[i], + "application/x-java-vm-npruntime") == 0) { + mIsNPRuntimeEnabledJavaPlugin = PR_TRUE; + + // Stop processing here, any mimetypes after the magic "I'm a + // NPRuntime enabled Java plugin" mimetype will be ignored. + mVariants = i; + + break; + } + mMimeTypeArray[i] = new_str(aPluginInfo->fMimeTypeArray[i]); if (nsPluginHostImpl::IsJavaMIMEType(mMimeTypeArray[i])) mIsJavaPlugin = PR_TRUE; @@ -833,18 +854,6 @@ nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo) for (int i = 0; i < mVariants; i++) mExtensionsArray[i] = new_str(aPluginInfo->fExtensionArray[i]); } - - mFileName = new_str(aPluginInfo->fFileName); - mFullPath = new_str(aPluginInfo->fFullPath); - - mLibrary = nsnull; - mCanUnloadLibrary = PR_TRUE; - mEntryPoint = nsnull; -#ifdef XP_MACOSX - mCanUnloadLibrary = !aPluginInfo->fBundle; -#endif - mFlags = NS_PLUGIN_FLAG_ENABLED; - mXPConnected = PR_FALSE; } @@ -860,7 +869,9 @@ nsPluginTag::nsPluginTag(const char* aName, PRInt32 aVariants, PRInt64 aLastModifiedTime, PRBool aCanUnload) - : mNext(nsnull), + : mPluginHost(nsnull), + mName(new_str(aName)), + mDescription(new_str(aDescription)), mVariants(aVariants), mMimeTypeArray(nsnull), mMimeDescriptionArray(nsnull), @@ -869,22 +880,30 @@ nsPluginTag::nsPluginTag(const char* aName, mEntryPoint(nsnull), mCanUnloadLibrary(aCanUnload), mXPConnected(PR_FALSE), + mIsJavaPlugin(PR_FALSE), + mIsNPRuntimeEnabledJavaPlugin(PR_FALSE), + mFileName(new_str(aFileName)), + mFullPath(new_str(aFullPath)), mLastModifiedTime(aLastModifiedTime), mFlags(0) // Caller will read in our flags from cache { - mPluginHost = nsnull; - mName = new_str(aName); - mDescription = new_str(aDescription); - mFileName = new_str(aFileName); - mFullPath = new_str(aFullPath); - mIsJavaPlugin = PR_FALSE; - - if (mVariants) { + if (aVariants) { mMimeTypeArray = new char*[mVariants]; mMimeDescriptionArray = new char*[mVariants]; mExtensionsArray = new char*[mVariants]; for (PRInt32 i = 0; i < aVariants; ++i) { + if (mIsJavaPlugin && aMimeTypes[i] && + strcmp(aMimeTypes[i], "application/x-java-vm-npruntime") == 0) { + mIsNPRuntimeEnabledJavaPlugin = PR_TRUE; + + // Stop processing here, any mimetypes after the magic "I'm a + // NPRuntime enabled Java plugin" mimetype will be ignored. + mVariants = i; + + break; + } + mMimeTypeArray[i] = new_str(aMimeTypes[i]); mMimeDescriptionArray[i] = new_str(aMimeDescriptions[i]); mExtensionsArray[i] = new_str(aExtensions[i]); @@ -904,17 +923,13 @@ nsPluginTag::~nsPluginTag() RegisterWithCategoryManager(PR_FALSE, nsPluginTag::ePluginUnregister); } - if (nsnull != mName) { - delete[] (mName); - mName = nsnull; - } + delete[] (mName); + mName = nsnull; - if (nsnull != mDescription) { - delete[] (mDescription); - mDescription = nsnull; - } + delete[] (mDescription); + mDescription = nsnull; - if (nsnull != mMimeTypeArray) { + if (mMimeTypeArray) { for (int i = 0; i < mVariants; i++) delete[] mMimeTypeArray[i]; @@ -922,7 +937,7 @@ nsPluginTag::~nsPluginTag() mMimeTypeArray = nsnull; } - if (nsnull != mMimeDescriptionArray) { + if (mMimeDescriptionArray) { for (int i = 0; i < mVariants; i++) delete[] mMimeDescriptionArray[i]; @@ -930,7 +945,7 @@ nsPluginTag::~nsPluginTag() mMimeDescriptionArray = nsnull; } - if (nsnull != mExtensionsArray) { + if (mExtensionsArray) { for (int i = 0; i < mVariants; i++) delete[] mExtensionsArray[i]; @@ -938,18 +953,11 @@ nsPluginTag::~nsPluginTag() mExtensionsArray = nsnull; } - if(nsnull != mFileName) - { - delete [] mFileName; - mFileName = nsnull; - } - - if(nsnull != mFullPath) - { - delete [] mFullPath; - mFullPath = nsnull; - } + delete [] mFileName; + mFileName = nsnull; + delete [] mFullPath; + mFullPath = nsnull; } NS_IMPL_ISUPPORTS1(nsPluginTag, nsIPluginTag) @@ -2895,7 +2903,7 @@ nsresult nsPluginHostImpl::UserAgent(const char **retstring) return res; } -nsresult nsPluginHostImpl:: GetPrompt(nsIPluginInstanceOwner *aOwner, nsIPrompt **aPrompt) +nsresult nsPluginHostImpl::GetPrompt(nsIPluginInstanceOwner *aOwner, nsIPrompt **aPrompt) { nsresult rv; nsCOMPtr prompt; @@ -3756,10 +3764,11 @@ nsresult nsPluginHostImpl::AddInstanceToActiveList(nsCOMPtr aPlugin, nsIPluginInstancePeer* peer) { - NS_ENSURE_ARG_POINTER(aURL); - nsCAutoString url; - (void)aURL->GetSpec(url); + // It's OK to not have a URL here, as is the case with the dummy + // Java plugin. In that case simply use an empty string... + if (aURL) + aURL->GetSpec(url); // let's find the corresponding plugin tag by matching nsIPlugin pointer // it's legal for XPCOM plugins not to have nsIPlugin implemented but @@ -3899,9 +3908,10 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, return rv; } -NS_IMETHODIMP nsPluginHostImpl::TrySetUpPluginInstance(const char *aMimeType, - nsIURI *aURL, - nsIPluginInstanceOwner *aOwner) +NS_IMETHODIMP +nsPluginHostImpl::TrySetUpPluginInstance(const char *aMimeType, + nsIURI *aURL, + nsIPluginInstanceOwner *aOwner) { #ifdef PLUGIN_LOGGING nsCAutoString urlSpec; @@ -3920,13 +3930,10 @@ NS_IMETHODIMP nsPluginHostImpl::TrySetUpPluginInstance(const char *aMimeType, nsCOMPtr plugin; const char* mimetype = nsnull; - if(!aURL) - return NS_ERROR_FAILURE; - // if don't have a mimetype or no plugin can handle this mimetype // check by file extension nsPluginTag* pluginTag = FindPluginForType(aMimeType, PR_TRUE); - if (!pluginTag) { + if (aURL && !pluginTag) { nsCOMPtr url = do_QueryInterface(aURL); if (!url) return NS_ERROR_FAILURE; @@ -3971,7 +3978,7 @@ NS_IMETHODIMP nsPluginHostImpl::TrySetUpPluginInstance(const char *aMimeType, // browser, before plugin gets a chance. // - if (isJavaPlugin) { + if (isJavaPlugin && !pluginTag->mIsNPRuntimeEnabledJavaPlugin) { // If Java is installed, get proxy JNI. nsCOMPtr jvmManager = do_GetService(nsIJVMManager::GetCID(), &result); @@ -4017,7 +4024,7 @@ NS_IMETHODIMP nsPluginHostImpl::TrySetUpPluginInstance(const char *aMimeType, #ifdef XP_WIN if (!firstJavaPlugin && restoreOrigDir) { - BOOL bCheck = :: SetCurrentDirectory(origDir); + BOOL bCheck = ::SetCurrentDirectory(origDir); NS_ASSERTION(bCheck, " Error restoring driectoy"); firstJavaPlugin = TRUE; } @@ -5601,7 +5608,7 @@ nsPluginHostImpl::WritePluginInfo() (tag->mName ? tag->mName : ""), PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER, - tag->mVariants); + tag->mVariants + (tag->mIsNPRuntimeEnabledJavaPlugin ? 1 : 0)); // Add in each mimetype this plugin supports for (int i=0; imVariants; i++) { @@ -5615,6 +5622,18 @@ nsPluginHostImpl::WritePluginInfo() PLUGIN_REGISTRY_FIELD_DELIMITER, PLUGIN_REGISTRY_END_OF_LINE_MARKER); } + + if (tag->mIsNPRuntimeEnabledJavaPlugin) { + PR_fprintf(fd, "%d%c%s%c%s%c%s%c%c\n", + tag->mVariants, PLUGIN_REGISTRY_FIELD_DELIMITER, + "application/x-java-vm-npruntime", + PLUGIN_REGISTRY_FIELD_DELIMITER, + "", + PLUGIN_REGISTRY_FIELD_DELIMITER, + "", + PLUGIN_REGISTRY_FIELD_DELIMITER, + PLUGIN_REGISTRY_END_OF_LINE_MARKER); + } } } @@ -6837,6 +6856,38 @@ nsPluginHostImpl::DeletePluginNativeWindow(nsPluginNativeWindow * aPluginNativeW return PLUG_DeletePluginNativeWindow(aPluginNativeWindow); } +NS_IMETHODIMP +nsPluginHostImpl::InstantiateDummyJavaPlugin(nsIPluginInstanceOwner *aOwner) +{ + // Pass PR_FALSE as the second arg, we want the answer to be the + // same here whether the Java plugin is enabled or not. + nsPluginTag *plugin = FindPluginForType("application/x-java-vm", PR_FALSE); + + if (!plugin || !plugin->mIsNPRuntimeEnabledJavaPlugin) { + // No NPRuntime enabled Java plugin found, no point in + // instantiating a dummy plugin then. + + return NS_OK; + } + + nsresult rv = SetUpPluginInstance("application/x-java-vm", nsnull, aOwner); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr instance; + aOwner->GetInstance(*getter_AddRefs(instance)); + + nsCOMPtr plugin_internal = + do_QueryInterface(instance); + + if (!plugin_internal) { + return NS_OK; + } + + plugin_internal->DefineJavaProperties(); + + return NS_OK; +} + /* ----- end of nsPIPluginHost implementation ----- */ nsresult diff --git a/modules/plugin/base/src/nsPluginHostImpl.h b/modules/plugin/base/src/nsPluginHostImpl.h index 73a2aac3750..21ed38e90df 100644 --- a/modules/plugin/base/src/nsPluginHostImpl.h +++ b/modules/plugin/base/src/nsPluginHostImpl.h @@ -150,6 +150,7 @@ public: PRPackedBool mCanUnloadLibrary; PRPackedBool mXPConnected; PRPackedBool mIsJavaPlugin; + PRPackedBool mIsNPRuntimeEnabledJavaPlugin; char *mFileName; char *mFullPath; PRInt64 mLastModifiedTime;