Get rid of nsPluginInstanceTagList. Make this code easier to deal with and less error-prone. b=535643 r=jst

This commit is contained in:
Josh Aas 2010-01-26 20:30:58 -05:00
parent 8c4dcf819d
commit e348c30e79
5 changed files with 257 additions and 387 deletions

View File

@ -1041,7 +1041,10 @@ _geturl(NPP npp, const char* relativeURL, const char* target)
(strncmp(relativeURL, "ftp:", 4) != 0)) {
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *) npp->ndata;
const char *name = nsPluginHost::GetPluginName(inst);
const char *name;
nsRefPtr<nsPluginHost> host = dont_AddRef(nsPluginHost::GetInst());
host->GetPluginName(inst, &name);
if (name && strstr(name, "Adobe") && strstr(name, "Acrobat")) {
return NPERR_NO_ERROR;

View File

@ -151,6 +151,7 @@
#include "nsIContentPolicy.h"
#include "nsContentPolicyUtils.h"
#include "nsContentErrors.h"
#include "mozilla/TimeStamp.h"
#if defined(XP_WIN)
#include "windows.h"
@ -161,6 +162,8 @@
#include <gdk/gdkx.h> // for GDK_DISPLAY()
#endif
using mozilla::TimeStamp;
// Null out a strong ref to a linked list iteratively to avoid
// exhausting the stack (bug 486349).
#define NS_ITERATIVE_UNREF_LIST(type_, list_, mNext_) \
@ -226,8 +229,6 @@ PRLogModuleInfo* nsPluginLogging::gPluginLog = nsnull;
#define MAGIC_REQUEST_CONTEXT 0x01020304
static nsPluginInstanceTagList *gActivePluginList;
#ifdef CALL_SAFETY_ON
PRBool gSkipPluginSafeCalls = PR_FALSE;
#endif
@ -453,8 +454,7 @@ public:
nsresult InitializeEmbedded(nsIURI *aURL,
nsIPluginInstance* aInstance,
nsIPluginInstanceOwner *aOwner = nsnull,
nsIPluginHost *aHost = nsnull);
nsIPluginInstanceOwner *aOwner = nsnull);
nsresult InitializeFullPage(nsIPluginInstance *aInstance);
@ -489,7 +489,6 @@ private:
char *mMIMEType;
PRUint32 mLength;
PRInt32 mStreamType;
nsIPluginHost *mHost;
// local cached file, we save the content into local cache if browser cache is not available,
// or plugin asks stream as file and it expects file extension until bug 90558 got fixed
@ -822,7 +821,6 @@ nsPluginStreamListenerPeer::nsPluginStreamListenerPeer()
mOwner = nsnull;
mInstance = nsnull;
mPStreamListener = nsnull;
mHost = nsnull;
mStreamType = NP_NORMAL;
mStartBinding = PR_FALSE;
mAbort = PR_FALSE;
@ -848,7 +846,6 @@ nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer()
NS_IF_RELEASE(mOwner);
NS_IF_RELEASE(mInstance);
NS_IF_RELEASE(mPStreamListener);
NS_IF_RELEASE(mHost);
// close FD of mFileCacheOutputStream if it's still open
// or we won't be able to remove the cache file
@ -929,12 +926,11 @@ nsresult nsPluginStreamListenerPeer::Initialize(nsIURI *aURL,
/* Called by NewEmbeddedPluginStream() - if this is called, we weren't
* able to load the plugin, so we need to load it later once we figure
* out the mimetype. In order to load it later, we need the plugin
* host and instance owner.
* instance owner.
*/
nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL,
nsIPluginInstance* aInstance,
nsIPluginInstanceOwner *aOwner,
nsIPluginHost *aHost)
nsIPluginInstanceOwner *aOwner)
{
#ifdef PLUGIN_LOGGING
nsCAutoString urlSpec;
@ -956,9 +952,6 @@ nsresult nsPluginStreamListenerPeer::InitializeEmbedded(nsIURI *aURL,
} else {
mOwner = aOwner;
NS_IF_ADDREF(mOwner);
mHost = aHost;
NS_IF_ADDREF(mHost);
}
mPluginStreamInfo = new nsPluginStreamInfo();
@ -1011,33 +1004,33 @@ nsresult
nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
{
nsresult rv = NS_OK;
// lets try to reused a file if we already have in the local plugin cache
// we loop through all of active plugins
// and call |nsPluginStreamInfo::UseExistingPluginCacheFile()| on opened stream
// will return RP_TRUE if file exisrs
// and some conditions are matched, in this case that file will be use
// in |::OnFileAvailable()| calls w/o rewriting the file again.
// The file will be deleted in |nsPluginStreamListenerPeer::~nsPluginStreamListenerPeer|
PRBool useExistingCacheFile = PR_FALSE;
nsPluginInstanceTag *pActivePlugins = gActivePluginList->mFirst;
while (pActivePlugins && pActivePlugins->mStreams && !useExistingCacheFile) {
// most recent streams are at the end of list
PRInt32 cnt;
pActivePlugins->mStreams->Count((PRUint32*)&cnt);
while (--cnt >= 0 && !useExistingCacheFile) {
nsPluginStreamListenerPeer *lp =
reinterpret_cast<nsPluginStreamListenerPeer *>(pActivePlugins->mStreams->ElementAt(cnt));
if (lp) {
if (lp->mLocalCachedFile &&
lp->mPluginStreamInfo &&
(useExistingCacheFile =
lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo))) {
NS_ADDREF(mLocalCachedFile = lp->mLocalCachedFile);
nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst());
nsTArray< nsAutoPtr<nsPluginInstanceTag> > *instanceTags = pluginHost->InstanceTagArray();
for (PRUint32 i = 0; i < instanceTags->Length(); i++) {
nsPluginInstanceTag *instanceTag = (*instanceTags)[i];
if (instanceTag->mStreams) {
// most recent streams are at the end of list
PRInt32 cnt;
instanceTag->mStreams->Count((PRUint32*)&cnt);
while (--cnt >= 0) {
nsPluginStreamListenerPeer *lp =
reinterpret_cast<nsPluginStreamListenerPeer*>(instanceTag->mStreams->ElementAt(cnt));
if (lp && lp->mLocalCachedFile && lp->mPluginStreamInfo) {
useExistingCacheFile = lp->mPluginStreamInfo->UseExistingPluginCacheFile(mPluginStreamInfo);
if (useExistingCacheFile) {
mLocalCachedFile = lp->mLocalCachedFile;
NS_ADDREF(mLocalCachedFile);
break;
}
NS_RELEASE(lp);
}
NS_RELEASE(lp);
}
if (useExistingCacheFile)
break;
}
pActivePlugins = pActivePlugins->mNext;
}
if (!useExistingCacheFile) {
@ -1088,15 +1081,15 @@ nsPluginStreamListenerPeer::SetupPluginCacheFile(nsIChannel* channel)
// add this listenerPeer to list of stream peers for this instance
// it'll delay release of listenerPeer until nsPluginInstanceTag::~nsPluginInstanceTag
// and the temp file is going to stay alive until then
pActivePlugins = gActivePluginList->find(mInstance);
if (pActivePlugins) {
if (!pActivePlugins->mStreams &&
(NS_FAILED(rv = NS_NewISupportsArray(getter_AddRefs(pActivePlugins->mStreams))))) {
nsPluginInstanceTag *instanceTag = pluginHost->FindInstanceTag(mInstance);
if (instanceTag) {
if (!instanceTag->mStreams &&
(NS_FAILED(rv = NS_NewISupportsArray(getter_AddRefs(instanceTag->mStreams))))) {
return rv;
}
nsISupports* supports = static_cast<nsISupports*>((static_cast<nsIStreamListener*>(this)));
pActivePlugins->mStreams->AppendElement(supports);
instanceTag->mStreams->AppendElement(supports);
}
return rv;
@ -1225,14 +1218,16 @@ nsPluginStreamListenerPeer::OnStartRequest(nsIRequest *request,
if (!mInstance && mOwner && !aContentType.IsEmpty()) {
mOwner->GetInstance(mInstance);
mOwner->GetWindow(window);
if (!mInstance && mHost && window) {
if (!mInstance && window) {
nsRefPtr<nsPluginHost> pluginHost = dont_AddRef(nsPluginHost::GetInst());
// determine if we need to try embedded again. FullPage takes a different code path
PRInt32 mode;
mOwner->GetMode(&mode);
if (mode == NP_EMBED)
rv = mHost->InstantiateEmbeddedPlugin(aContentType.get(), aURL, mOwner);
rv = pluginHost->InstantiateEmbeddedPlugin(aContentType.get(), aURL, mOwner);
else
rv = mHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner);
rv = pluginHost->SetUpPluginInstance(aContentType.get(), aURL, mOwner);
if (NS_OK == rv) {
// GetInstance() adds a ref
@ -1685,8 +1680,6 @@ nsPluginHost::nsPluginHost()
// No need to initialize members to nsnull, PR_FALSE etc because this class
// has a zeroing operator new.
{
gActivePluginList = &mPluginInstanceTagList;
// check to see if pref is set at startup to let plugins take over in
// full page mode for certain image mime types that we handle internally
mPrefService = do_GetService(NS_PREFSERVICE_CONTRACTID);
@ -1771,32 +1764,17 @@ nsPluginHost::GetInst()
return sInst;
}
// static
const char *
nsPluginHost::GetPluginName(nsIPluginInstance *aPluginInstance)
{
nsPluginInstanceTag *plugin =
gActivePluginList ? gActivePluginList->find(aPluginInstance) : nsnull;
if (plugin && plugin->mPluginTag)
return plugin->mPluginTag->mName.get();
return nsnull;
}
PRBool nsPluginHost::IsRunningPlugin(nsPluginTag * plugin)
{
if (!plugin)
return PR_FALSE;
// we can check for mLibrary to be non-zero and then ask nsIPluginInstance
// in nsPluginInstanceTagList to see if plugin with matching mime type is not stopped
if (!plugin->mLibrary)
return PR_FALSE;
for (int i = 0; i < plugin->mVariants; i++) {
nsPluginInstanceTag * p = mPluginInstanceTagList.find(plugin->mMimeTypeArray[i]);
if (p && p->mInstance->IsRunning())
nsPluginInstanceTag *instanceTag = FindInstanceTag(plugin->mMimeTypeArray[i]);
if (instanceTag && instanceTag->mInstance->IsRunning())
return PR_TRUE;
}
@ -1807,7 +1785,7 @@ nsresult nsPluginHost::ReloadPlugins(PRBool reloadPages)
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHost::ReloadPlugins Begin reloadPages=%d, active_instance_count=%d\n",
reloadPages, mPluginInstanceTagList.mCount));
reloadPages, mInstanceTags.Length()));
nsresult rv = NS_OK;
@ -1832,18 +1810,14 @@ nsresult nsPluginHost::ReloadPlugins(PRBool reloadPages)
return NS_ERROR_PLUGINS_PLUGINSNOTCHANGED;
nsCOMPtr<nsISupportsArray> instsToReload;
if (reloadPages) {
NS_NewISupportsArray(getter_AddRefs(instsToReload));
// Then stop any running plugin instances but hold on to the documents in the array
// We are going to need to restart the instances in these documents later
mPluginInstanceTagList.stopRunning(instsToReload, nsnull);
StopRunningInstances(instsToReload, nsnull);
}
// clean active plugin list
mPluginInstanceTagList.removeAllStopped();
// shutdown plugins and kill the list if there are no running plugins
nsRefPtr<nsPluginTag> prev;
nsRefPtr<nsPluginTag> next;
@ -1892,7 +1866,7 @@ nsresult nsPluginHost::ReloadPlugins(PRBool reloadPages)
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHost::ReloadPlugins End active_instance_count=%d\n",
mPluginInstanceTagList.mCount));
mInstanceTags.Length()));
return rv;
}
@ -2214,10 +2188,7 @@ NS_IMETHODIMP nsPluginHost::Destroy()
// we should call nsIPluginInstance::Stop and nsIPluginInstance::SetWindow
// for those plugins who want it
mPluginInstanceTagList.stopRunning(nsnull, nsnull);
// at this point nsIPlugin::Shutdown calls will be performed if needed
mPluginInstanceTagList.shutdown();
StopRunningInstances(nsnull, nsnull);
nsPluginTag *pluginTag;
for (pluginTag = mPlugins; pluginTag; pluginTag = pluginTag->mNext) {
@ -2259,6 +2230,29 @@ void nsPluginHost::UnloadUnusedLibraries()
mUnusedLibraries.Clear();
}
void nsPluginHost::OnPluginInstanceDestroyed(nsPluginTag* aPluginTag)
{
PRBool hasInstance = PR_FALSE;
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
if (mInstanceTags[i]->mPluginTag == aPluginTag) {
hasInstance = PR_TRUE;
break;
}
}
if (!hasInstance) {
nsresult rv;
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
if (NS_FAILED(rv))
return;
PRBool unloadPluginsASAP = PR_FALSE;
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
aPluginTag->TryUnloadPlugin();
}
}
nsresult
nsPluginHost::GetPluginTempDir(nsIFile **aDir)
{
@ -2607,7 +2601,7 @@ nsresult nsPluginHost::FindStoppedPluginForURL(nsIURI* aURL,
aURL->GetAsciiSpec(url);
nsPluginInstanceTag *instanceTag = mPluginInstanceTagList.findStopped(url.get());
nsPluginInstanceTag *instanceTag = FindStoppedInstanceTag(url.get());
if (instanceTag && !instanceTag->mInstance->IsRunning()) {
NPWindow* window = nsnull;
@ -2651,12 +2645,11 @@ nsresult nsPluginHost::AddInstanceToActiveList(nsCOMPtr<nsIPlugin> aPlugin,
NS_ASSERTION(pluginTag, "Plugin tag not found");
}
nsPluginInstanceTag * plugin = new nsPluginInstanceTag(pluginTag, aInstance, url.get(), aDefaultPlugin);
if (!plugin)
nsPluginInstanceTag *instanceTag = new nsPluginInstanceTag(pluginTag, aInstance, url.get(), aDefaultPlugin);
if (!instanceTag)
return NS_ERROR_OUT_OF_MEMORY;
mPluginInstanceTagList.add(plugin);
mInstanceTags.AppendElement(instanceTag);
return NS_OK;
}
@ -3918,8 +3911,7 @@ nsPluginHost::UpdatePluginInfo(nsPluginTag* aPluginTag)
nsCOMPtr<nsISupportsArray> instsToReload;
NS_NewISupportsArray(getter_AddRefs(instsToReload));
mPluginInstanceTagList.stopRunning(instsToReload, aPluginTag);
mPluginInstanceTagList.removeAllStopped();
StopRunningInstances(instsToReload, aPluginTag);
PRUint32 c;
if (instsToReload && NS_SUCCEEDED(instsToReload->Count(&c)) && c > 0) {
@ -4547,40 +4539,72 @@ nsPluginHost::StopPluginInstance(nsIPluginInstance* aInstance)
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("nsPluginHost::StopPluginInstance called instance=%p\n",aInstance));
nsPluginInstanceTag * plugin = mPluginInstanceTagList.find(aInstance);
aInstance->Stop();
if (plugin) {
nsPluginInstanceTag * instanceTag = FindInstanceTag(aInstance);
if (instanceTag) {
// if the plugin does not want to be 'cached' just remove it
PRBool doCache = PR_TRUE;
aInstance->ShouldCache(&doCache);
if (!doCache) {
PRLibrary * library = nsnull;
if (plugin->mPluginTag)
library = plugin->mPluginTag->mLibrary;
mPluginInstanceTagList.remove(plugin);
} else {
// if it is allowed to be cached simply stop it, but first we should check
// if we haven't exceeded the maximum allowed number of cached instances
if (doCache) {
// try to get the max cached plugins from a pref or use default
PRUint32 max_num;
PRUint32 cachedPluginLimit;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefService)
rv = mPrefService->GetIntPref(NS_PREF_MAX_NUM_CACHED_PLUGINS, (int*)&max_num);
rv = mPrefService->GetIntPref(NS_PREF_MAX_NUM_CACHED_PLUGINS, (int*)&cachedPluginLimit);
if (NS_FAILED(rv))
max_num = DEFAULT_NUMBER_OF_STOPPED_PLUGINS;
if (mPluginInstanceTagList.getStoppedCount() >= max_num) {
nsPluginInstanceTag * oldest = mPluginInstanceTagList.findOldestStopped();
if (oldest != nsnull)
mPluginInstanceTagList.remove(oldest);
cachedPluginLimit = DEFAULT_NUMBER_OF_STOPPED_PLUGINS;
if (StoppedInstanceTagCount() >= cachedPluginLimit) {
nsPluginInstanceTag * oldestInstanceTag = FindOldestStoppedInstanceTag();
if (oldestInstanceTag) {
nsPluginTag* pluginTag = oldestInstanceTag->mPluginTag;
mInstanceTags.RemoveElement(oldestInstanceTag);
OnPluginInstanceDestroyed(pluginTag);
}
}
} else {
nsPluginTag* pluginTag = instanceTag->mPluginTag;
mInstanceTags.RemoveElement(instanceTag);
OnPluginInstanceDestroyed(pluginTag);
}
}
return NS_OK;
}
nsPluginInstanceTag*
nsPluginHost::FindOldestStoppedInstanceTag()
{
nsPluginInstanceTag *oldestInstanceTag = nsnull;
TimeStamp oldestTime = TimeStamp::Now();
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
nsPluginInstanceTag *instanceTag = mInstanceTags[i];
if (instanceTag->mInstance->IsRunning())
continue;
TimeStamp time = instanceTag->mInstance->LastStopTime();
if (time < oldestTime) {
oldestTime = time;
oldestInstanceTag = instanceTag;
}
}
return oldestInstanceTag;
}
PRUint32
nsPluginHost::StoppedInstanceTagCount()
{
PRUint32 stoppedCount = 0;
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
nsPluginInstanceTag *instanceTag = mInstanceTags[i];
if (!instanceTag->mInstance->IsRunning())
stoppedCount++;
}
return stoppedCount;
}
nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURL,
nsIPluginInstanceOwner *aOwner,
nsIPluginInstance* aInstance,
@ -4603,7 +4627,7 @@ nsresult nsPluginHost::NewEmbeddedPluginStreamListener(nsIURI* aURL,
if (aInstance != nsnull)
rv = listener->InitializeEmbedded(aURL, aInstance);
else if (aOwner != nsnull)
rv = listener->InitializeEmbedded(aURL, nsnull, aOwner, this);
rv = listener->InitializeEmbedded(aURL, nsnull, aOwner);
else
rv = NS_ERROR_ILLEGAL_VALUE;
if (NS_SUCCEEDED(rv))
@ -4663,7 +4687,7 @@ nsresult nsPluginHost::NewFullPagePluginStream(nsIStreamListener *&aStreamListen
NS_ADDREF(listener);
// add peer to list of stream peers for this instance
nsPluginInstanceTag * p = mPluginInstanceTagList.find(aInstance);
nsPluginInstanceTag * p = FindInstanceTag(aInstance);
if (p) {
if (!p->mStreams && (NS_FAILED(rv = NS_NewISupportsArray(getter_AddRefs(p->mStreams)))))
return rv;
@ -4685,8 +4709,8 @@ NS_IMETHODIMP nsPluginHost::Observe(nsISupports *aSubject,
}
if (!nsCRT::strcmp(NS_PRIVATE_BROWSING_SWITCH_TOPIC, aTopic)) {
// inform all active plugins of changed private mode state
for (nsPluginInstanceTag* ap = mPluginInstanceTagList.mFirst; ap; ap = ap->mNext) {
nsNPAPIPluginInstance* pi = static_cast<nsNPAPIPluginInstance*>(ap->mInstance);
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
nsNPAPIPluginInstance* pi = static_cast<nsNPAPIPluginInstance*>(mInstanceTags[i]->mInstance);
pi->PrivateModeStateChanged();
}
}
@ -4748,7 +4772,7 @@ nsPluginHost::HandleBadPlugin(PRLibrary* aLibrary, nsIPluginInstance *aInstance)
// add plugin name to the message
nsCString pluginname;
nsPluginInstanceTag * p = mPluginInstanceTagList.find(aInstance);
nsPluginInstanceTag * p = FindInstanceTag(aInstance);
if (p) {
nsPluginTag * tag = p->mPluginTag;
if (tag) {
@ -5074,7 +5098,12 @@ NS_IMETHODIMP
nsPluginHost::GetPluginName(nsIPluginInstance *aPluginInstance,
const char** aPluginName)
{
*aPluginName = GetPluginName(aPluginInstance);
nsPluginInstanceTag *instanceTag = FindInstanceTag(aPluginInstance);
if (!instanceTag || !instanceTag->mPluginTag)
return NS_ERROR_FAILURE;
*aPluginName = instanceTag->mPluginTag->mName.get();
return NS_OK;
}
@ -5084,13 +5113,12 @@ nsPluginHost::GetPluginTagForInstance(nsIPluginInstance *aPluginInstance,
{
NS_ENSURE_ARG_POINTER(aPluginInstance);
NS_ENSURE_ARG_POINTER(aPluginTag);
nsPluginInstanceTag *plugin =
gActivePluginList ? gActivePluginList->find(aPluginInstance) : nsnull;
NS_ENSURE_TRUE(plugin && plugin->mPluginTag, NS_ERROR_FAILURE);
nsPluginInstanceTag *instanceTag = FindInstanceTag(aPluginInstance);
NS_ENSURE_TRUE(instanceTag && instanceTag->mPluginTag, NS_ERROR_FAILURE);
*aPluginTag = plugin->mPluginTag;
*aPluginTag = instanceTag->mPluginTag;
NS_ADDREF(*aPluginTag);
return NS_OK;
}
@ -5177,32 +5205,30 @@ NS_IMETHODIMP nsPluginHost::Notify(nsITimer* timer)
void
nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin)
{
nsPluginTag* plugin = FindTagForPlugin(aPlugin);
if (!plugin) {
nsPluginTag* pluginTag = FindTagForPlugin(aPlugin);
if (!pluginTag) {
NS_WARNING("nsPluginTag not found in nsPluginHost::PluginCrashed");
return;
}
// Invalidate each nsPluginInstanceTag for the crashed plugin
nsPluginInstanceTag** pinstancetag = &mPluginInstanceTagList.mFirst;
while (*pinstancetag) {
nsPluginInstanceTag* instancetag = *pinstancetag;
if (instancetag->mPluginTag == plugin) {
for (PRUint32 i = mInstanceTags.Length(); i > 0; i--) {
nsPluginInstanceTag* instanceTag = mInstanceTags[i - 1];
if (instanceTag->mPluginTag == pluginTag) {
// notify the content node (nsIObjectLoadingContent) that the plugin has crashed
nsCOMPtr<nsIDOMElement> domElement;
instancetag->mInstance->GetDOMElement(getter_AddRefs(domElement));
instanceTag->mInstance->GetDOMElement(getter_AddRefs(domElement));
nsCOMPtr<nsIObjectLoadingContent> objectContent(do_QueryInterface(domElement));
if (objectContent) {
objectContent->PluginCrashed();
}
instanceTag->mInstance->Stop();
instancetag->mInstance->Stop();
*pinstancetag = (*pinstancetag)->mNext;
delete instancetag;
}
else {
pinstancetag = &(*pinstancetag)->mNext;
nsPluginTag* pluginTag = instanceTag->mPluginTag;
mInstanceTags.RemoveElement(instanceTag);
OnPluginInstanceDestroyed(pluginTag);
}
}
@ -5210,10 +5236,95 @@ nsPluginHost::PluginCrashed(nsNPAPIPlugin* aPlugin)
// out nsPluginTag.mEntryPoint. The next time we try to create an
// instance of this plugin we reload it (launch a new plugin process).
plugin->mEntryPoint = nsnull;
pluginTag->mEntryPoint = nsnull;
}
#endif
nsPluginInstanceTag*
nsPluginHost::FindInstanceTag(nsIPluginInstance *instance)
{
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
nsPluginInstanceTag *instanceTag = mInstanceTags[i];
if (instanceTag->mInstance == instance)
return instanceTag;
}
return nsnull;
}
nsPluginInstanceTag*
nsPluginHost::FindInstanceTag(const char *mimetype)
{
PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
nsPluginInstanceTag* instanceTag = mInstanceTags[i];
// give it some special treatment for the default plugin first
// because we cannot tell the default plugin by asking instance for a mime type
if (defaultplugin && instanceTag->mDefaultPlugin)
return instanceTag;
if (!instanceTag->mInstance)
continue;
const char* mt;
nsresult rv = instanceTag->mInstance->GetMIMEType(&mt);
if (NS_FAILED(rv))
continue;
if (PL_strcasecmp(mt, mimetype) == 0)
return instanceTag;
}
return nsnull;
}
nsPluginInstanceTag*
nsPluginHost::FindStoppedInstanceTag(const char * url)
{
for (PRUint32 i = 0; i < mInstanceTags.Length(); i++) {
nsPluginInstanceTag *instanceTag = mInstanceTags[i];
if (!PL_strcmp(url, instanceTag->mURL) && !instanceTag->mInstance->IsRunning())
return instanceTag;
}
return nsnull;
}
void
nsPluginHost::StopRunningInstances(nsISupportsArray* aReloadDocs, nsPluginTag* aPluginTag)
{
for (PRInt32 i = mInstanceTags.Length(); i > 0; i--) {
nsPluginInstanceTag *instanceTag = mInstanceTags[i - 1];
nsNPAPIPluginInstance* instance = instanceTag->mInstance;
if (instance->IsRunning() && (!aPluginTag || aPluginTag == instanceTag->mPluginTag)) {
instance->SetWindow(nsnull);
instance->Stop();
// If we've been passed an array to return, lets collect all our documents,
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
// to kickstart our instances.
if (aReloadDocs) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
instance->GetOwner(getter_AddRefs(owner));
if (owner) {
nsCOMPtr<nsIDocument> doc;
owner->GetDocument(getter_AddRefs(doc));
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
aReloadDocs->AppendElement(doc);
}
}
nsPluginTag* pluginTag = instanceTag->mPluginTag;
mInstanceTags.RemoveElement(instanceTag);
OnPluginInstanceDestroyed(pluginTag);
}
}
}
nsTArray< nsAutoPtr<nsPluginInstanceTag> >*
nsPluginHost::InstanceTagArray()
{
return &mInstanceTags;
}
nsresult nsPluginStreamListenerPeer::ServeStreamAsFile(nsIRequest *request,
nsISupports* aContext)
{
@ -5455,10 +5566,7 @@ public:
PLUGIN_LOG(PLUGIN_LOG_NORMAL,
("Doing delayed destroy of instance %p\n", instance.get()));
instance->Stop();
nsRefPtr<nsPluginHost> host = nsPluginHost::GetInst();
if (host)
host->StopPluginInstance(instance);

View File

@ -81,7 +81,6 @@ public:
virtual ~nsPluginHost();
static nsPluginHost* GetInst();
static const char *GetPluginName(nsIPluginInstance *aPluginInstance);
NS_DECL_AND_IMPL_ZEROING_OPERATOR_NEW
@ -164,6 +163,16 @@ public:
void PluginCrashed(nsNPAPIPlugin* plugin);
#endif
nsPluginInstanceTag *FindInstanceTag(nsIPluginInstance *instance);
nsPluginInstanceTag *FindInstanceTag(const char *mimetype);
nsPluginInstanceTag *FindStoppedInstanceTag(const char * url);
nsPluginInstanceTag *FindOldestStoppedInstanceTag();
PRUint32 StoppedInstanceTagCount();
void StopRunningInstances(nsISupportsArray* aReloadDocs, nsPluginTag* aPluginTag);
nsTArray< nsAutoPtr<nsPluginInstanceTag> > *InstanceTagArray();
private:
nsresult
TrySetUpPluginInstance(const char *aMimeType, nsIURI *aURL, nsIPluginInstanceOwner *aOwner);
@ -243,7 +252,9 @@ private:
// calls PostPluginUnloadEvent for each library in mUnusedLibraries
void UnloadUnusedLibraries();
void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag);
nsRefPtr<nsPluginTag> mPlugins;
nsRefPtr<nsPluginTag> mCachedPlugins;
PRPackedBool mPluginsLoaded;
@ -262,7 +273,8 @@ private:
// set by pref plugin.disable
PRPackedBool mPluginsDisabled;
nsPluginInstanceTagList mPluginInstanceTagList;
nsTArray< nsAutoPtr<nsPluginInstanceTag> > mInstanceTags;
nsTArray<PRLibrary*> mUnusedLibraries;
nsCOMPtr<nsIFile> mPluginRegFile;

View File

@ -571,7 +571,6 @@ nsPluginInstanceTag::nsPluginInstanceTag(nsPluginTag* aPluginTag,
NS_ADDREF(aInstance);
mInstance = static_cast<nsNPAPIPluginInstance*>(aInstance);
mNext = nsnull;
mPluginTag = aPluginTag;
mURL = PL_strdup(url);
@ -593,231 +592,3 @@ nsPluginInstanceTag::~nsPluginInstanceTag()
PL_strfree(mURL);
}
/* nsPluginInstanceTagList */
nsPluginInstanceTagList::nsPluginInstanceTagList()
{
mFirst = nsnull;
mLast = nsnull;
mCount = 0;
}
nsPluginInstanceTagList::~nsPluginInstanceTagList()
{
if (!mFirst)
return;
shutdown();
}
void nsPluginInstanceTagList::shutdown()
{
if (!mFirst)
return;
for (nsPluginInstanceTag * plugin = mFirst; plugin != nsnull;) {
nsPluginInstanceTag * next = plugin->mNext;
remove(plugin);
plugin = next;
}
mFirst = nsnull;
mLast = nsnull;
}
PRInt32 nsPluginInstanceTagList::add(nsPluginInstanceTag * plugin)
{
if (!mFirst) {
mFirst = plugin;
mLast = plugin;
mFirst->mNext = nsnull;
}
else {
mLast->mNext = plugin;
mLast = plugin;
}
mLast->mNext = nsnull;
mCount++;
return mCount;
}
PRBool nsPluginInstanceTagList::IsLastInstance(nsPluginInstanceTag * plugin)
{
if (!plugin)
return PR_FALSE;
if (!plugin->mPluginTag)
return PR_FALSE;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if ((p->mPluginTag == plugin->mPluginTag) && (p != plugin))
return PR_FALSE;
}
return PR_TRUE;
}
PRBool nsPluginInstanceTagList::remove(nsPluginInstanceTag * plugin)
{
if (!mFirst)
return PR_FALSE;
nsPluginInstanceTag * prev = nsnull;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p == plugin) {
PRBool lastInstance = IsLastInstance(p);
if (p == mFirst)
mFirst = p->mNext;
else
prev->mNext = p->mNext;
if (prev && !prev->mNext)
mLast = prev;
if (lastInstance) {
nsRefPtr<nsPluginTag> pluginTag = p->mPluginTag;
delete p;
if (pluginTag) {
nsresult rv;
nsCOMPtr<nsIPrefBranch> pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
PRBool unloadPluginsASAP = PR_FALSE;
rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP);
if (NS_SUCCEEDED(rv) && unloadPluginsASAP)
pluginTag->TryUnloadPlugin();
} else {
NS_ASSERTION(pluginTag, "pluginTag was not set, plugin not shutdown");
}
} else {
delete p;
}
mCount--;
return PR_TRUE;
}
prev = p;
}
return PR_FALSE;
}
// This method terminates all running instances of plugins and collects their
// documents to be returned through an array. This method is used
// when we are shutting down or when a plugins.refresh(1) happens.
// If aPluginTag is given, then only that plugin is terminated
void nsPluginInstanceTagList::stopRunning(nsISupportsArray* aReloadDocs,
nsPluginTag* aPluginTag)
{
if (!mFirst)
return;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mInstance->IsRunning() && (!aPluginTag || aPluginTag == p->mPluginTag)) {
p->mInstance->SetWindow(nsnull);
p->mInstance->Stop();
// If we've been passed an array to return, lets collect all our documents,
// removing duplicates. These will be reframed (embedded) or reloaded (full-page) later
// to kickstart our instances.
if (aReloadDocs) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
p->mInstance->GetOwner(getter_AddRefs(owner));
if (owner) {
nsCOMPtr<nsIDocument> doc;
owner->GetDocument(getter_AddRefs(doc));
if (doc && aReloadDocs->IndexOf(doc) == -1) // don't allow for duplicates
aReloadDocs->AppendElement(doc);
}
}
}
}
}
void nsPluginInstanceTagList::removeAllStopped()
{
if (!mFirst)
return;
nsPluginInstanceTag * next = nsnull;
for (nsPluginInstanceTag * p = mFirst; p != nsnull;) {
next = p->mNext;
if (!p->mInstance->IsRunning())
remove(p);
p = next;
}
return;
}
nsPluginInstanceTag * nsPluginInstanceTagList::find(nsIPluginInstance* instance)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mInstance == instance)
return p;
}
return nsnull;
}
nsPluginInstanceTag * nsPluginInstanceTagList::find(const char * mimetype)
{
PRBool defaultplugin = (PL_strcmp(mimetype, "*") == 0);
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
// give it some special treatment for the default plugin first
// because we cannot tell the default plugin by asking instance for a mime type
if (defaultplugin && p->mDefaultPlugin)
return p;
if (!p->mInstance)
continue;
const char* mt;
nsresult rv = p->mInstance->GetMIMEType(&mt);
if (NS_FAILED(rv))
continue;
if (PL_strcasecmp(mt, mimetype) == 0)
return p;
}
return nsnull;
}
nsPluginInstanceTag * nsPluginInstanceTagList::findStopped(const char * url)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!PL_strcmp(url, p->mURL) && !p->mInstance->IsRunning())
return p;
}
return nsnull;
}
PRUint32 nsPluginInstanceTagList::getStoppedCount()
{
PRUint32 stoppedCount = 0;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mInstance->IsRunning())
stoppedCount++;
}
return stoppedCount;
}
nsPluginInstanceTag * nsPluginInstanceTagList::findOldestStopped()
{
nsPluginInstanceTag * res = nsnull;
TimeStamp oldestTime = TimeStamp::Now();
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mInstance->IsRunning())
continue;
TimeStamp time = p->mInstance->LastStopTime();
if (time < oldestTime) {
oldestTime = time;
res = p;
}
}
return res;
}

