Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Commit

Permalink
Bug 700835 - Restore plugin caching to work around bad crash in lates…
Browse files Browse the repository at this point in the history
…t Apple Java updates. r=josh a=akeybl
  • Loading branch information
steven-michaud committed Nov 12, 2011
1 parent d7d8529 commit 2741cc5
Show file tree
Hide file tree
Showing 5 changed files with 99 additions and 8 deletions.
5 changes: 2 additions & 3 deletions dom/plugins/base/nsNPAPIPlugin.cpp
Expand Up @@ -2480,9 +2480,8 @@ _setvalue(NPP npp, NPPVariable variable, void *result)
}

case NPPVpluginKeepLibraryInMemory: {
// This variable is not supported any more but we'll pretend it is
// so that plugins don't fail on an error return.
return NS_OK;
NPBool bCached = (result != nsnull);
return inst->SetCached(bCached);
}

case NPPVpluginUsesDOMForCursorBool: {
Expand Down
21 changes: 21 additions & 0 deletions dom/plugins/base/nsNPAPIPluginInstance.cpp
Expand Up @@ -95,6 +95,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
mWindowless(PR_FALSE),
mWindowlessLocal(PR_FALSE),
mTransparent(PR_FALSE),
mCached(PR_FALSE),
mUsesDOMForCursor(PR_FALSE),
mInPluginInitCall(PR_FALSE),
mPlugin(plugin),
Expand Down Expand Up @@ -142,6 +143,12 @@ nsNPAPIPluginInstance::Destroy()
mPlugin = nsnull;
}

TimeStamp
nsNPAPIPluginInstance::StopTime()
{
return mStopTime;
}

nsresult nsNPAPIPluginInstance::Initialize(nsIPluginInstanceOwner* aOwner, const char* aMIMEType)
{
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Initialize this=%p\n",this));
Expand Down Expand Up @@ -200,6 +207,7 @@ nsresult nsNPAPIPluginInstance::Stop()
{
AsyncCallbackAutoLock lock;
mRunning = DESTROYING;
mStopTime = TimeStamp::Now();
}

OnPluginDestroy(&mNPP);
Expand Down Expand Up @@ -873,6 +881,19 @@ nsNPAPIPluginInstance::DefineJavaProperties()
return NS_OK;
}

nsresult
nsNPAPIPluginInstance::SetCached(PRBool aCache)
{
mCached = aCache;
return NS_OK;
}

PRBool
nsNPAPIPluginInstance::ShouldCache()
{
return mCached;
}

nsresult
nsNPAPIPluginInstance::IsWindowless(PRBool* isWindowless)
{
Expand Down
12 changes: 12 additions & 0 deletions dom/plugins/base/nsNPAPIPluginInstance.h
Expand Up @@ -95,6 +95,7 @@ class nsNPAPIPluginInstance : public nsISupports
nsresult IsRemoteDrawingCoreAnimation(PRBool* aDrawing);
nsresult GetJSObject(JSContext *cx, JSObject** outObject);
nsresult DefineJavaProperties();
PRBool ShouldCache();
nsresult IsWindowless(PRBool* isWindowless);
nsresult AsyncSetWindow(NPWindow* window);
nsresult GetImage(ImageContainer* aContainer, Image** aImage);
Expand Down Expand Up @@ -173,6 +174,12 @@ class nsNPAPIPluginInstance : public nsISupports
return mRunning == RUNNING || mRunning == DESTROYING;
}

// return is only valid when the plugin is not running
mozilla::TimeStamp StopTime();

// cache this NPAPI plugin
nsresult SetCached(PRBool aCache);

already_AddRefed<nsPIDOMWindow> GetDOMWindow();

nsresult PrivateModeStateChanged();
Expand Down Expand Up @@ -232,6 +239,7 @@ class nsNPAPIPluginInstance : public nsISupports
PRPackedBool mWindowless;
PRPackedBool mWindowlessLocal;
PRPackedBool mTransparent;
PRPackedBool mCached;
PRPackedBool mUsesDOMForCursor;

public:
Expand Down Expand Up @@ -260,6 +268,10 @@ class nsNPAPIPluginInstance : public nsISupports
// 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;

nsCOMPtr<nsIURI> mURI;

