Improve plugin instance stopped/started state management. b=535660 r=roc

This commit is contained in:
Josh Aas 2009-12-17 21:09:22 -05:00
parent f59fcf5bcb
commit ac8d51b495
6 changed files with 79 additions and 76 deletions

View File

@ -889,7 +889,7 @@ nsPluginThreadRunnable::nsPluginThreadRunnable(NPP instance,
nsAutoLock lock(sPluginThreadAsyncCallLock);
nsNPAPIPluginInstance *inst = (nsNPAPIPluginInstance *)instance->ndata;
if (!inst || !inst->IsStarted()) {
if (!inst || !inst->IsRunning()) {
// The plugin was stopped, ignore this async call.
mFunc = nsnull;

View File

@ -58,6 +58,7 @@
#include "nsJSNPRuntime.h"
using namespace mozilla::plugins::parent;
using mozilla::TimeStamp;
static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
@ -255,7 +256,7 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason)
if (mStreamCleanedUp)
return NS_OK;
if (!mInst || !mInst->IsStarted())
if (!mInst || !mInst->IsRunning())
return rv;
PluginDestructionGuard guard(mInst);
@ -297,7 +298,7 @@ nsresult nsNPAPIPluginStreamListener::CleanUpStream(NPReason reason)
void nsNPAPIPluginStreamListener::CallURLNotify(NPReason reason)
{
if (!mCallNotify || !mInst || !mInst->IsStarted())
if (!mCallNotify || !mInst || !mInst->IsRunning())
return;
PluginDestructionGuard guard(mInst);
@ -336,7 +337,7 @@ nsNPAPIPluginStreamListener::OnStartBinding(nsIPluginStreamInfo* pluginInfo)
mInst->GetCallbacks(&callbacks);
mInst->GetNPP(&npp);
if (!callbacks || !mInst->IsStarted())
if (!callbacks || !mInst->IsRunning())
return NS_ERROR_FAILURE;
PRBool seekable;
@ -479,7 +480,7 @@ nsNPAPIPluginStreamListener::OnDataAvailable(nsIPluginStreamInfo* pluginInfo,
nsIInputStream* input,
PRUint32 length)
{
if (!mInst || !mInst->IsStarted())
if (!mInst || !mInst->IsRunning())
return NS_ERROR_FAILURE;
PluginDestructionGuard guard(mInst);
@ -744,7 +745,7 @@ NS_IMETHODIMP
nsNPAPIPluginStreamListener::OnFileAvailable(nsIPluginStreamInfo* pluginInfo,
const char* fileName)
{
if (!mInst || !mInst->IsStarted())
if (!mInst || !mInst->IsRunning())
return NS_ERROR_FAILURE;
PluginDestructionGuard guard(mInst);
@ -787,7 +788,7 @@ nsNPAPIPluginStreamListener::OnStopBinding(nsIPluginStreamInfo* pluginInfo,
}
}
if (!mInst || !mInst->IsStarted())
if (!mInst || !mInst->IsRunning())
return NS_ERROR_FAILURE;
// check if the stream is of seekable type and later its destruction
@ -889,7 +890,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(NPPluginFuncs* callbacks,
mWindowless(PR_FALSE),
mWindowlessLocal(PR_FALSE),
mTransparent(PR_FALSE),
mStarted(PR_FALSE),
mRunning(PR_FALSE),
mCached(PR_FALSE),
mWantsAllNetworkStreams(PR_FALSE),
mInPluginInitCall(PR_FALSE),
@ -927,9 +928,15 @@ nsNPAPIPluginInstance::~nsNPAPIPluginInstance(void)
}
PRBool
nsNPAPIPluginInstance::IsStarted(void)
nsNPAPIPluginInstance::IsRunning()
{
return mStarted;
return mRunning;
}
TimeStamp
nsNPAPIPluginInstance::LastStopTime()
{
return mStopTime;
}
NS_IMETHODIMP nsNPAPIPluginInstance::Initialize(nsIPluginInstanceOwner* aOwner, const char* aMIMEType)
@ -948,17 +955,17 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Initialize(nsIPluginInstanceOwner* aOwner,
return InitializePlugin();
}
NS_IMETHODIMP nsNPAPIPluginInstance::Start(void)
NS_IMETHODIMP nsNPAPIPluginInstance::Start()
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Start this=%p\n",this));
if (mStarted)
if (mRunning)
return NS_OK;
return InitializePlugin();
}
NS_IMETHODIMP nsNPAPIPluginInstance::Stop(void)
NS_IMETHODIMP nsNPAPIPluginInstance::Stop()
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Stop this=%p\n",this));
@ -973,7 +980,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Stop(void)
}
}
if (!mStarted) {
if (!mRunning) {
return NS_OK;
}
@ -987,10 +994,11 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Stop(void)
return NS_OK;
}
// Make sure we lock while we're writing to mStarted after we've
// Make sure we lock while we're writing to mRunning after we've
// started as other threads might be checking that inside a lock.
EnterAsyncPluginThreadCallLock();
mStarted = PR_FALSE;
mRunning = PR_FALSE;
mStopTime = TimeStamp::Now();
ExitAsyncPluginThreadCallLock();
OnPluginDestroy(&mNPP);
@ -1188,10 +1196,10 @@ nsNPAPIPluginInstance::InitializePlugin()
}
}
// Mark this instance as started before calling NPP_New because the plugin may
// Mark this instance as running before calling NPP_New because the plugin may
// call other NPAPI functions, like NPN_GetURLNotify, that assume this is set
// before returning. If the plugin returns failure, we'll clear it out below.
mStarted = PR_TRUE;
mRunning = PR_TRUE;
PRBool oldVal = mInPluginInitCall;
mInPluginInitCall = PR_TRUE;
@ -1200,8 +1208,10 @@ nsNPAPIPluginInstance::InitializePlugin()
// the plugin may make could fail (NPN_HasProperty, for example).
NPPAutoPusher autopush(&mNPP);
nsresult newResult = mLibrary->NPP_New((char*)mimetype, &mNPP, (PRUint16)mode, count, (char**)names, (char**)values, NULL, &error);
if (NS_FAILED(newResult))
if (NS_FAILED(newResult)) {
mRunning = PR_FALSE;
return newResult;
}
mInPluginInitCall = oldVal;
@ -1210,7 +1220,7 @@ nsNPAPIPluginInstance::InitializePlugin()
this, &mNPP, mimetype, mode, count, error));
if (error != NPERR_NO_ERROR) {
mStarted = PR_FALSE;
mRunning = PR_FALSE;
return NS_ERROR_FAILURE;
}
@ -1220,7 +1230,7 @@ nsNPAPIPluginInstance::InitializePlugin()
NS_IMETHODIMP nsNPAPIPluginInstance::SetWindow(NPWindow* window)
{
// NPAPI plugins don't want a SetWindow(NULL).
if (!window || !mStarted)
if (!window || !mRunning)
return NS_OK;
#if defined(MOZ_WIDGET_GTK2)
@ -1352,7 +1362,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::Print(NPPrint* platformPrint)
NS_IMETHODIMP nsNPAPIPluginInstance::HandleEvent(void* event, PRBool* handled)
{
if (!mStarted)
if (!mRunning)
return NS_OK;
if (!event)
@ -1391,7 +1401,7 @@ NS_IMETHODIMP nsNPAPIPluginInstance::GetValueFromPlugin(NPPVariable variable, vo
}
#endif
nsresult res = NS_OK;
if (mCallbacks->getvalue && mStarted) {
if (mCallbacks->getvalue && mRunning) {
PluginDestructionGuard guard(this);
NS_TRY_SAFE_CALL_RETURN(res, (*mCallbacks->getvalue)(&mNPP, variable, value), mLibrary, this);
@ -1651,7 +1661,7 @@ nsNPAPIPluginInstance::GetPluginAPIVersion(PRUint16* version)
nsresult
nsNPAPIPluginInstance::PrivateModeStateChanged()
{
if (!mStarted)
if (!mRunning)
return NS_OK;
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance informing plugin of private mode state change this=%p\n",this));

View File

@ -48,6 +48,7 @@
#include "nsPIDOMWindow.h"
#include "nsIPluginInstanceOwner.h"
#include "nsITimer.h"
#include "mozilla/TimeStamp.h"
#include "npfunctions.h"
#include "mozilla/PluginLibrary.h"
@ -111,7 +112,10 @@ public:
virtual ~nsNPAPIPluginInstance();
// returns the state of mStarted
PRBool IsStarted();
PRBool IsRunning();
// return is only valid when the plugin is not running
mozilla::TimeStamp LastStopTime();
// cache this NPAPI plugin
nsresult SetCached(PRBool aCache);
@ -155,7 +159,7 @@ protected:
PRPackedBool mWindowless;
PRPackedBool mWindowlessLocal;
PRPackedBool mTransparent;
PRPackedBool mStarted;
PRPackedBool mRunning;
PRPackedBool mCached;
PRPackedBool mWantsAllNetworkStreams;
@ -178,6 +182,10 @@ private:
// non-null during a HandleEvent call
void* mCurrentPluginEvent;
// Timestamp for the last time this plugin was stopped.
// This is only valid when the plugin is actually stopped!
mozilla::TimeStamp mStopTime;
};
#endif // nsNPAPIPluginInstance_h_

View File

@ -1799,7 +1799,7 @@ PRBool nsPluginHost::IsRunningPlugin(nsPluginTag * plugin)
for (int i = 0; i < plugin->mVariants; i++) {
nsPluginInstanceTag * p = mPluginInstanceTagList.find(plugin->mMimeTypeArray[i]);
if (p && !p->mStopped)
if (p && p->mInstance->IsRunning())
return PR_TRUE;
}
@ -2571,7 +2571,7 @@ NS_IMETHODIMP nsPluginHost::InstantiateFullPagePlugin(const char *aMimeType,
}
nsresult nsPluginHost::FindStoppedPluginForURL(nsIURI* aURL,
nsIPluginInstanceOwner *aOwner)
nsIPluginInstanceOwner *aOwner)
{
nsCAutoString url;
if (!aURL)
@ -2579,13 +2579,13 @@ nsresult nsPluginHost::FindStoppedPluginForURL(nsIURI* aURL,
aURL->GetAsciiSpec(url);
nsPluginInstanceTag * plugin = mPluginInstanceTagList.findStopped(url.get());
nsPluginInstanceTag *instanceTag = mPluginInstanceTagList.findStopped(url.get());
if (plugin && plugin->mStopped) {
nsIPluginInstance* instance = plugin->mInstance;
if (instanceTag && !instanceTag->mInstance->IsRunning()) {
NPWindow* window = nsnull;
aOwner->GetWindow(window);
nsIPluginInstance* instance = static_cast<nsIPluginInstance*>(instanceTag->mInstance);
aOwner->SetInstance(instance);
instance->SetOwner(aOwner);
@ -2598,7 +2598,6 @@ nsresult nsPluginHost::FindStoppedPluginForURL(nsIURI* aURL,
((nsPluginNativeWindow*)window)->CallSetWindow(inst);
}
plugin->setStopped(PR_FALSE);
return NS_OK;
}
return NS_ERROR_FAILURE;
@ -2608,7 +2607,6 @@ nsresult nsPluginHost::AddInstanceToActiveList(nsCOMPtr<nsIPlugin> aPlugin,
nsIPluginInstance* aInstance,
nsIURI* aURL,
PRBool aDefaultPlugin)
{
nsCAutoString url;
// It's OK to not have a URL here, as is the case with the dummy
@ -4538,8 +4536,6 @@ nsPluginHost::StopPluginInstance(nsIPluginInstance* aInstance)
nsPluginInstanceTag * plugin = mPluginInstanceTagList.find(aInstance);
if (plugin) {
plugin->setStopped(PR_TRUE); // be sure we set the "stop" bit
// if the plugin does not want to be 'cached' just remove it
PRBool doCache = PR_TRUE;
aInstance->ShouldCache(&doCache);

View File

@ -54,6 +54,9 @@
#include "nsICharsetConverterManager.h"
#include "nsPluginLogging.h"
#include "nsICategoryManager.h"
#include "mozilla/TimeStamp.h"
using mozilla::TimeStamp;
inline char* new_str(const char* str)
{
@ -564,40 +567,31 @@ nsPluginInstanceTag::nsPluginInstanceTag(nsPluginTag* aPluginTag,
const char * url,
PRBool aDefaultPlugin)
{
NS_ASSERTION(aInstance, "Must have a valid plugin instance when creating an nsPluginInstanceTag");
NS_ADDREF(aInstance);
mInstance = static_cast<nsNPAPIPluginInstance*>(aInstance);
mNext = nsnull;
mPluginTag = aPluginTag;
mURL = PL_strdup(url);
mInstance = aInstance;
if (aInstance)
NS_ADDREF(aInstance);
mDefaultPlugin = aDefaultPlugin;
mStopped = PR_FALSE;
mllStopTime = LL_ZERO;
}
nsPluginInstanceTag::~nsPluginInstanceTag()
{
mPluginTag = nsnull;
if (mInstance) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
mInstance->GetOwner(getter_AddRefs(owner));
if (owner)
owner->SetInstance(nsnull);
mInstance->InvalidateOwner();
NS_RELEASE(mInstance);
}
PL_strfree(mURL);
}
void nsPluginInstanceTag::setStopped(PRBool stopped)
{
mStopped = stopped;
if (mStopped) // plugin instance is told to stop
mllStopTime = PR_Now();
else
mllStopTime = LL_ZERO;
nsCOMPtr<nsIPluginInstanceOwner> owner;
mInstance->GetOwner(getter_AddRefs(owner));
if (owner)
owner->SetInstance(nsnull);
mInstance->InvalidateOwner();
NS_RELEASE(mInstance);
PL_strfree(mURL);
}
/* nsPluginInstanceTagList */
@ -719,16 +713,14 @@ void nsPluginInstanceTagList::stopRunning(nsISupportsArray* aReloadDocs,
return;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mStopped && p->mInstance &&
(!aPluginTag || aPluginTag == p->mPluginTag)) {
if (p->mInstance->IsRunning() && (!aPluginTag || aPluginTag == p->mPluginTag)) {
p->mInstance->SetWindow(nsnull);
p->mInstance->Stop();
p->setStopped(PR_TRUE);
// 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 && p->mInstance) {
if (aReloadDocs) {
nsCOMPtr<nsIPluginInstanceOwner> owner;
p->mInstance->GetOwner(getter_AddRefs(owner));
if (owner) {
@ -752,7 +744,7 @@ void nsPluginInstanceTagList::removeAllStopped()
for (nsPluginInstanceTag * p = mFirst; p != nsnull;) {
next = p->mNext;
if (p->mStopped)
if (!p->mInstance->IsRunning())
remove(p);
p = next;
@ -796,7 +788,7 @@ nsPluginInstanceTag * nsPluginInstanceTagList::find(const char * mimetype)
nsPluginInstanceTag * nsPluginInstanceTagList::findStopped(const char * url)
{
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!PL_strcmp(url, p->mURL) && p->mStopped)
if (!PL_strcmp(url, p->mURL) && !p->mInstance->IsRunning())
return p;
}
return nsnull;
@ -806,7 +798,7 @@ PRUint32 nsPluginInstanceTagList::getStoppedCount()
{
PRUint32 stoppedCount = 0;
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (p->mStopped)
if (!p->mInstance->IsRunning())
stoppedCount++;
}
return stoppedCount;
@ -815,13 +807,14 @@ PRUint32 nsPluginInstanceTagList::getStoppedCount()
nsPluginInstanceTag * nsPluginInstanceTagList::findOldestStopped()
{
nsPluginInstanceTag * res = nsnull;
PRInt64 llTime = LL_MAXINT;
TimeStamp oldestTime = TimeStamp::Now();
for (nsPluginInstanceTag * p = mFirst; p != nsnull; p = p->mNext) {
if (!p->mStopped)
if (p->mInstance->IsRunning())
continue;
if (LL_CMP(p->mllStopTime, <, llTime)) {
llTime = p->mllStopTime;
TimeStamp time = p->mInstance->LastStopTime();
if (time < oldestTime) {
oldestTime = time;
res = p;
}
}

View File

@ -45,7 +45,7 @@
#include "nsCOMPtr.h"
#include "nsIPluginTag.h"
#include "nsIPlugin.h"
#include "nsIPluginInstance.h"
#include "nsNPAPIPluginInstance.h"
#include "nsISupportsArray.h"
class nsPluginHost;
@ -128,9 +128,7 @@ struct nsPluginInstanceTag
nsPluginInstanceTag* mNext;
char* mURL;
nsRefPtr<nsPluginTag> mPluginTag;
nsIPluginInstance* mInstance;
PRTime mllStopTime;
PRPackedBool mStopped;
nsNPAPIPluginInstance* mInstance; // this must always be valid
PRPackedBool mDefaultPlugin;
// Array holding all opened stream listeners for this entry
nsCOMPtr <nsISupportsArray> mStreams;
@ -140,8 +138,6 @@ struct nsPluginInstanceTag
const char * url,
PRBool aDefaultPlugin);
~nsPluginInstanceTag();
void setStopped(PRBool stopped);
};
class nsPluginInstanceTagList