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

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

@ -100,6 +100,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
mWindowless(false), mWindowless(false),
mWindowlessLocal(false), mWindowlessLocal(false),
mTransparent(false), mTransparent(false),
mCached(false),
mUsesDOMForCursor(false), mUsesDOMForCursor(false),
mInPluginInitCall(false), mInPluginInitCall(false),
mPlugin(plugin), mPlugin(plugin),
@ -167,6 +168,12 @@ nsNPAPIPluginInstance::Destroy()
mPlugin = nsnull; mPlugin = nsnull;
} }
TimeStamp
nsNPAPIPluginInstance::StopTime()
{
return mStopTime;
}
nsresult nsNPAPIPluginInstance::Initialize(nsIPluginInstanceOwner* aOwner, const char* aMIMEType) nsresult nsNPAPIPluginInstance::Initialize(nsIPluginInstanceOwner* aOwner, const char* aMIMEType)
{ {
PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Initialize this=%p\n",this)); PLUGIN_LOG(PLUGIN_LOG_NORMAL, ("nsNPAPIPluginInstance::Initialize this=%p\n",this));
@ -225,6 +232,7 @@ nsresult nsNPAPIPluginInstance::Stop()
{ {
AsyncCallbackAutoLock lock; AsyncCallbackAutoLock lock;
mRunning = DESTROYING; mRunning = DESTROYING;
mStopTime = TimeStamp::Now();
} }
OnPluginDestroy(&mNPP); OnPluginDestroy(&mNPP);
@ -955,6 +963,19 @@ nsNPAPIPluginInstance::DefineJavaProperties()
return NS_OK; return NS_OK;
} }
nsresult
nsNPAPIPluginInstance::SetCached(bool aCache)
{
mCached = aCache;
return NS_OK;
}
bool
nsNPAPIPluginInstance::ShouldCache()
{
return mCached;
}
nsresult nsresult
nsNPAPIPluginInstance::IsWindowless(bool* isWindowless) nsNPAPIPluginInstance::IsWindowless(bool* isWindowless)
{ {

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

@ -102,6 +102,7 @@ public:
nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing); nsresult IsRemoteDrawingCoreAnimation(bool* aDrawing);
nsresult GetJSObject(JSContext *cx, JSObject** outObject); nsresult GetJSObject(JSContext *cx, JSObject** outObject);
nsresult DefineJavaProperties(); nsresult DefineJavaProperties();
bool ShouldCache();
nsresult IsWindowless(bool* isWindowless); nsresult IsWindowless(bool* isWindowless);
nsresult AsyncSetWindow(NPWindow* window); nsresult AsyncSetWindow(NPWindow* window);
nsresult GetImage(ImageContainer* aContainer, Image** aImage); nsresult GetImage(ImageContainer* aContainer, Image** aImage);
@ -187,6 +188,12 @@ public:
return mRunning == RUNNING || mRunning == DESTROYING; 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(); already_AddRefed<nsPIDOMWindow> GetDOMWindow();
nsresult PrivateModeStateChanged(); nsresult PrivateModeStateChanged();
@ -246,6 +253,7 @@ protected:
bool mWindowless; bool mWindowless;
bool mWindowlessLocal; bool mWindowlessLocal;
bool mTransparent; bool mTransparent;
bool mCached;
bool mUsesDOMForCursor; bool mUsesDOMForCursor;
public: public:
@ -274,6 +282,10 @@ private:
// non-null during a HandleEvent call // non-null during a HandleEvent call
void* mCurrentPluginEvent; 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; nsCOMPtr<nsIURI> mURI;
bool mUsePluginLayersPref; bool mUsePluginLayersPref;

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

@ -231,6 +231,10 @@ PRLogModuleInfo* nsPluginLogging::gPluginLog = nsnull;
#define BRAND_PROPERTIES_URL "chrome://branding/locale/brand.properties" #define BRAND_PROPERTIES_URL "chrome://branding/locale/brand.properties"
#define PLUGIN_PROPERTIES_URL "chrome://global/locale/downloadProgress.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 #ifdef CALL_SAFETY_ON
// By default we run OOPP, so we don't want to cover up crashes. // By default we run OOPP, so we don't want to cover up crashes.
bool gSkipPluginSafeCalls = true; bool gSkipPluginSafeCalls = true;
@ -3204,13 +3208,34 @@ nsPluginHost::StopPluginInstance(nsNPAPIPluginInstance* aInstance)
return NS_OK; return NS_OK;
} }
nsPluginTag* pluginTag = TagForPlugin(aInstance->GetPlugin());
aInstance->Stop(); 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; return NS_OK;
} }
@ -3936,6 +3961,38 @@ nsPluginHost::FindInstance(const char *mimetype)
return nsnull; 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> >* nsTArray< nsRefPtr<nsNPAPIPluginInstance> >*
nsPluginHost::InstanceArray() nsPluginHost::InstanceArray()
{ {

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

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