diff --git a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp index 6f7d6925c29..74347ba6be2 100644 --- a/mozilla/modules/plugin/base/src/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPlugin.cpp @@ -518,23 +518,23 @@ ns4xPlugin::_write(NPP npp, NPStream *pstream, int32 len, void *buffer) if(!npp) return -1; - ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; - NS_ASSERTION(wrapper != NULL, "null stream"); + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; + NS_ASSERTION(wrapper != NULL, "null stream"); - if (wrapper == NULL) - return -1; + if (wrapper == NULL) + return -1; - nsIOutputStream* stream; - wrapper->GetStream(stream); + nsIOutputStream* stream; + wrapper->GetStream(stream); + + PRUint32 count = 0; + nsresult rv = stream->Write((char *)buffer, len, &count); + NS_RELEASE(stream); - PRUint32 count = 0; - nsresult rv = stream->Write((char *)buffer, len, &count); - NS_RELEASE(stream); + if(rv != NS_OK) + return -1; - if(rv != NS_OK) - return -1; - - return (int32)count; + return (int32)count; } NPError NP_EXPORT @@ -556,17 +556,17 @@ ns4xPlugin::_destroystream(NPP npp, NPStream *pstream, NPError reason) return NPERR_NO_ERROR; } - ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; - NS_ASSERTION(wrapper != NULL, "null wrapper"); + NS_ASSERTION(wrapper != NULL, "null wrapper"); - if (wrapper == NULL) - return NPERR_INVALID_PARAM; + if (wrapper == NULL) + return NPERR_INVALID_PARAM; - // This will release the wrapped nsIOutputStream. - delete wrapper; + // This will release the wrapped nsIOutputStream. + delete wrapper; - return NPERR_NO_ERROR; + return NPERR_NO_ERROR; } void NP_EXPORT @@ -704,27 +704,51 @@ ns4xPlugin::_getvalue(NPP npp, NPNVariable variable, void *result) if(!npp) return NPERR_INVALID_INSTANCE_ERROR; - nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; + switch(variable) + { +#ifdef XP_UNIX + case NPNVxDisplay : return NPERR_GENERIC_ERROR; - NS_ASSERTION(inst != NULL, "null instance"); + case NPNVxtAppContext : return NPERR_GENERIC_ERROR; +#endif - if (inst == NULL) - return NPERR_INVALID_INSTANCE_ERROR; +#ifdef XP_PC + case NPNVnetscapeWindow : return NPERR_GENERIC_ERROR; +#endif - nsIPluginInstancePeer *peer; + case NPNVjavascriptEnabledBool : *(NPBool*)result = TRUE; return NPERR_NO_ERROR; - if (NS_OK == inst->GetPeer(&peer)) - { - nsresult rv; + case NPNVasdEnabledBool : *(NPBool*)result = FALSE; return NPERR_NO_ERROR; - // XXX Note that for backwards compatibility, the old NPNVariables - // map correctly to NPPluginManagerVariables. - rv = peer->GetValue((nsPluginInstancePeerVariable)variable, result); - NS_RELEASE(peer); - return rv; - } - else - return NPERR_GENERIC_ERROR; + case NPNVisOfflineBool : *(NPBool*)result = FALSE; return NPERR_NO_ERROR; + + default : return NPERR_GENERIC_ERROR; + + } + +#if 0 + nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; + + NS_ASSERTION(inst != NULL, "null instance"); + + if (inst == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + nsIPluginInstancePeer *peer; + + if (NS_OK == inst->GetPeer(&peer)) + { + nsresult rv; + + // XXX Note that for backwards compatibility, the old NPNVariables + // map correctly to NPPluginManagerVariables. + rv = peer->GetValue((nsPluginInstancePeerVariable)variable, result); + NS_RELEASE(peer); + return rv; + } + else + return NPERR_GENERIC_ERROR; +#endif } NPError NP_EXPORT @@ -818,7 +842,6 @@ ns4xPlugin::_memalloc (uint32 size) java_lang_Class* NP_EXPORT ns4xPlugin::_getJavaClass(void* handle) { - // Is this just a generic call into the Java VM? return NULL; } diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp index bca13548f3b..5794d9c41b4 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.cpp @@ -283,6 +283,7 @@ ns4xPluginInstance :: ns4xPluginInstance(NPPluginFuncs* callbacks) mWindowless = PR_FALSE; mTransparent = PR_FALSE; + mStarted = PR_FALSE; } @@ -328,51 +329,7 @@ NS_IMETHODIMP ns4xPluginInstance :: QueryInterface(const nsIID& iid, void** inst NS_IMETHODIMP ns4xPluginInstance :: Initialize(nsIPluginInstancePeer* peer) { - PRUint16 count = 0; - const char* const* names = nsnull; - const char* const* values = nsnull; - nsresult rv; - NPError error; - nsIPluginTagInfo* taginfo; - - NS_ASSERTION(peer != NULL, "null peer"); - - fPeer = peer; - NS_ADDREF(fPeer); - - rv = fPeer->QueryInterface(kIPluginTagInfoIID, (void **)&taginfo); - - if (NS_OK == rv) - { - taginfo->GetAttributes(count, names, values); - NS_IF_RELEASE(taginfo); - } - - if (fCallbacks->newp == NULL) - return NS_ERROR_FAILURE; // XXX right error? - - // XXX Note that the NPPluginType_* enums were crafted to be - // backward compatible... - - nsPluginMode mode; - nsMIMEType mimetype; - - fPeer->GetMode(&mode); - fPeer->GetMIMEType(&mimetype); - - error = CallNPP_NewProc(fCallbacks->newp, - (char *)mimetype, - &fNPP, - (PRUint16)mode, - count, - (char**)names, - (char**)values, - NULL); // saved data - - if(error != NPERR_NO_ERROR) - rv = NS_ERROR_FAILURE; - - return rv; + return InitializePlugin(peer); } NS_IMETHODIMP ns4xPluginInstance :: GetPeer(nsIPluginInstancePeer* *resultingPeer) @@ -385,36 +342,89 @@ NS_IMETHODIMP ns4xPluginInstance :: GetPeer(nsIPluginInstancePeer* *resultingPee NS_IMETHODIMP ns4xPluginInstance::Start(void) { - // XXX At some point, we maybe should implement start and stop to - // load/unload the 4.x plugin, just in case there are some plugins - // that rely on that behavior... -printf("instance start called\n"); + printf("instance start called\n"); + if(mStarted) return NS_OK; + else + return InitializePlugin(fPeer); } NS_IMETHODIMP ns4xPluginInstance::Stop(void) { -printf("instance stop called\n"); - return NS_OK; + NPError error; + + printf("instance stop/destroy called\n"); + if (fCallbacks->destroy == NULL) + return NS_ERROR_FAILURE; // XXX right error? + + NPSavedData *sdata; + + error = (nsresult)CallNPP_DestroyProc(fCallbacks->destroy, + &fNPP, &sdata); // saved data + + mStarted = PR_FALSE; + if(error != NPERR_NO_ERROR) + return NS_ERROR_FAILURE; + else + return NS_OK; +} + +nsresult ns4xPluginInstance::InitializePlugin(nsIPluginInstancePeer* peer) +{ + PRUint16 count = 0; + const char* const* names = nsnull; + const char* const* values = nsnull; + nsresult rv; + NPError error; + nsIPluginTagInfo* taginfo; + + NS_ASSERTION(peer != NULL, "null peer"); + + fPeer = peer; + NS_ADDREF(fPeer); + + rv = fPeer->QueryInterface(kIPluginTagInfoIID, (void **)&taginfo); + + if (NS_OK == rv) + { + taginfo->GetAttributes(count, names, values); + NS_IF_RELEASE(taginfo); + } + + if (fCallbacks->newp == NULL) + return NS_ERROR_FAILURE; // XXX right error? + + // XXX Note that the NPPluginType_* enums were crafted to be + // backward compatible... + + nsPluginMode mode; + nsMIMEType mimetype; + + fPeer->GetMode(&mode); + fPeer->GetMIMEType(&mimetype); + + error = CallNPP_NewProc(fCallbacks->newp, + (char *)mimetype, + &fNPP, + (PRUint16)mode, + count, + (char**)names, + (char**)values, + NULL); // saved data + + if(error != NPERR_NO_ERROR) + rv = NS_ERROR_FAILURE; + + mStarted = PR_TRUE; + + return rv; } NS_IMETHODIMP ns4xPluginInstance::Destroy(void) { - NPError error; - -printf("instance destroy called\n"); - if (fCallbacks->destroy == NULL) - return NS_ERROR_FAILURE; // XXX right error? - - NPSavedData *sdata; - - error = (nsresult)CallNPP_DestroyProc(fCallbacks->destroy, - &fNPP, &sdata); // saved data - - if(error != NPERR_NO_ERROR) - return NS_ERROR_FAILURE; - else - return NS_OK; + printf("instance destroy called\n"); + // destruction is handled in the Stop call + return NS_OK; } NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) diff --git a/mozilla/modules/plugin/base/src/ns4xPluginInstance.h b/mozilla/modules/plugin/base/src/ns4xPluginInstance.h index d755b61033e..e9404bacaca 100644 --- a/mozilla/modules/plugin/base/src/ns4xPluginInstance.h +++ b/mozilla/modules/plugin/base/src/ns4xPluginInstance.h @@ -112,6 +112,8 @@ public: protected: + nsresult InitializePlugin(nsIPluginInstancePeer* peer); + /** * The plugin instance peer for this instance. */ @@ -135,6 +137,7 @@ protected: PRBool mWindowless; PRBool mTransparent; + PRBool mStarted; }; diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp index a5213b07621..434baea67fc 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.cpp @@ -1002,6 +1002,8 @@ nsPluginHostImpl::nsPluginHostImpl(nsIServiceManager *serviceMgr) NS_INIT_REFCNT(); mPluginsLoaded = PR_FALSE; mServiceMgr = serviceMgr; + mNumActivePlugins = 0; + mOldestActivePlugin = 0; } nsPluginHostImpl::~nsPluginHostImpl() @@ -1342,10 +1344,18 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, nsresult rv; nsIPluginInstance *instance = nsnull; + if(FindStoppedPluginForURL(aURL, aOwner) == NS_OK) + { + aOwner->GetInstance(instance); + if(!aMimeType || PL_strcasecmp(aMimeType, "application/x-java-vm")) + rv = NewEmbededPluginStream(aURL, nsnull, instance); + return NS_OK; + } + rv = SetUpPluginInstance(aMimeType, aURL, aOwner); - + if(rv == NS_OK) - rv = aOwner->GetInstance(instance); + rv = aOwner->GetInstance(instance); // if we have a failure error, it means we found a plugin for the mimetype, // but we had a problem with the entry point @@ -1378,7 +1388,7 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, // don't make an initial steam if it's a java applet if(!aMimeType || PL_strcasecmp(aMimeType, "application/x-java-vm")) - rv = NewEmbededPluginStream(aURL, nsnull, instance); + rv = NewEmbededPluginStream(aURL, nsnull, instance); NS_RELEASE(instance); } @@ -1403,7 +1413,16 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateFullPagePlugin(const char *aMimeType, if (rv != NS_OK) url = nsnull; - + + if(FindStoppedPluginForURL(url, aOwner) == NS_OK) + { + nsIPluginInstance* instance; + aOwner->GetInstance(instance); + if(!aMimeType || PL_strcasecmp(aMimeType, "application/x-java-vm")) + rv = NewFullPagePluginStream(aStreamListener, instance); + return NS_OK; + } + rv = SetUpPluginInstance(aMimeType, url, aOwner); NS_IF_RELEASE(url); @@ -1433,6 +1452,72 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateFullPagePlugin(const char *aMimeType, return rv; } +nsresult nsPluginHostImpl::FindStoppedPluginForURL(nsIURL* aURL, nsIPluginInstanceOwner *aOwner) +{ + PRUint32 i; + const char* url; + (void)aURL->GetSpec(&url); + + for(i=0; iGetWindow(window); + + aOwner->SetInstance(instance); + + // we have to reset the owner and instance in the plugin instance peer + //instance->GetPeer(&peer); + ((nsPluginInstancePeerImpl*)mActivePluginList[i].mPeer)->SetOwner(aOwner); + + aOwner->CreateWidget(); + instance->SetWindow(window); + instance->Start(); + + return NS_OK; + } + } + return NS_ERROR_FAILURE; +} + +void nsPluginHostImpl::AddInstanceToActiveList(nsIPluginInstance* aInstance, nsIURL* aURL) +{ + const char* url; + (void)aURL->GetSpec(&url); + + if(mNumActivePlugins < MAX_ACTIVE_PLUGINS) + { + mActivePluginList[mNumActivePlugins].mURL = PL_strdup(url); + mActivePluginList[mNumActivePlugins].mInstance = aInstance; + + aInstance->GetPeer(&(mActivePluginList[mNumActivePlugins].mPeer)); + ++mNumActivePlugins; + } + else + { + // XXX - TODO: we need to make sure that this plugin is currently not active + + // destroy the oldest plugin on the list + mActivePluginList[mOldestActivePlugin].mInstance->Destroy(); + NS_RELEASE(mActivePluginList[mOldestActivePlugin].mInstance); + NS_RELEASE(mActivePluginList[mOldestActivePlugin].mPeer); + PL_strfree(mActivePluginList[mOldestActivePlugin].mURL); + + // replace it with the new one + mActivePluginList[mOldestActivePlugin].mURL = PL_strdup(url); + mActivePluginList[mOldestActivePlugin].mInstance = aInstance; + aInstance->GetPeer(&(mActivePluginList[mOldestActivePlugin].mPeer)); + + ++mOldestActivePlugin; + if(mOldestActivePlugin == MAX_ACTIVE_PLUGINS) + mOldestActivePlugin = 0; + + } +} + NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, nsIURL *aURL, nsIPluginInstanceOwner *aOwner) @@ -1461,10 +1546,12 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, mimetype = aMimeType; - if (GetPluginFactory(mimetype, &plugin) == NS_OK) { + if(GetPluginFactory(mimetype, &plugin) == NS_OK) + { // instantiate a plugin. nsIPluginInstance* instance = NULL; - if (plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance) == NS_OK) { + if(plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance) == NS_OK) + { aOwner->SetInstance(instance); nsPluginInstancePeerImpl *peer = new nsPluginInstancePeerImpl(); @@ -1474,10 +1561,12 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, // tell the plugin instance to initialize itself and pass in the peer. instance->Initialize(peer); - NS_RELEASE(instance); + + AddInstanceToActiveList(instance, aURL); + //NS_RELEASE(instance); result = NS_OK; - } - NS_RELEASE(plugin); + } + NS_RELEASE(plugin); } return result; } @@ -1750,13 +1839,13 @@ NS_IMETHODIMP nsPluginHostImpl::GetPluginFactory(const char *aMimeType, nsIPlugi // need to get the plugin factory from this plugin. nsFactoryProc nsGetFactory = nsnull; nsGetFactory = (nsFactoryProc) PR_FindSymbol(pluginTag->mLibrary, "NSGetFactory"); - if (nsGetFactory != nsnull) + if(nsGetFactory != nsnull) { - rv = nsGetFactory(mServiceMgr, kPluginCID, nsnull, nsnull, // XXX fix ClassName/ProgID - (nsIFactory**)&pluginTag->mEntryPoint); - plugin = pluginTag->mEntryPoint; - if (plugin != NULL) - plugin->Initialize(); + rv = nsGetFactory(mServiceMgr, kPluginCID, nsnull, nsnull, // XXX fix ClassName/ProgID + (nsIFactory**)&pluginTag->mEntryPoint); + plugin = pluginTag->mEntryPoint; + if (plugin != NULL) + plugin->Initialize(); } else { @@ -1764,6 +1853,8 @@ NS_IMETHODIMP nsPluginHostImpl::GetPluginFactory(const char *aMimeType, nsIPlugi (nsIPlugin **)&pluginTag->mEntryPoint, mServiceMgr); plugin = pluginTag->mEntryPoint; + pluginTag->mFlags |= NS_PLUGIN_FLAG_OLDSCHOOL; + // no need to initialize, already done by CreatePlugin() } } @@ -1826,57 +1917,6 @@ NS_IMETHODIMP nsPluginHostImpl::LoadPlugins() return NS_ERROR_FAILURE; } -// private methods - -PRLibrary* nsPluginHostImpl::LoadPluginLibrary(const nsFileSpec &pluginSpec) -{ - PRLibrary* plugin = NULL; - -#ifdef XP_PC - plugin = PR_LoadLibrary((const char*)pluginSpec); -#endif - -#ifdef XP_MAC - char* pluginName = pluginSpec.GetLeafName(); - if (pluginName != NULL) { - plugin = PR_LoadLibrary(pluginName); - delete[] pluginName; - } -#endif - - return plugin; -} - - -PRLibrary* nsPluginHostImpl::LoadPluginLibrary(const char* pluginPath, const char* path) -{ -#ifdef XP_PC - BOOL restoreOrigDir = FALSE; - char aOrigDir[MAX_PATH + 1]; - DWORD dwCheck = ::GetCurrentDirectory(sizeof(aOrigDir), aOrigDir); - PR_ASSERT(dwCheck <= MAX_PATH + 1); - - if (dwCheck <= MAX_PATH + 1) - { - restoreOrigDir = ::SetCurrentDirectory(pluginPath); - PR_ASSERT(restoreOrigDir); - } - - PRLibrary* plugin = PR_LoadLibrary(path); - - if (restoreOrigDir) - { - BOOL bCheck = ::SetCurrentDirectory(aOrigDir); - PR_ASSERT(bCheck); - } - - return plugin; -#else - return NULL; -#endif -} - - /* Called by GetURL and PostURL */ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, diff --git a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h index 810473339b3..e68beff6f9b 100644 --- a/mozilla/modules/plugin/base/src/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/base/src/nsPluginHostImpl.h @@ -54,6 +54,15 @@ public: PRUint32 mFlags; }; +#define MAX_ACTIVE_PLUGINS 10 + +typedef struct nsActivePlugin +{ + char* mURL; + nsIPluginInstancePeer* mPeer; + nsIPluginInstance* mInstance; +} nsActivePlugin; + #define NS_PLUGIN_FLAG_ENABLED 0x0001 //is this plugin enabled? #define NS_PLUGIN_FLAG_OLDSCHOOL 0x0002 //is this a pre-xpcom plugin? @@ -224,17 +233,23 @@ private: nsresult NewFullPagePluginStream(nsIStreamListener *&aStreamListener, nsIPluginInstance *aInstance); - PRLibrary* LoadPluginLibrary(const nsFileSpec &pluginSpec); - - PRLibrary* LoadPluginLibrary(const char* pluginPath, const char* path); - nsresult FindPluginEnabledForType(const char* aMimeType, nsPluginTag* &aPlugin); + nsresult + FindStoppedPluginForURL(nsIURL* aURL, nsIPluginInstanceOwner *aOwner); + + void + AddInstanceToActiveList(nsIPluginInstance* aInstance, nsIURL* aURL); + char *mPluginPath; nsPluginTag *mPlugins; PRBool mPluginsLoaded; nsIServiceManager *mServiceMgr; + + PRUint32 mNumActivePlugins; + PRUint32 mOldestActivePlugin; + nsActivePlugin mActivePluginList[MAX_ACTIVE_PLUGINS]; }; #endif diff --git a/mozilla/modules/plugin/base/src/nsPluginInstancePeer.cpp b/mozilla/modules/plugin/base/src/nsPluginInstancePeer.cpp index 399a98635f5..207a3f5db2f 100644 --- a/mozilla/modules/plugin/base/src/nsPluginInstancePeer.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginInstancePeer.cpp @@ -827,6 +827,15 @@ nsresult nsPluginInstancePeerImpl::Initialize(nsIPluginInstanceOwner *aOwner, return NS_OK; } +nsresult nsPluginInstancePeerImpl::SetOwner(nsIPluginInstanceOwner *aOwner) +{ + // do not add refs to these objects to prevent circular references + mOwner = aOwner; + aOwner->GetInstance(mInstance); + NS_IF_RELEASE(mInstance); + return NS_OK; +} + nsresult nsPluginInstancePeerImpl::GetOwner(nsIPluginInstanceOwner *&aOwner) { aOwner = mOwner; diff --git a/mozilla/modules/plugin/base/src/nsPluginInstancePeer.h b/mozilla/modules/plugin/base/src/nsPluginInstancePeer.h index 8f8f11fbc06..13c2627fbf9 100644 --- a/mozilla/modules/plugin/base/src/nsPluginInstancePeer.h +++ b/mozilla/modules/plugin/base/src/nsPluginInstancePeer.h @@ -148,9 +148,11 @@ public: //locals - nsresult Initialize(nsIPluginInstanceOwner *aInstance, + nsresult Initialize(nsIPluginInstanceOwner *aOwner, const nsMIMEType aMimeType); + nsresult SetOwner(nsIPluginInstanceOwner *aOwner); + nsresult GetOwner(nsIPluginInstanceOwner *&aOwner); private: diff --git a/mozilla/modules/plugin/base/src/nsPluginsDirWin.cpp b/mozilla/modules/plugin/base/src/nsPluginsDirWin.cpp index efe3be1ab93..220f0fba77f 100644 --- a/mozilla/modules/plugin/base/src/nsPluginsDirWin.cpp +++ b/mozilla/modules/plugin/base/src/nsPluginsDirWin.cpp @@ -68,6 +68,10 @@ static char* GetKeyValue(char* verbuf, char* key) static PRUint32 CalculateVariantCount(char* mimeTypes) { PRUint32 variants = 1; + + if(mimeTypes == NULL) + return 0; + char* index = mimeTypes; while (*index) { @@ -85,6 +89,9 @@ static char** MakeStringArray(PRUint32 variants, char* data) char* index = data; PRUint32 count = 0; + if(variants == 0) + return NULL; + buffer = (char **)PR_Malloc(variants * sizeof(char *)); if(!buffer) return NULL; diff --git a/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp b/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp index 6f7d6925c29..74347ba6be2 100644 --- a/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp +++ b/mozilla/modules/plugin/nglsrc/ns4xPlugin.cpp @@ -518,23 +518,23 @@ ns4xPlugin::_write(NPP npp, NPStream *pstream, int32 len, void *buffer) if(!npp) return -1; - ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; - NS_ASSERTION(wrapper != NULL, "null stream"); + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; + NS_ASSERTION(wrapper != NULL, "null stream"); - if (wrapper == NULL) - return -1; + if (wrapper == NULL) + return -1; - nsIOutputStream* stream; - wrapper->GetStream(stream); + nsIOutputStream* stream; + wrapper->GetStream(stream); + + PRUint32 count = 0; + nsresult rv = stream->Write((char *)buffer, len, &count); + NS_RELEASE(stream); - PRUint32 count = 0; - nsresult rv = stream->Write((char *)buffer, len, &count); - NS_RELEASE(stream); + if(rv != NS_OK) + return -1; - if(rv != NS_OK) - return -1; - - return (int32)count; + return (int32)count; } NPError NP_EXPORT @@ -556,17 +556,17 @@ ns4xPlugin::_destroystream(NPP npp, NPStream *pstream, NPError reason) return NPERR_NO_ERROR; } - ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; + ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) pstream->ndata; - NS_ASSERTION(wrapper != NULL, "null wrapper"); + NS_ASSERTION(wrapper != NULL, "null wrapper"); - if (wrapper == NULL) - return NPERR_INVALID_PARAM; + if (wrapper == NULL) + return NPERR_INVALID_PARAM; - // This will release the wrapped nsIOutputStream. - delete wrapper; + // This will release the wrapped nsIOutputStream. + delete wrapper; - return NPERR_NO_ERROR; + return NPERR_NO_ERROR; } void NP_EXPORT @@ -704,27 +704,51 @@ ns4xPlugin::_getvalue(NPP npp, NPNVariable variable, void *result) if(!npp) return NPERR_INVALID_INSTANCE_ERROR; - nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; + switch(variable) + { +#ifdef XP_UNIX + case NPNVxDisplay : return NPERR_GENERIC_ERROR; - NS_ASSERTION(inst != NULL, "null instance"); + case NPNVxtAppContext : return NPERR_GENERIC_ERROR; +#endif - if (inst == NULL) - return NPERR_INVALID_INSTANCE_ERROR; +#ifdef XP_PC + case NPNVnetscapeWindow : return NPERR_GENERIC_ERROR; +#endif - nsIPluginInstancePeer *peer; + case NPNVjavascriptEnabledBool : *(NPBool*)result = TRUE; return NPERR_NO_ERROR; - if (NS_OK == inst->GetPeer(&peer)) - { - nsresult rv; + case NPNVasdEnabledBool : *(NPBool*)result = FALSE; return NPERR_NO_ERROR; - // XXX Note that for backwards compatibility, the old NPNVariables - // map correctly to NPPluginManagerVariables. - rv = peer->GetValue((nsPluginInstancePeerVariable)variable, result); - NS_RELEASE(peer); - return rv; - } - else - return NPERR_GENERIC_ERROR; + case NPNVisOfflineBool : *(NPBool*)result = FALSE; return NPERR_NO_ERROR; + + default : return NPERR_GENERIC_ERROR; + + } + +#if 0 + nsIPluginInstance *inst = (nsIPluginInstance *) npp->ndata; + + NS_ASSERTION(inst != NULL, "null instance"); + + if (inst == NULL) + return NPERR_INVALID_INSTANCE_ERROR; + + nsIPluginInstancePeer *peer; + + if (NS_OK == inst->GetPeer(&peer)) + { + nsresult rv; + + // XXX Note that for backwards compatibility, the old NPNVariables + // map correctly to NPPluginManagerVariables. + rv = peer->GetValue((nsPluginInstancePeerVariable)variable, result); + NS_RELEASE(peer); + return rv; + } + else + return NPERR_GENERIC_ERROR; +#endif } NPError NP_EXPORT @@ -818,7 +842,6 @@ ns4xPlugin::_memalloc (uint32 size) java_lang_Class* NP_EXPORT ns4xPlugin::_getJavaClass(void* handle) { - // Is this just a generic call into the Java VM? return NULL; } diff --git a/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp b/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp index bca13548f3b..5794d9c41b4 100644 --- a/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp +++ b/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.cpp @@ -283,6 +283,7 @@ ns4xPluginInstance :: ns4xPluginInstance(NPPluginFuncs* callbacks) mWindowless = PR_FALSE; mTransparent = PR_FALSE; + mStarted = PR_FALSE; } @@ -328,51 +329,7 @@ NS_IMETHODIMP ns4xPluginInstance :: QueryInterface(const nsIID& iid, void** inst NS_IMETHODIMP ns4xPluginInstance :: Initialize(nsIPluginInstancePeer* peer) { - PRUint16 count = 0; - const char* const* names = nsnull; - const char* const* values = nsnull; - nsresult rv; - NPError error; - nsIPluginTagInfo* taginfo; - - NS_ASSERTION(peer != NULL, "null peer"); - - fPeer = peer; - NS_ADDREF(fPeer); - - rv = fPeer->QueryInterface(kIPluginTagInfoIID, (void **)&taginfo); - - if (NS_OK == rv) - { - taginfo->GetAttributes(count, names, values); - NS_IF_RELEASE(taginfo); - } - - if (fCallbacks->newp == NULL) - return NS_ERROR_FAILURE; // XXX right error? - - // XXX Note that the NPPluginType_* enums were crafted to be - // backward compatible... - - nsPluginMode mode; - nsMIMEType mimetype; - - fPeer->GetMode(&mode); - fPeer->GetMIMEType(&mimetype); - - error = CallNPP_NewProc(fCallbacks->newp, - (char *)mimetype, - &fNPP, - (PRUint16)mode, - count, - (char**)names, - (char**)values, - NULL); // saved data - - if(error != NPERR_NO_ERROR) - rv = NS_ERROR_FAILURE; - - return rv; + return InitializePlugin(peer); } NS_IMETHODIMP ns4xPluginInstance :: GetPeer(nsIPluginInstancePeer* *resultingPeer) @@ -385,36 +342,89 @@ NS_IMETHODIMP ns4xPluginInstance :: GetPeer(nsIPluginInstancePeer* *resultingPee NS_IMETHODIMP ns4xPluginInstance::Start(void) { - // XXX At some point, we maybe should implement start and stop to - // load/unload the 4.x plugin, just in case there are some plugins - // that rely on that behavior... -printf("instance start called\n"); + printf("instance start called\n"); + if(mStarted) return NS_OK; + else + return InitializePlugin(fPeer); } NS_IMETHODIMP ns4xPluginInstance::Stop(void) { -printf("instance stop called\n"); - return NS_OK; + NPError error; + + printf("instance stop/destroy called\n"); + if (fCallbacks->destroy == NULL) + return NS_ERROR_FAILURE; // XXX right error? + + NPSavedData *sdata; + + error = (nsresult)CallNPP_DestroyProc(fCallbacks->destroy, + &fNPP, &sdata); // saved data + + mStarted = PR_FALSE; + if(error != NPERR_NO_ERROR) + return NS_ERROR_FAILURE; + else + return NS_OK; +} + +nsresult ns4xPluginInstance::InitializePlugin(nsIPluginInstancePeer* peer) +{ + PRUint16 count = 0; + const char* const* names = nsnull; + const char* const* values = nsnull; + nsresult rv; + NPError error; + nsIPluginTagInfo* taginfo; + + NS_ASSERTION(peer != NULL, "null peer"); + + fPeer = peer; + NS_ADDREF(fPeer); + + rv = fPeer->QueryInterface(kIPluginTagInfoIID, (void **)&taginfo); + + if (NS_OK == rv) + { + taginfo->GetAttributes(count, names, values); + NS_IF_RELEASE(taginfo); + } + + if (fCallbacks->newp == NULL) + return NS_ERROR_FAILURE; // XXX right error? + + // XXX Note that the NPPluginType_* enums were crafted to be + // backward compatible... + + nsPluginMode mode; + nsMIMEType mimetype; + + fPeer->GetMode(&mode); + fPeer->GetMIMEType(&mimetype); + + error = CallNPP_NewProc(fCallbacks->newp, + (char *)mimetype, + &fNPP, + (PRUint16)mode, + count, + (char**)names, + (char**)values, + NULL); // saved data + + if(error != NPERR_NO_ERROR) + rv = NS_ERROR_FAILURE; + + mStarted = PR_TRUE; + + return rv; } NS_IMETHODIMP ns4xPluginInstance::Destroy(void) { - NPError error; - -printf("instance destroy called\n"); - if (fCallbacks->destroy == NULL) - return NS_ERROR_FAILURE; // XXX right error? - - NPSavedData *sdata; - - error = (nsresult)CallNPP_DestroyProc(fCallbacks->destroy, - &fNPP, &sdata); // saved data - - if(error != NPERR_NO_ERROR) - return NS_ERROR_FAILURE; - else - return NS_OK; + printf("instance destroy called\n"); + // destruction is handled in the Stop call + return NS_OK; } NS_IMETHODIMP ns4xPluginInstance::SetWindow(nsPluginWindow* window) diff --git a/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.h b/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.h index d755b61033e..e9404bacaca 100644 --- a/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.h +++ b/mozilla/modules/plugin/nglsrc/ns4xPluginInstance.h @@ -112,6 +112,8 @@ public: protected: + nsresult InitializePlugin(nsIPluginInstancePeer* peer); + /** * The plugin instance peer for this instance. */ @@ -135,6 +137,7 @@ protected: PRBool mWindowless; PRBool mTransparent; + PRBool mStarted; }; diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp index a5213b07621..434baea67fc 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.cpp @@ -1002,6 +1002,8 @@ nsPluginHostImpl::nsPluginHostImpl(nsIServiceManager *serviceMgr) NS_INIT_REFCNT(); mPluginsLoaded = PR_FALSE; mServiceMgr = serviceMgr; + mNumActivePlugins = 0; + mOldestActivePlugin = 0; } nsPluginHostImpl::~nsPluginHostImpl() @@ -1342,10 +1344,18 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, nsresult rv; nsIPluginInstance *instance = nsnull; + if(FindStoppedPluginForURL(aURL, aOwner) == NS_OK) + { + aOwner->GetInstance(instance); + if(!aMimeType || PL_strcasecmp(aMimeType, "application/x-java-vm")) + rv = NewEmbededPluginStream(aURL, nsnull, instance); + return NS_OK; + } + rv = SetUpPluginInstance(aMimeType, aURL, aOwner); - + if(rv == NS_OK) - rv = aOwner->GetInstance(instance); + rv = aOwner->GetInstance(instance); // if we have a failure error, it means we found a plugin for the mimetype, // but we had a problem with the entry point @@ -1378,7 +1388,7 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateEmbededPlugin(const char *aMimeType, // don't make an initial steam if it's a java applet if(!aMimeType || PL_strcasecmp(aMimeType, "application/x-java-vm")) - rv = NewEmbededPluginStream(aURL, nsnull, instance); + rv = NewEmbededPluginStream(aURL, nsnull, instance); NS_RELEASE(instance); } @@ -1403,7 +1413,16 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateFullPagePlugin(const char *aMimeType, if (rv != NS_OK) url = nsnull; - + + if(FindStoppedPluginForURL(url, aOwner) == NS_OK) + { + nsIPluginInstance* instance; + aOwner->GetInstance(instance); + if(!aMimeType || PL_strcasecmp(aMimeType, "application/x-java-vm")) + rv = NewFullPagePluginStream(aStreamListener, instance); + return NS_OK; + } + rv = SetUpPluginInstance(aMimeType, url, aOwner); NS_IF_RELEASE(url); @@ -1433,6 +1452,72 @@ NS_IMETHODIMP nsPluginHostImpl::InstantiateFullPagePlugin(const char *aMimeType, return rv; } +nsresult nsPluginHostImpl::FindStoppedPluginForURL(nsIURL* aURL, nsIPluginInstanceOwner *aOwner) +{ + PRUint32 i; + const char* url; + (void)aURL->GetSpec(&url); + + for(i=0; iGetWindow(window); + + aOwner->SetInstance(instance); + + // we have to reset the owner and instance in the plugin instance peer + //instance->GetPeer(&peer); + ((nsPluginInstancePeerImpl*)mActivePluginList[i].mPeer)->SetOwner(aOwner); + + aOwner->CreateWidget(); + instance->SetWindow(window); + instance->Start(); + + return NS_OK; + } + } + return NS_ERROR_FAILURE; +} + +void nsPluginHostImpl::AddInstanceToActiveList(nsIPluginInstance* aInstance, nsIURL* aURL) +{ + const char* url; + (void)aURL->GetSpec(&url); + + if(mNumActivePlugins < MAX_ACTIVE_PLUGINS) + { + mActivePluginList[mNumActivePlugins].mURL = PL_strdup(url); + mActivePluginList[mNumActivePlugins].mInstance = aInstance; + + aInstance->GetPeer(&(mActivePluginList[mNumActivePlugins].mPeer)); + ++mNumActivePlugins; + } + else + { + // XXX - TODO: we need to make sure that this plugin is currently not active + + // destroy the oldest plugin on the list + mActivePluginList[mOldestActivePlugin].mInstance->Destroy(); + NS_RELEASE(mActivePluginList[mOldestActivePlugin].mInstance); + NS_RELEASE(mActivePluginList[mOldestActivePlugin].mPeer); + PL_strfree(mActivePluginList[mOldestActivePlugin].mURL); + + // replace it with the new one + mActivePluginList[mOldestActivePlugin].mURL = PL_strdup(url); + mActivePluginList[mOldestActivePlugin].mInstance = aInstance; + aInstance->GetPeer(&(mActivePluginList[mOldestActivePlugin].mPeer)); + + ++mOldestActivePlugin; + if(mOldestActivePlugin == MAX_ACTIVE_PLUGINS) + mOldestActivePlugin = 0; + + } +} + NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, nsIURL *aURL, nsIPluginInstanceOwner *aOwner) @@ -1461,10 +1546,12 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, mimetype = aMimeType; - if (GetPluginFactory(mimetype, &plugin) == NS_OK) { + if(GetPluginFactory(mimetype, &plugin) == NS_OK) + { // instantiate a plugin. nsIPluginInstance* instance = NULL; - if (plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance) == NS_OK) { + if(plugin->CreateInstance(NULL, kIPluginInstanceIID, (void **)&instance) == NS_OK) + { aOwner->SetInstance(instance); nsPluginInstancePeerImpl *peer = new nsPluginInstancePeerImpl(); @@ -1474,10 +1561,12 @@ NS_IMETHODIMP nsPluginHostImpl::SetUpPluginInstance(const char *aMimeType, // tell the plugin instance to initialize itself and pass in the peer. instance->Initialize(peer); - NS_RELEASE(instance); + + AddInstanceToActiveList(instance, aURL); + //NS_RELEASE(instance); result = NS_OK; - } - NS_RELEASE(plugin); + } + NS_RELEASE(plugin); } return result; } @@ -1750,13 +1839,13 @@ NS_IMETHODIMP nsPluginHostImpl::GetPluginFactory(const char *aMimeType, nsIPlugi // need to get the plugin factory from this plugin. nsFactoryProc nsGetFactory = nsnull; nsGetFactory = (nsFactoryProc) PR_FindSymbol(pluginTag->mLibrary, "NSGetFactory"); - if (nsGetFactory != nsnull) + if(nsGetFactory != nsnull) { - rv = nsGetFactory(mServiceMgr, kPluginCID, nsnull, nsnull, // XXX fix ClassName/ProgID - (nsIFactory**)&pluginTag->mEntryPoint); - plugin = pluginTag->mEntryPoint; - if (plugin != NULL) - plugin->Initialize(); + rv = nsGetFactory(mServiceMgr, kPluginCID, nsnull, nsnull, // XXX fix ClassName/ProgID + (nsIFactory**)&pluginTag->mEntryPoint); + plugin = pluginTag->mEntryPoint; + if (plugin != NULL) + plugin->Initialize(); } else { @@ -1764,6 +1853,8 @@ NS_IMETHODIMP nsPluginHostImpl::GetPluginFactory(const char *aMimeType, nsIPlugi (nsIPlugin **)&pluginTag->mEntryPoint, mServiceMgr); plugin = pluginTag->mEntryPoint; + pluginTag->mFlags |= NS_PLUGIN_FLAG_OLDSCHOOL; + // no need to initialize, already done by CreatePlugin() } } @@ -1826,57 +1917,6 @@ NS_IMETHODIMP nsPluginHostImpl::LoadPlugins() return NS_ERROR_FAILURE; } -// private methods - -PRLibrary* nsPluginHostImpl::LoadPluginLibrary(const nsFileSpec &pluginSpec) -{ - PRLibrary* plugin = NULL; - -#ifdef XP_PC - plugin = PR_LoadLibrary((const char*)pluginSpec); -#endif - -#ifdef XP_MAC - char* pluginName = pluginSpec.GetLeafName(); - if (pluginName != NULL) { - plugin = PR_LoadLibrary(pluginName); - delete[] pluginName; - } -#endif - - return plugin; -} - - -PRLibrary* nsPluginHostImpl::LoadPluginLibrary(const char* pluginPath, const char* path) -{ -#ifdef XP_PC - BOOL restoreOrigDir = FALSE; - char aOrigDir[MAX_PATH + 1]; - DWORD dwCheck = ::GetCurrentDirectory(sizeof(aOrigDir), aOrigDir); - PR_ASSERT(dwCheck <= MAX_PATH + 1); - - if (dwCheck <= MAX_PATH + 1) - { - restoreOrigDir = ::SetCurrentDirectory(pluginPath); - PR_ASSERT(restoreOrigDir); - } - - PRLibrary* plugin = PR_LoadLibrary(path); - - if (restoreOrigDir) - { - BOOL bCheck = ::SetCurrentDirectory(aOrigDir); - PR_ASSERT(bCheck); - } - - return plugin; -#else - return NULL; -#endif -} - - /* Called by GetURL and PostURL */ NS_IMETHODIMP nsPluginHostImpl::NewPluginURLStream(const nsString& aURL, diff --git a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h index 810473339b3..e68beff6f9b 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h +++ b/mozilla/modules/plugin/nglsrc/nsPluginHostImpl.h @@ -54,6 +54,15 @@ public: PRUint32 mFlags; }; +#define MAX_ACTIVE_PLUGINS 10 + +typedef struct nsActivePlugin +{ + char* mURL; + nsIPluginInstancePeer* mPeer; + nsIPluginInstance* mInstance; +} nsActivePlugin; + #define NS_PLUGIN_FLAG_ENABLED 0x0001 //is this plugin enabled? #define NS_PLUGIN_FLAG_OLDSCHOOL 0x0002 //is this a pre-xpcom plugin? @@ -224,17 +233,23 @@ private: nsresult NewFullPagePluginStream(nsIStreamListener *&aStreamListener, nsIPluginInstance *aInstance); - PRLibrary* LoadPluginLibrary(const nsFileSpec &pluginSpec); - - PRLibrary* LoadPluginLibrary(const char* pluginPath, const char* path); - nsresult FindPluginEnabledForType(const char* aMimeType, nsPluginTag* &aPlugin); + nsresult + FindStoppedPluginForURL(nsIURL* aURL, nsIPluginInstanceOwner *aOwner); + + void + AddInstanceToActiveList(nsIPluginInstance* aInstance, nsIURL* aURL); + char *mPluginPath; nsPluginTag *mPlugins; PRBool mPluginsLoaded; nsIServiceManager *mServiceMgr; + + PRUint32 mNumActivePlugins; + PRUint32 mOldestActivePlugin; + nsActivePlugin mActivePluginList[MAX_ACTIVE_PLUGINS]; }; #endif diff --git a/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.cpp b/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.cpp index 399a98635f5..207a3f5db2f 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.cpp +++ b/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.cpp @@ -827,6 +827,15 @@ nsresult nsPluginInstancePeerImpl::Initialize(nsIPluginInstanceOwner *aOwner, return NS_OK; } +nsresult nsPluginInstancePeerImpl::SetOwner(nsIPluginInstanceOwner *aOwner) +{ + // do not add refs to these objects to prevent circular references + mOwner = aOwner; + aOwner->GetInstance(mInstance); + NS_IF_RELEASE(mInstance); + return NS_OK; +} + nsresult nsPluginInstancePeerImpl::GetOwner(nsIPluginInstanceOwner *&aOwner) { aOwner = mOwner; diff --git a/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.h b/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.h index 8f8f11fbc06..13c2627fbf9 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.h +++ b/mozilla/modules/plugin/nglsrc/nsPluginInstancePeer.h @@ -148,9 +148,11 @@ public: //locals - nsresult Initialize(nsIPluginInstanceOwner *aInstance, + nsresult Initialize(nsIPluginInstanceOwner *aOwner, const nsMIMEType aMimeType); + nsresult SetOwner(nsIPluginInstanceOwner *aOwner); + nsresult GetOwner(nsIPluginInstanceOwner *&aOwner); private: diff --git a/mozilla/modules/plugin/nglsrc/nsPluginsDirWin.cpp b/mozilla/modules/plugin/nglsrc/nsPluginsDirWin.cpp index efe3be1ab93..220f0fba77f 100644 --- a/mozilla/modules/plugin/nglsrc/nsPluginsDirWin.cpp +++ b/mozilla/modules/plugin/nglsrc/nsPluginsDirWin.cpp @@ -68,6 +68,10 @@ static char* GetKeyValue(char* verbuf, char* key) static PRUint32 CalculateVariantCount(char* mimeTypes) { PRUint32 variants = 1; + + if(mimeTypes == NULL) + return 0; + char* index = mimeTypes; while (*index) { @@ -85,6 +89,9 @@ static char** MakeStringArray(PRUint32 variants, char* data) char* index = data; PRUint32 count = 0; + if(variants == 0) + return NULL; + buffer = (char **)PR_Malloc(variants * sizeof(char *)); if(!buffer) return NULL;