From e8f9c5380641090e3440899f9e7757738474ce02 Mon Sep 17 00:00:00 2001 From: Josh Aas Date: Fri, 13 Aug 2010 02:42:42 -0400 Subject: [PATCH] Bug 578868: Only load plugin libraries into the main process when absolutely necessary. r=benwa sr=bsmedberg --- dom/plugins/PluginModuleChild.cpp | 2 +- modules/plugin/base/public/npfunctions.h | 22 +++- modules/plugin/base/public/nsIPlugin.idl | 27 +--- modules/plugin/base/src/PluginPRLibrary.cpp | 8 +- modules/plugin/base/src/PluginPRLibrary.h | 19 +-- modules/plugin/base/src/nsNPAPIPlugin.cpp | 45 +------ modules/plugin/base/src/nsNPAPIPlugin.h | 2 + modules/plugin/base/src/nsPluginHost.cpp | 124 ++++++++++-------- modules/plugin/base/src/nsPluginsDir.h | 5 +- modules/plugin/base/src/nsPluginsDirBeOS.cpp | 8 +- .../plugin/base/src/nsPluginsDirDarwin.cpp | 23 ++-- modules/plugin/base/src/nsPluginsDirOS2.cpp | 10 +- modules/plugin/base/src/nsPluginsDirUnix.cpp | 103 +++++++++------ modules/plugin/base/src/nsPluginsDirWin.cpp | 10 +- 14 files changed, 203 insertions(+), 205 deletions(-) diff --git a/dom/plugins/PluginModuleChild.cpp b/dom/plugins/PluginModuleChild.cpp index 74099521a37d..eb1ac9fe142b 100644 --- a/dom/plugins/PluginModuleChild.cpp +++ b/dom/plugins/PluginModuleChild.cpp @@ -189,7 +189,7 @@ PluginModuleChild::Init(const std::string& aPluginFilename, nsPluginFile lib(pluginIfile); - nsresult rv = lib.LoadPlugin(mLibrary); + nsresult rv = lib.LoadPlugin(&mLibrary); NS_ASSERTION(NS_OK == rv, "trouble with mPluginFile"); NS_ASSERTION(mLibrary, "couldn't open shared object"); diff --git a/modules/plugin/base/public/npfunctions.h b/modules/plugin/base/public/npfunctions.h index 56d132a141f8..426a1b6d2a03 100644 --- a/modules/plugin/base/public/npfunctions.h +++ b/modules/plugin/base/public/npfunctions.h @@ -267,12 +267,17 @@ typedef struct _NPPluginData { /* Alternate OS2 Plugin interface */ unsigned long dwProductVersionMS; unsigned long dwProductVersionLS; } NPPluginData; -NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData); +typedef NPError (*NP_GetPluginDataFunc)(NPPluginData*); +NPError OSCALL NP_GetPluginData(NPPluginData * pPluginData); #endif -NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs); -NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs); -NPError OSCALL NP_Shutdown(); -char* NP_GetMIMEDescription(); +typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*); +NPError OSCALL NP_GetEntryPoints(NPPluginFuncs* pFuncs); +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*); +NPError OSCALL NP_Initialize(NPNetscapeFuncs* bFuncs); +typedef NPError (*NP_ShutdownFunc)(); +NPError OSCALL NP_Shutdown(); +typedef char* (*NP_GetMIMEDescriptionFunc)(); +char* NP_GetMIMEDescription(); #ifdef __cplusplus } #endif @@ -286,15 +291,22 @@ char* NP_GetMIMEDescription(); #ifdef __cplusplus extern "C" { #endif +typedef char* (*NP_GetPluginVersionFunc)(); NP_EXPORT(char*) NP_GetPluginVersion(); +typedef char* (*NP_GetMIMEDescriptionFunc)(); NP_EXPORT(char*) NP_GetMIMEDescription(); #ifdef XP_MACOSX +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*); NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs); +typedef NPError (*NP_GetEntryPointsFunc)(NPPluginFuncs*); NP_EXPORT(NPError) NP_GetEntryPoints(NPPluginFuncs* pFuncs); #else +typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*); NP_EXPORT(NPError) NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs); #endif +typedef NPError (*NP_ShutdownFunc)(); NP_EXPORT(NPError) NP_Shutdown(); +typedef NPError (*NP_GetValueFunc)(void *, NPPVariable, void *); NP_EXPORT(NPError) NP_GetValue(void *future, NPPVariable aVariable, void *aValue); #ifdef __cplusplus } diff --git a/modules/plugin/base/public/nsIPlugin.idl b/modules/plugin/base/public/nsIPlugin.idl index d540d2f91ebf..10ee36012092 100644 --- a/modules/plugin/base/public/nsIPlugin.idl +++ b/modules/plugin/base/public/nsIPlugin.idl @@ -47,7 +47,7 @@ interface nsIPluginInstance; -[uuid(843D6092-2BB0-4A21-8827-0510A52CA795)] +[uuid(94C32FEA-5C50-49D3-9D3D-9047CD342777)] interface nsIPlugin : nsISupports { /** @@ -66,29 +66,4 @@ interface nsIPlugin : nsISupports * @result - NS_OK if this operation was successful */ void shutdown(); - - /** - * Returns the MIME description for the plugin. The MIME description - * is a colon-separated string containg the plugin MIME type, plugin - * data file extension, and plugin name, e.g.: - * - * "application/x-simple-plugin:smp:Simple Sample Plug-in" - * - * (Corresponds to NPP_GetMIMEDescription.) - * - * @param aMIMEDescription - the resulting MIME description - * @result - NS_OK if this operation was successful - */ - void getMIMEDescription(out constCharPtr aMIMEDescription); - - /** - * Returns the value of a variable associated with the plugin. - * - * (Corresponds to NPP_GetValue.) - * - * @param aVariable - the plugin variable to get - * @param aValue - the address of where to store the resulting value - * @result - NS_OK if this operation was successful - */ - void getValue(in NPPVariable aVariable, in voidPtr aValue); }; diff --git a/modules/plugin/base/src/PluginPRLibrary.cpp b/modules/plugin/base/src/PluginPRLibrary.cpp index 13d1981367b5..98b4d6409c6f 100644 --- a/modules/plugin/base/src/PluginPRLibrary.cpp +++ b/modules/plugin/base/src/PluginPRLibrary.cpp @@ -137,17 +137,19 @@ nsresult PluginPRLibrary::NP_GetValue(void *future, NPPVariable aVariable, void *aValue, NPError* error) { +#if defined(XP_UNIX) && !defined(XP_MACOSX) if (mNP_GetValue) { *error = mNP_GetValue(future, aVariable, aValue); } else { - NP_GetValueFunc pfNP_GetValue = (NP_GetValueFunc) - PR_FindFunctionSymbol(mLibrary, "NP_GetValue"); + NP_GetValueFunc pfNP_GetValue = (NP_GetValueFunc)PR_FindFunctionSymbol(mLibrary, "NP_GetValue"); if (!pfNP_GetValue) return NS_ERROR_FAILURE; *error = pfNP_GetValue(future, aVariable, aValue); } - return NS_OK; +#else + return NS_ERROR_NOT_IMPLEMENTED; +#endif } #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2) diff --git a/modules/plugin/base/src/PluginPRLibrary.h b/modules/plugin/base/src/PluginPRLibrary.h index 799cfe528fdb..fe20f8a6bf65 100644 --- a/modules/plugin/base/src/PluginPRLibrary.h +++ b/modules/plugin/base/src/PluginPRLibrary.h @@ -41,23 +41,12 @@ #include "mozilla/PluginLibrary.h" #include "nsNPAPIPlugin.h" +#include "npfunctions.h" namespace mozilla { class PluginPRLibrary : public PluginLibrary { -#if defined(XP_UNIX) && !defined(XP_MACOSX) - typedef NPError (*NP_InitializeFunc)(NPNetscapeFuncs*, NPPluginFuncs*); -#else - typedef NPError (OSCALL *NP_InitializeFunc)(NPNetscapeFuncs*); -#endif - typedef NPError (OSCALL *NP_ShutdownFunc)(); - typedef char* (*NP_GetMIMEDescriptionFunc)(); - typedef NPError (*NP_GetValueFunc)(void *, NPPVariable, void*); -#if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2) - typedef NPError (OSCALL *NP_GetEntryPointsFunc)(NPPluginFuncs*); -#endif - public: PluginPRLibrary(const char* aFilePath, PRLibrary* aLibrary) : #if defined(XP_UNIX) && !defined(XP_MACOSX) @@ -67,7 +56,9 @@ public: #endif mNP_Shutdown(nsnull), mNP_GetMIMEDescription(nsnull), +#if defined(XP_UNIX) && !defined(XP_MACOSX) mNP_GetValue(nsnull), +#endif #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2) mNP_GetEntryPoints(nsnull), #endif @@ -103,9 +94,9 @@ public: return false; #endif +#if defined(XP_UNIX) && !defined(XP_MACOSX) mNP_GetValue = (NP_GetValueFunc) PR_FindFunctionSymbol(mLibrary, "NP_GetValue"); -#ifndef XP_MACOSX if (!mNP_GetValue) return false; #endif @@ -146,7 +137,9 @@ private: NP_InitializeFunc mNP_Initialize; NP_ShutdownFunc mNP_Shutdown; NP_GetMIMEDescriptionFunc mNP_GetMIMEDescription; +#if defined(XP_UNIX) && !defined(XP_MACOSX) NP_GetValueFunc mNP_GetValue; +#endif #if defined(XP_WIN) || defined(XP_MACOSX) || defined(XP_OS2) NP_GetEntryPointsFunc mNP_GetEntryPoints; #endif diff --git a/modules/plugin/base/src/nsNPAPIPlugin.cpp b/modules/plugin/base/src/nsNPAPIPlugin.cpp index bc0c24dc3c4c..d64d11f4c10b 100644 --- a/modules/plugin/base/src/nsNPAPIPlugin.cpp +++ b/modules/plugin/base/src/nsNPAPIPlugin.cpp @@ -266,8 +266,6 @@ nsNPAPIPlugin::PluginCrashed(const nsAString& pluginDumpID, } #endif -namespace { - #ifdef MOZ_IPC #ifdef XP_MACOSX @@ -310,8 +308,8 @@ static PRBool GMA9XXGraphics() } #endif -inline PRBool -RunPluginOOP(const char* aFilePath, const nsPluginTag *aPluginTag) +PRBool +nsNPAPIPlugin::RunPluginOOP(const char* aFilePath, const nsPluginTag *aPluginTag) { if (PR_GetEnv("MOZ_DISABLE_OOP_PLUGINS")) { return PR_FALSE; @@ -394,7 +392,7 @@ GetNewPluginLibrary(const char* aFilePath, nsRefPtr host = dont_AddRef(nsPluginHost::GetInst()); nsPluginTag* tag = host->FindTagForLibrary(aLibrary); if (tag) { - if (aFilePath && RunPluginOOP(aFilePath, tag)) { + if (aFilePath && nsNPAPIPlugin::RunPluginOOP(aFilePath, tag)) { return PluginModuleParent::LoadModule(aFilePath); } } @@ -402,8 +400,6 @@ GetNewPluginLibrary(const char* aFilePath, return new PluginPRLibrary(aFilePath, aLibrary); } -} /* anonymous namespace */ - // Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance). nsresult nsNPAPIPlugin::CreatePlugin(const char* aFilePath, PRLibrary* aLibrary, @@ -411,6 +407,10 @@ nsNPAPIPlugin::CreatePlugin(const char* aFilePath, PRLibrary* aLibrary, { *aResult = nsnull; + if (!aFilePath || !aLibrary) { + return NS_ERROR_FAILURE; + } + CheckClassInitialized(); nsRefPtr plugin = new nsNPAPIPlugin(); @@ -432,14 +432,6 @@ nsNPAPIPlugin::CreatePlugin(const char* aFilePath, PRLibrary* aLibrary, plugin->mLibrary = pluginLib; pluginLib->SetPlugin(plugin); -#if defined(XP_UNIX) && !defined(XP_MACOSX) - // Do not initialize if the file path is NULL. - if (!aFilePath) { - *aResult = plugin.forget().get(); - return NS_OK; - } -#endif - NPError pluginCallError; nsresult rv; @@ -523,29 +515,6 @@ nsNPAPIPlugin::Shutdown() return NS_OK; } -nsresult -nsNPAPIPlugin::GetMIMEDescription(const char* *resultingDesc) -{ - nsresult gmdResult = mLibrary->NP_GetMIMEDescription(resultingDesc); - if (gmdResult != NS_OK) { - return gmdResult; - } - - return NS_OK; -} - -nsresult -nsNPAPIPlugin::GetValue(NPPVariable variable, void *value) -{ - PLUGIN_LOG(PLUGIN_LOG_NORMAL, - ("nsNPAPIPlugin::GetValue called: this=%p, variable=%d\n", this, variable)); - - NPError gvError; - mLibrary->NP_GetValue(nsnull, variable, value, &gvError); - - return gvError; -} - // Create a new NPP GET or POST (given in the type argument) url // stream that may have a notify callback NPError diff --git a/modules/plugin/base/src/nsNPAPIPlugin.h b/modules/plugin/base/src/nsNPAPIPlugin.h index 187f2bc310d0..e1ee1cf8aaca 100644 --- a/modules/plugin/base/src/nsNPAPIPlugin.h +++ b/modules/plugin/base/src/nsNPAPIPlugin.h @@ -104,6 +104,8 @@ public: // minidump was written. void PluginCrashed(const nsAString& pluginDumpID, const nsAString& browserDumpID); + + static PRBool RunPluginOOP(const char* aFilePath, const nsPluginTag *aPluginTag); #endif protected: diff --git a/modules/plugin/base/src/nsPluginHost.cpp b/modules/plugin/base/src/nsPluginHost.cpp index 612792bdaa5c..06321cb66dec 100644 --- a/modules/plugin/base/src/nsPluginHost.cpp +++ b/modules/plugin/base/src/nsPluginHost.cpp @@ -301,6 +301,22 @@ NS_IMETHODIMP nsPluginDocReframeEvent::Run() { return mDocs->Clear(); } +static PRBool UnloadPluginsASAP() +{ + nsresult rv; + nsCOMPtr pref(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + if (NS_SUCCEEDED(rv)) { + PRBool unloadPluginsASAP = PR_FALSE; + rv = pref->GetBoolPref("plugins.unloadASAP", &unloadPluginsASAP); + if (NS_SUCCEEDED(rv)) { + return unloadPluginsASAP; + } + } + + NS_WARNING("Unable to retrieve pref: plugins.unloadASAP"); + return PR_FALSE; +} + // helper struct for asynchronous handling of plugin unloading class nsPluginUnloadEvent : public nsRunnable { public: @@ -417,9 +433,6 @@ PRBool nsPluginHost::IsRunningPlugin(nsPluginTag * plugin) if (!plugin) return PR_FALSE; - if (!plugin->mLibrary) - return PR_FALSE; - for (int i = 0; i < plugin->mVariants; i++) { nsNPAPIPluginInstance *instance = FindInstance(plugin->mMimeTypeArray[i]); if (instance && instance->IsRunning()) @@ -867,16 +880,8 @@ void nsPluginHost::OnPluginInstanceDestroyed(nsPluginTag* aPluginTag) } } - if (!hasInstance) { - nsresult rv; - nsCOMPtr 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(); + if (!hasInstance && UnloadPluginsASAP()) { + aPluginTag->TryUnloadPlugin(); } } @@ -1270,10 +1275,8 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType, PR_LogFlush(); #endif - - nsresult result = NS_ERROR_FAILURE; - nsCOMPtr instance; - nsCOMPtr plugin; + nsresult rv = NS_ERROR_FAILURE; + const char* mimetype = nsnull; // if don't have a mimetype or no plugin can handle this mimetype @@ -1300,8 +1303,10 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType, NS_ASSERTION(pluginTag, "Must have plugin tag here!"); + nsCOMPtr plugin; GetPlugin(mimetype, getter_AddRefs(plugin)); + nsCOMPtr instance; if (plugin) { #if defined(XP_WIN) && !defined(WINCE) static BOOL firstJavaPlugin = FALSE; @@ -1311,17 +1316,18 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType, DWORD dw = GetCurrentDirectoryW(_MAX_PATH, origDir); NS_ASSERTION(dw <= _MAX_PATH, "Failed to obtain the current directory, which may lead to incorrect class loading"); nsCOMPtr binDirectory; - result = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, - getter_AddRefs(binDirectory)); + rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, + getter_AddRefs(binDirectory)); - if (NS_SUCCEEDED(result)) { + if (NS_SUCCEEDED(rv)) { nsAutoString path; binDirectory->GetPath(path); restoreOrigDir = SetCurrentDirectoryW(path.get()); } } #endif - result = plugin->CreatePluginInstance(getter_AddRefs(instance)); + + rv = plugin->CreatePluginInstance(getter_AddRefs(instance)); #if defined(XP_WIN) && !defined(WINCE) if (!firstJavaPlugin && restoreOrigDir) { @@ -1332,8 +1338,8 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType, #endif } - if (NS_FAILED(result)) - return result; + if (NS_FAILED(rv)) + return rv; // it is adreffed here aOwner->SetInstance(instance); @@ -1341,10 +1347,10 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType, // this should not addref the instance or owner // except in some cases not Java, see bug 140931 // our COM pointer will free the peer - result = instance->Initialize(aOwner, mimetype); - if (NS_FAILED(result)) { + rv = instance->Initialize(aOwner, mimetype); + if (NS_FAILED(rv)) { aOwner->SetInstance(nsnull); - return result; + return rv; } mInstances.AppendElement(static_cast(instance.get())); @@ -1356,12 +1362,12 @@ nsPluginHost::TrySetUpPluginInstance(const char *aMimeType, PR_LOG(nsPluginLogging::gPluginLog, PLUGIN_LOG_BASIC, ("nsPluginHost::TrySetupPluginInstance Finished mime=%s, rv=%d, owner=%p, url=%s\n", - aMimeType, result, aOwner, urlSpec2.get())); + aMimeType, rv, aOwner, urlSpec2.get())); PR_LogFlush(); #endif - return result; + return rv; } NS_IMETHODIMP @@ -1693,9 +1699,29 @@ static nsresult ConvertToNative(nsIUnicodeEncoder *aEncoder, return NS_OK; } -static nsresult CreateNPAPIPlugin(const nsPluginTag *aPluginTag, +static nsresult CreateNPAPIPlugin(nsPluginTag *aPluginTag, nsIPlugin **aOutNPAPIPlugin) { + // If this is an in-process plugin we'll need to load it here if we haven't already. +#ifdef MOZ_IPC + if (!aPluginTag->mLibrary && + !nsNPAPIPlugin::RunPluginOOP(aPluginTag->mFileName.get(), aPluginTag)) { +#else + if (!aPluginTag->mLibrary) { +#endif + if (aPluginTag->mFullPath.IsEmpty()) + return NS_ERROR_FAILURE; + nsCOMPtr file = do_CreateInstance("@mozilla.org/file/local;1"); + file->InitWithPath(NS_ConvertUTF8toUTF16(aPluginTag->mFullPath)); + nsPluginFile pluginFile(file); + PRLibrary* pluginLibrary = NULL; + + if (NS_FAILED(pluginFile.LoadPlugin(&pluginLibrary)) || !pluginLibrary) + return NS_ERROR_FAILURE; + + aPluginTag->mLibrary = pluginLibrary; + } + nsresult rv; nsCOMPtr pcs = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv); @@ -1766,28 +1792,12 @@ NS_IMETHODIMP nsPluginHost::GetPlugin(const char *aMimeType, nsIPlugin** aPlugin printf("For %s found plugin %s\n", aMimeType, pluginTag->mFileName.get()); #endif - if (!pluginTag->mLibrary) { // if we haven't done this yet - if (pluginTag->mFullPath.IsEmpty()) - return NS_ERROR_FAILURE; - nsCOMPtr file = do_CreateInstance("@mozilla.org/file/local;1"); - file->InitWithPath(NS_ConvertUTF8toUTF16(pluginTag->mFullPath)); - nsPluginFile pluginFile(file); - PRLibrary* pluginLibrary = NULL; - - if (pluginFile.LoadPlugin(pluginLibrary) != NS_OK || pluginLibrary == NULL) - return NS_ERROR_FAILURE; - - pluginTag->mLibrary = pluginLibrary; - } - + // Create a plugin object if necessary nsCOMPtr plugin = pluginTag->mEntryPoint; if (!plugin) { - // Now lets try to get the entry point from an NPAPI plugin rv = CreateNPAPIPlugin(pluginTag, getter_AddRefs(plugin)); if (NS_FAILED(rv)) return rv; - - NS_ASSERTION(plugin, "CreateNPAPIPlugin succeeded without setting 'plugin'"); pluginTag->mEntryPoint = plugin; } @@ -2041,18 +2051,12 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile * pluginsDir, // if it is not found in cache info list or has been changed, create a new one if (!pluginTag) { nsPluginFile pluginFile(file); - PRLibrary* pluginLibrary = nsnull; - - // load the plugin's library so we can ask it some questions, but not for Windows -#ifndef XP_WIN - if (pluginFile.LoadPlugin(pluginLibrary) != NS_OK || pluginLibrary == nsnull) - continue; -#endif // create a tag describing this plugin. + PRLibrary *library = nsnull; nsPluginInfo info; memset(&info, 0, sizeof(info)); - nsresult res = pluginFile.GetPluginInfo(info); + nsresult res = pluginFile.GetPluginInfo(info, &library); // if we don't have mime type don't proceed, this is not a plugin if (NS_FAILED(res) || !info.fMimeTypeArray) { pluginFile.FreePluginInfo(info); @@ -2061,11 +2065,10 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile * pluginsDir, pluginTag = new nsPluginTag(&info); pluginFile.FreePluginInfo(info); - - if (pluginTag == nsnull) + if (!pluginTag) return NS_ERROR_OUT_OF_MEMORY; - pluginTag->mLibrary = pluginLibrary; + pluginTag->mLibrary = library; pluginTag->mLastModifiedTime = fileModTime; nsCOMPtr blocklist = do_GetService("@mozilla.org/extensions/blocklist;1"); @@ -2100,6 +2103,13 @@ nsresult nsPluginHost::ScanPluginsDirectory(nsIFile * pluginsDir, pluginTag->mNext = mCachedPlugins; mCachedPlugins = pluginTag; } + + // Plugin unloading is tag-based. If we created a new tag and loaded + // the library in the process then we want to attempt to unload it here. + // Only do this if the pref is set for aggressive unloading. + if (UnloadPluginsASAP()) { + pluginTag->TryUnloadPlugin(); + } } // set the flag that we want to add this plugin to the list for now diff --git a/modules/plugin/base/src/nsPluginsDir.h b/modules/plugin/base/src/nsPluginsDir.h index cd16844dc98b..6e9193f33713 100644 --- a/modules/plugin/base/src/nsPluginsDir.h +++ b/modules/plugin/base/src/nsPluginsDir.h @@ -93,12 +93,13 @@ public: * Loads the plugin into memory using NSPR's shared-library loading * mechanism. Handles platform differences in loading shared libraries. */ - nsresult LoadPlugin(PRLibrary* &outLibrary); + nsresult LoadPlugin(PRLibrary **outLibrary); /** * Obtains all of the information currently available for this plugin. + * Has a library outparam which will be non-null if a library load was required. */ - nsresult GetPluginInfo(nsPluginInfo &outPluginInfo); + nsresult GetPluginInfo(nsPluginInfo &outPluginInfo, PRLibrary **outLibrary); /** * Should be called after GetPluginInfo to free all allocated stuff diff --git a/modules/plugin/base/src/nsPluginsDirBeOS.cpp b/modules/plugin/base/src/nsPluginsDirBeOS.cpp index 02031e3b7455..e0fdc72a6c51 100644 --- a/modules/plugin/base/src/nsPluginsDirBeOS.cpp +++ b/modules/plugin/base/src/nsPluginsDirBeOS.cpp @@ -139,14 +139,14 @@ nsPluginFile::~nsPluginFile() * Loads the plugin into memory using NSPR's shared-library loading * mechanism. Handles platform differences in loading shared libraries. */ -nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) +nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary) { nsCAutoString path; nsresult rv = mPlugin->GetNativePath(path); if (NS_OK != rv) { return rv; } - pLibrary = outLibrary = PR_LoadLibrary(path.get()); + pLibrary = *outLibrary = PR_LoadLibrary(path.get()); #ifdef NS_DEBUG printf("LoadPlugin() %s returned %lx\n",path,(unsigned long)pLibrary); @@ -161,8 +161,10 @@ typedef char* (*BeOS_Plugin_GetMIMEDescription)(); /** * Obtains all of the information currently available for this plugin. */ -nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info) +nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary) { + *outLibrary = nsnull; + info.fVersion = nsnull; nsCAutoString fullPath; diff --git a/modules/plugin/base/src/nsPluginsDirDarwin.cpp b/modules/plugin/base/src/nsPluginsDirDarwin.cpp index 24e6500acbd3..2ebb0b56e78b 100644 --- a/modules/plugin/base/src/nsPluginsDirDarwin.cpp +++ b/modules/plugin/base/src/nsPluginsDirDarwin.cpp @@ -220,7 +220,7 @@ nsPluginFile::nsPluginFile(nsIFile *spec) nsPluginFile::~nsPluginFile() {} -nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) +nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary) { if (!mPlugin) return NS_ERROR_NULL_POINTER; @@ -261,9 +261,9 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) const char *executablePath = bundlePath.get(); #endif - outLibrary = PR_LoadLibrary(executablePath); - pLibrary = outLibrary; - if (!outLibrary) { + *outLibrary = PR_LoadLibrary(executablePath); + pLibrary = *outLibrary; + if (!pLibrary) { return NS_ERROR_FAILURE; } #ifdef DEBUG @@ -350,17 +350,17 @@ private: /** * Obtains all of the information currently available for this plugin. */ -nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info) +nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary) { + *outLibrary = nsnull; + nsresult rv = NS_OK; // clear out the info, except for the first field. memset(&info, 0, sizeof(info)); - // First open up resource we can use to get plugin info. - #ifndef __LP64__ - // Try to open a resource fork. + // Try to open a resource fork in case we have to use it. nsAutoCloseResourceObject resourceObject(mPlugin); bool resourceOpened = resourceObject.ResourceOpened(); #endif @@ -428,7 +428,7 @@ nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info) ParsePlistPluginInfo(info, bundle); ::CFRelease(bundle); if (info.fVariantCount > 0) - return NS_OK; + return NS_OK; } // It's possible that our plugin has 2 entry points that'll give us mime type @@ -436,6 +436,11 @@ nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info) // change mime info in the resource fork. We need to use this info instead of // the resource. See bug 113464. + // Sadly we have to load the library for this to work. + rv = LoadPlugin(outLibrary); + if (NS_FAILED(rv)) + return rv; + // Try to get data from NP_GetMIMEDescription if (pLibrary) { NP_GETMIMEDESCRIPTION pfnGetMimeDesc = (NP_GETMIMEDESCRIPTION)PR_FindFunctionSymbol(pLibrary, NP_GETMIMEDESCRIPTION_NAME); diff --git a/modules/plugin/base/src/nsPluginsDirOS2.cpp b/modules/plugin/base/src/nsPluginsDirOS2.cpp index 95ebfafcd5b1..7e64cb48df3f 100644 --- a/modules/plugin/base/src/nsPluginsDirOS2.cpp +++ b/modules/plugin/base/src/nsPluginsDirOS2.cpp @@ -199,7 +199,7 @@ nsPluginFile::~nsPluginFile() {} // Loads the plugin into memory using NSPR's shared-library loading -nsresult nsPluginFile::LoadPlugin( PRLibrary *&outLibrary) +nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary) { if (!mPlugin) return NS_ERROR_NULL_POINTER; @@ -207,13 +207,15 @@ nsresult nsPluginFile::LoadPlugin( PRLibrary *&outLibrary) nsCAutoString temp; mPlugin->GetNativePath(temp); - outLibrary = PR_LoadLibrary(temp.get()); - return outLibrary == nsnull ? NS_ERROR_FAILURE : NS_OK; + *outLibrary = PR_LoadLibrary(temp.get()); + return *outLibrary == nsnull ? NS_ERROR_FAILURE : NS_OK; } // Obtains all of the information currently available for this plugin. -nsresult nsPluginFile::GetPluginInfo( nsPluginInfo &info) +nsresult nsPluginFile::GetPluginInfo(nsPluginInfo &info, PRLibrary **outLibrary) { + *outLibrary = nsnull; + nsresult rv = NS_ERROR_FAILURE; HMODULE hPlug = 0; // Need a HMODULE to query resource statements char failure[ CCHMAXPATH] = ""; diff --git a/modules/plugin/base/src/nsPluginsDirUnix.cpp b/modules/plugin/base/src/nsPluginsDirUnix.cpp index add6d7eccd00..75344a279e5a 100644 --- a/modules/plugin/base/src/nsPluginsDirUnix.cpp +++ b/modules/plugin/base/src/nsPluginsDirUnix.cpp @@ -272,7 +272,7 @@ nsPluginFile::~nsPluginFile() { } -nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) +nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary) { PRLibSpec libSpec; libSpec.type = PR_LibSpec_Pathname; @@ -305,20 +305,24 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) #if defined(SOLARIS) || defined(HPUX) // Acrobat/libXm: Lazy resolving might cause crash later (bug 211587) - pLibrary = outLibrary = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW); + *outLibrary = PR_LoadLibraryWithFlags(libSpec, PR_LD_NOW); + pLibrary = *outLibrary; #else // Some dlopen() doesn't recover from a failed PR_LD_NOW (bug 223744) - pLibrary = outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); + *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); + pLibrary = *outLibrary; #endif if (!pLibrary) { LoadExtraSharedLibs(); // try reload plugin once more - pLibrary = outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); + *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); + pLibrary = *outLibrary; if (!pLibrary) DisplayPR_LoadLibraryErrorMessage(libSpec.value.pathname); } #else - pLibrary = outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); + *outLibrary = PR_LoadLibraryWithFlags(libSpec, 0); + pLibrary = *outLibrary; #endif // MOZ_WIDGET_GTK2 #ifdef NS_DEBUG @@ -329,53 +333,72 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) return NS_OK; } -nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info) +nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary) { + *outLibrary = nsnull; + info.fVersion = nsnull; - // Passing NULL for a file path will prevent a call to NP_Initialize. - nsCOMPtr plugin; - nsresult rv = nsNPAPIPlugin::CreatePlugin(NULL, pLibrary, getter_AddRefs(plugin)); + // Sadly we have to load the library for this to work. + nsresult rv = LoadPlugin(outLibrary); if (NS_FAILED(rv)) - return rv; + return rv; + + const char* (*npGetPluginVersion)() = + (const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetPluginVersion"); + if (npGetPluginVersion) { + info.fVersion = PL_strdup(npGetPluginVersion()); + } - if (plugin) { - const char* (*npGetPluginVersion)() = - (const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetPluginVersion"); - if (npGetPluginVersion) - info.fVersion = PL_strdup(npGetPluginVersion()); + const char* (*npGetMIMEDescription)() = + (const char* (*)()) PR_FindFunctionSymbol(pLibrary, "NP_GetMIMEDescription"); + if (!npGetMIMEDescription) { + return NS_ERROR_FAILURE; + } - const char *mimedescr = NULL; - plugin->GetMIMEDescription(&mimedescr); -#ifdef NS_DEBUG - printf("GetMIMEDescription() returned \"%s\"\n", mimedescr); -#endif - if (NS_FAILED(rv = ParsePluginMimeDescription(mimedescr, info))) - return rv; + const char* mimedescr = npGetMIMEDescription(); + if (!mimedescr) { + return NS_ERROR_FAILURE; + } - nsCAutoString path; - if (NS_FAILED(rv = mPlugin->GetNativePath(path))) - return rv; - info.fFullPath = PL_strdup(path.get()); + rv = ParsePluginMimeDescription(mimedescr, info); + if (NS_FAILED(rv)) { + return rv; + } - nsCAutoString fileName; - if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName))) - return rv; - info.fFileName = PL_strdup(fileName.get()); + nsCAutoString path; + if (NS_FAILED(rv = mPlugin->GetNativePath(path))) + return rv; + info.fFullPath = PL_strdup(path.get()); - const char *name = NULL; - plugin->GetValue(NPPVpluginNameString, &name); - if (name) - info.fName = PL_strdup(name); - else - info.fName = PL_strdup(fileName.get()); + nsCAutoString fileName; + if (NS_FAILED(rv = mPlugin->GetNativeLeafName(fileName))) + return rv; + info.fFileName = PL_strdup(fileName.get()); - const char *description = NULL; - plugin->GetValue(NPPVpluginDescriptionString, &description); - if (!description) - description = ""; + NP_GetValueFunc npGetValue = (NP_GetValueFunc)PR_FindFunctionSymbol(pLibrary, "NP_GetValue"); + if (!npGetValue) { + return NS_ERROR_FAILURE; + } + + const char *name = NULL; + NPError nperr = npGetValue(NULL, NPPVpluginNameString, &name); + if (name) { + info.fName = PL_strdup(name); + } + else { + info.fName = PL_strdup(fileName.get()); + } + + const char *description = NULL; + nperr = npGetValue(NULL, NPPVpluginDescriptionString, &description); + if (description) { info.fDescription = PL_strdup(description); } + else { + info.fDescription = ""; + } + return NS_OK; } diff --git a/modules/plugin/base/src/nsPluginsDirWin.cpp b/modules/plugin/base/src/nsPluginsDirWin.cpp index bcfa4ab7f497..7bae5ab28368 100644 --- a/modules/plugin/base/src/nsPluginsDirWin.cpp +++ b/modules/plugin/base/src/nsPluginsDirWin.cpp @@ -259,7 +259,7 @@ nsPluginFile::~nsPluginFile() * Loads the plugin into memory using NSPR's shared-library loading * mechanism. Handles platform differences in loading shared libraries. */ -nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) +nsresult nsPluginFile::LoadPlugin(PRLibrary **outLibrary) { nsCOMPtr plugin = do_QueryInterface(mPlugin); @@ -287,9 +287,9 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) } #endif - nsresult rv = plugin->Load(&outLibrary); + nsresult rv = plugin->Load(outLibrary); if (NS_FAILED(rv)) - outLibrary = NULL; + *outLibrary = NULL; #ifndef WINCE if (restoreOrigDir) { @@ -304,8 +304,10 @@ nsresult nsPluginFile::LoadPlugin(PRLibrary* &outLibrary) /** * Obtains all of the information currently available for this plugin. */ -nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info) +nsresult nsPluginFile::GetPluginInfo(nsPluginInfo& info, PRLibrary **outLibrary) { + *outLibrary = nsnull; + nsresult rv = NS_OK; DWORD zerome, versionsize; WCHAR* verbuf = nsnull;