PRPackedBool mUsePluginLayersPref;
Expand Down
67 changes: 62 additions & 5 deletions dom/plugins/base/nsPluginHost.cpp
Expand Up @@ -230,6 +230,10 @@ PRLogModuleInfo* nsPluginLogging::gPluginLog = nsnull;
#define BRAND_PROPERTIES_URL "chrome://branding/locale/brand.properties"
#define PLUGIN_PROPERTIES_URL "chrome://global/locale/downloadProgress.properties"

// #defines for plugin cache and prefs
#define NS_PREF_MAX_NUM_CACHED_INSTANCES "browser.plugins.max_num_cached_plugins"
#define DEFAULT_NUMBER_OF_STOPPED_INSTANCES 10

#ifdef CALL_SAFETY_ON
// By default we run OOPP, so we don't want to cover up crashes.
PRBool gSkipPluginSafeCalls = PR_TRUE;
Expand Down Expand Up @@ -3198,13 +3202,34 @@ nsPluginHost::StopPluginInstance(nsNPAPIPluginInstance* aInstance)
return NS_OK;
}

nsPluginTag* pluginTag = TagForPlugin(aInstance->GetPlugin());

aInstance->Stop();
aInstance->Destroy();
mInstances.RemoveElement(aInstance);

OnPluginInstanceDestroyed(pluginTag);
// if the instance does not want to be 'cached' just remove it
PRBool doCache = aInstance->ShouldCache();
if (doCache) {
// try to get the max cached instances from a pref or use default
PRUint32 cachedInstanceLimit;
nsresult rv = NS_ERROR_FAILURE;
if (mPrefService)
rv = mPrefService->GetIntPref(NS_PREF_MAX_NUM_CACHED_INSTANCES, (int*)&cachedInstanceLimit);
if (NS_FAILED(rv))
cachedInstanceLimit = DEFAULT_NUMBER_OF_STOPPED_INSTANCES;

if (StoppedInstanceCount() >= cachedInstanceLimit) {
nsNPAPIPluginInstance *oldestInstance = FindOldestStoppedInstance();
if (oldestInstance) {
nsPluginTag* pluginTag = TagForPlugin(oldestInstance->GetPlugin());
oldestInstance->Destroy();
mInstances.RemoveElement(oldestInstance);
OnPluginInstanceDestroyed(pluginTag);
}
}
} else {
nsPluginTag* pluginTag = TagForPlugin(aInstance->GetPlugin());
aInstance->Destroy();
mInstances.RemoveElement(aInstance);
OnPluginInstanceDestroyed(pluginTag);
}

return NS_OK;
}
Expand Down Expand Up @@ -3930,6 +3955,38 @@ nsPluginHost::FindInstance(const char *mimetype)
return nsnull;
}

nsNPAPIPluginInstance*
nsPluginHost::FindOldestStoppedInstance()
{
nsNPAPIPluginInstance *oldestInstance = nsnull;
TimeStamp oldestTime = TimeStamp::Now();
for (PRUint32 i = 0; i < mInstances.Length(); i++) {
nsNPAPIPluginInstance *instance = mInstances[i];
if (instance->IsRunning())
continue;

TimeStamp time = instance->StopTime();
if (time < oldestTime) {
oldestTime = time;
oldestInstance = instance;
}
}

return oldestInstance;
}

PRUint32
nsPluginHost::StoppedInstanceCount()
{
PRUint32 stoppedCount = 0;
for (PRUint32 i = 0; i < mInstances.Length(); i++) {
nsNPAPIPluginInstance *instance = mInstances[i];
if (!instance->IsRunning())
stoppedCount++;
}
return stoppedCount;
}

nsTArray< nsRefPtr<nsNPAPIPluginInstance> >*
nsPluginHost::InstanceArray()
{
Expand Down
2 changes: 2 additions & 0 deletions dom/plugins/base/nsPluginHost.h
Expand Up @@ -205,6 +205,8 @@ class nsPluginHost : public nsIPluginHost,
const nsAString& browserDumpID);

nsNPAPIPluginInstance *FindInstance(const char *mimetype);
nsNPAPIPluginInstance *FindOldestStoppedInstance();
PRUint32 StoppedInstanceCount();

nsTArray< nsRefPtr<nsNPAPIPluginInstance> > *InstanceArray();

Expand Down

0 comments on commit 2741cc5

Please sign in to comment.