Added support for Start/Stop Applet/Plugin lifetimes.

git-svn-id: svn://10.0.0.236/trunk@30775 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
amusil%netscape.com
1999-05-07 22:06:47 +00:00
parent 39540ee53b
commit 1da8f68a76
16 changed files with 566 additions and 348 deletions

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
};

View File

@@ -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; i<mNumActivePlugins; i++)
{
if(!PL_strcmp(url, mActivePluginList[i].mURL))
{
nsIPluginInstance* instance = mActivePluginList[i].mInstance;
nsIPluginInstancePeer* peer;
nsPluginWindow *window = nsnull;
aOwner->GetWindow(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,

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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;

View File

@@ -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;
}

View File

@@ -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)

View File

@@ -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;
};

View File

@@ -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; i<mNumActivePlugins; i++)
{
if(!PL_strcmp(url, mActivePluginList[i].mURL))
{
nsIPluginInstance* instance = mActivePluginList[i].mInstance;
nsIPluginInstancePeer* peer;
nsPluginWindow *window = nsnull;
aOwner->GetWindow(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,

View File

@@ -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

View File

@@ -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;

View File

@@ -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:

View File

@@ -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;