Bug 700835 - Restore plugin caching to work around bad crash bug in latest Apple Java updates. r=josh

This commit is contained in:
Steven Michaud 2011-11-11 19:10:31 -06:00
Родитель db401edaf6
Коммит 6e6abfa495
5 изменённых файлов: 102 добавлений и 8 удалений

Просмотреть файл

@ -2485,9 +2485,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: {

Просмотреть файл

@ -100,6 +100,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
mWindowless(false),
mWindowlessLocal(false),
mTransparent(false),
mCached(false),
mUsesDOMForCursor(false),
mInPluginInitCall(false),
mPlugin(plugin),
@ -167,6 +168,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));
@ -225,6 +232,7 @@ nsresult nsNPAPIPluginInstance::Stop()
{
AsyncCallbackAutoLock lock;
mRunning = DESTROYING;
mStopTime = TimeStamp::Now();
}
OnPluginDestroy(&mNPP);
@ -955,6 +963,19 @@ nsNPAPIPluginInstance::DefineJavaProperties()
return NS_OK;
}
nsresult
nsNPAPIPluginInstance::SetCached(bool aCache)
{
mCached = aCache;
return NS_OK;
}
bool
nsNPAPIPluginInstance::ShouldCache()
{
return mCached;
}
nsresult
nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
{

Просмотреть файл

@ -102,6 +102,7 @@ public:
nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
nsresult GetJSObject(JSContext *cx, JSObject** outObject);
nsresult DefineJavaProperties();
bool ShouldCache();
nsresult IsWindowless(bool* isWindowless);
nsresult AsyncSetWindow(NPWindow* window);
nsresult GetImage(ImageContainer* aContainer, Image** aImage);
@ -187,6 +188,12 @@ public:
return mRunning == RUNNING || mRunning == DESTROYING;
}
// return is only valid when the plugin is not running
mozilla::TimeStamp StopTime();
// cache this NPAPI plugin
nsresult SetCached(bool aCache);
already_AddRefed<nsPIDOMWindow> GetDOMWindow();
nsresult PrivateModeStateChanged();
@ -246,6 +253,7 @@ protected:
bool mWindowless;
bool mWindowlessLocal;
bool mTransparent;
bool mCached;
bool mUsesDOMForCursor;
public:
@ -274,6 +282,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;
nsCOMPtr<nsIURI> mURI;
bool mUsePluginLayersPref;

Просмотреть файл

@ -231,6 +231,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.
bool gSkipPluginSafeCalls = true;
@ -3204,13 +3208,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
bool 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;
}
@ -3936,6 +3961,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()
{

Просмотреть файл

@ -205,6 +205,8 @@ public:
const nsAString& browserDumpID);
nsNPAPIPluginInstance *FindInstance(const char *mimetype);
nsNPAPIPluginInstance *FindOldestStoppedInstance();
PRUint32 StoppedInstanceCount();
nsTArray< nsRefPtr<nsNPAPIPluginInstance> > *InstanceArray();
@ -253,6 +255,9 @@ private:
nsPluginTag*
FindPluginEnabledForExtension(const char* aExtension, const char* &aMimeType);
nsresult
FindStoppedPluginForURL(nsIURI* aURL, nsIPluginInstanceOwner *aOwner);
nsresult
FindPlugins(bool aCreatePluginList, bool * aPluginsChanged);