View File

@ -125,11 +125,10 @@ private:
struct nsPluginInstanceTag
{
nsPluginInstanceTag* mNext;
char* mURL;
nsRefPtr<nsPluginTag> mPluginTag;
nsNPAPIPluginInstance* mInstance; // this must always be valid
PRPackedBool mDefaultPlugin;
PRBool mDefaultPlugin;
// Array holding all opened stream listeners for this entry
nsCOMPtr <nsISupportsArray> mStreams;
@ -140,27 +139,4 @@ struct nsPluginInstanceTag
~nsPluginInstanceTag();
};
class nsPluginInstanceTagList
{
public:
nsPluginInstanceTag *mFirst;
nsPluginInstanceTag *mLast;
PRInt32 mCount;
nsPluginInstanceTagList();
~nsPluginInstanceTagList();
void shutdown();
PRBool add(nsPluginInstanceTag *plugin);
PRBool remove(nsPluginInstanceTag *plugin);
nsPluginInstanceTag *find(nsIPluginInstance *instance);
nsPluginInstanceTag *find(const char *mimetype);
nsPluginInstanceTag *findStopped(const char *url);
PRUint32 getStoppedCount();
nsPluginInstanceTag *findOldestStopped();
void removeAllStopped();
void stopRunning(nsISupportsArray *aReloadDocs, nsPluginTag *aPluginTag);
PRBool IsLastInstance(nsPluginInstanceTag *plugin);
};
#endif // nsPluginTags_h_