Improve plugin loading code, make it more efficient and easier to understand. Allow Mac OS X plugins to modify their NPAPI function table. b=543405 r=jst
This commit is contained in:
Родитель
bcf48bea34
Коммит
aaff52da2b
|
@ -47,7 +47,7 @@
|
|||
|
||||
interface nsIPluginInstance;
|
||||
|
||||
[uuid(15246FD3-29FB-4354-8811-AD8B53661B71)]
|
||||
[uuid(843D6092-2BB0-4A21-8827-0510A52CA795)]
|
||||
interface nsIPlugin : nsISupports
|
||||
{
|
||||
/**
|
||||
|
@ -57,17 +57,6 @@ interface nsIPlugin : nsISupports
|
|||
*/
|
||||
void createPluginInstance(out nsIPluginInstance aResult);
|
||||
|
||||
/**
|
||||
* Initializes the plugin and will be called before any new instances are
|
||||
* created. It is passed browserInterfaces on which QueryInterface
|
||||
* may be used to obtain an nsIPluginManager, and other interfaces.
|
||||
*
|
||||
* @param browserInterfaces - an object that allows access to other browser
|
||||
* interfaces via QueryInterface
|
||||
* @result - NS_OK if this operation was successful
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
/**
|
||||
* Called when the browser is done with the plugin factory, or when
|
||||
* the plugin is disabled by the user.
|
||||
|
|
|
@ -201,8 +201,7 @@ void NS_NotifyPluginCall(PRIntervalTime startTime)
|
|||
runTime);
|
||||
}
|
||||
|
||||
void
|
||||
nsNPAPIPlugin::CheckClassInitialized()
|
||||
static void CheckClassInitialized()
|
||||
{
|
||||
static PRBool initialized = PR_FALSE;
|
||||
|
||||
|
@ -219,68 +218,16 @@ nsNPAPIPlugin::CheckClassInitialized()
|
|||
|
||||
NS_IMPL_ISUPPORTS1(nsNPAPIPlugin, nsIPlugin)
|
||||
|
||||
nsNPAPIPlugin::nsNPAPIPlugin(NPPluginFuncs* callbacks,
|
||||
PluginLibrary* aLibrary)
|
||||
nsNPAPIPlugin::nsNPAPIPlugin()
|
||||
{
|
||||
memset((void*) &mPluginFuncs, 0, sizeof(mPluginFuncs));
|
||||
|
||||
mPluginFuncs.size = sizeof(mPluginFuncs);
|
||||
mLibrary = nsnull;
|
||||
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
// On Windows and OS/2 we need to keep a direct reference to
|
||||
// the plugin's function struct, we can't just copy it. See
|
||||
// Mozilla bug 85334.
|
||||
|
||||
NPError gepError;
|
||||
nsresult gepResult = aLibrary->NP_GetEntryPoints(&mPluginFuncs, &gepError);
|
||||
if (gepResult != NS_OK || gepError != NPERR_NO_ERROR)
|
||||
return;
|
||||
|
||||
NS_ASSERTION(HIBYTE(mPluginFuncs.version) >= NP_VERSION_MAJOR,
|
||||
"callback version is less than NP version");
|
||||
|
||||
#elif defined(XP_MACOSX)
|
||||
NPPluginFuncs np_callbacks;
|
||||
memset((void*) &np_callbacks, 0, sizeof(np_callbacks));
|
||||
np_callbacks.size = sizeof(np_callbacks);
|
||||
|
||||
if (!aLibrary->HasRequiredFunctions()) {
|
||||
NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
|
||||
return;
|
||||
}
|
||||
|
||||
// we call NP_Initialize before getting function pointers to match
|
||||
// WebKit's behavior. They implemented this first on Mac OS X.
|
||||
NPError initError;
|
||||
nsresult initResult = aLibrary->NP_Initialize(&(sBrowserFuncs), &initError);
|
||||
if (initResult != NS_OK || initError != NPERR_NO_ERROR)
|
||||
return;
|
||||
NPError gepError;
|
||||
nsresult gepResult = aLibrary->NP_GetEntryPoints(&np_callbacks, &gepError);
|
||||
if (gepResult != NS_OK || gepError != NPERR_NO_ERROR)
|
||||
return;
|
||||
|
||||
mPluginFuncs.version = np_callbacks.version;
|
||||
mPluginFuncs.newp = (NPP_NewProcPtr)np_callbacks.newp;
|
||||
mPluginFuncs.destroy = (NPP_DestroyProcPtr)np_callbacks.destroy;
|
||||
mPluginFuncs.setwindow = (NPP_SetWindowProcPtr)np_callbacks.setwindow;
|
||||
mPluginFuncs.newstream = (NPP_NewStreamProcPtr)np_callbacks.newstream;
|
||||
mPluginFuncs.destroystream = (NPP_DestroyStreamProcPtr)np_callbacks.destroystream;
|
||||
mPluginFuncs.asfile = (NPP_StreamAsFileProcPtr)np_callbacks.asfile;
|
||||
mPluginFuncs.writeready = (NPP_WriteReadyProcPtr)np_callbacks.writeready;
|
||||
mPluginFuncs.write = (NPP_WriteProcPtr)np_callbacks.write;
|
||||
mPluginFuncs.print = (NPP_PrintProcPtr)np_callbacks.print;
|
||||
mPluginFuncs.event = (NPP_HandleEventProcPtr)np_callbacks.event;
|
||||
mPluginFuncs.urlnotify = (NPP_URLNotifyProcPtr)np_callbacks.urlnotify;
|
||||
mPluginFuncs.getvalue = (NPP_GetValueProcPtr)np_callbacks.getvalue;
|
||||
mPluginFuncs.setvalue = (NPP_SetValueProcPtr)np_callbacks.setvalue;
|
||||
#else // for everyone else
|
||||
memcpy((void*) &mPluginFuncs, (void*) callbacks, sizeof(mPluginFuncs));
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
mPluginRefNum = -1;
|
||||
#endif
|
||||
|
||||
mLibrary = aLibrary;
|
||||
mLibrary->SetPlugin(this);
|
||||
memset((void*)&mPluginFuncs, 0, sizeof(mPluginFuncs));
|
||||
mPluginFuncs.size = sizeof(mPluginFuncs);
|
||||
|
||||
mLibrary = nsnull;
|
||||
}
|
||||
|
||||
nsNPAPIPlugin::~nsNPAPIPlugin()
|
||||
|
@ -288,10 +235,9 @@ nsNPAPIPlugin::~nsNPAPIPlugin()
|
|||
// reset the callbacks list
|
||||
memset((void*) &mPluginFuncs, 0, sizeof(mPluginFuncs));
|
||||
delete mLibrary;
|
||||
mLibrary = NULL;
|
||||
mLibrary = nsnull;
|
||||
}
|
||||
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
void
|
||||
nsNPAPIPlugin::SetPluginRefNum(short aRefNum)
|
||||
|
@ -419,235 +365,78 @@ GetNewPluginLibrary(const char* aFilePath,
|
|||
|
||||
} /* anonymous namespace */
|
||||
|
||||
// Creates the nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
|
||||
// Creates an nsNPAPIPlugin object. One nsNPAPIPlugin object exists per plugin (not instance).
|
||||
nsresult
|
||||
nsNPAPIPlugin::CreatePlugin(const char* aFilePath, PRLibrary* aLibrary,
|
||||
nsIPlugin** aResult)
|
||||
{
|
||||
*aResult = nsnull;
|
||||
|
||||
CheckClassInitialized();
|
||||
|
||||
#if defined(XP_UNIX) && !defined(XP_MACOSX)
|
||||
nsNPAPIPlugin *plptr;
|
||||
|
||||
NPPluginFuncs callbacks;
|
||||
memset((void*) &callbacks, 0, sizeof(callbacks));
|
||||
callbacks.size = sizeof(callbacks);
|
||||
|
||||
PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
|
||||
|
||||
// create the new plugin handler
|
||||
*aResult = plptr = new nsNPAPIPlugin(&callbacks, pluginLib);
|
||||
|
||||
if (*aResult == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
// Do not initialize if the file path is NULL.
|
||||
if (!aFilePath)
|
||||
return NS_OK;
|
||||
|
||||
// we must init here because the plugin may call NPN functions
|
||||
// when we call into the NP_Initialize entry point - NPN functions
|
||||
// require that mBrowserManager be set up
|
||||
plptr->Initialize();
|
||||
|
||||
NPError initError;
|
||||
nsresult initResult = pluginLib->NP_Initialize(&(sBrowserFuncs),&callbacks, &initError);
|
||||
if (initResult != NS_OK || initError != NPERR_NO_ERROR) {
|
||||
NS_RELEASE(*aResult);
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
// now copy function table back to nsNPAPIPlugin instance
|
||||
memcpy((void*) &(plptr->mPluginFuncs), (void*)&callbacks, sizeof(callbacks));
|
||||
#endif
|
||||
|
||||
#ifdef XP_WIN
|
||||
PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
|
||||
|
||||
// Note: on Windows, we must use the fCallback because plugins may
|
||||
// change the function table. The Shockwave installer makes changes
|
||||
// in the table while running
|
||||
*aResult = new nsNPAPIPlugin(nsnull, pluginLib);
|
||||
|
||||
if (*aResult == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
// we must init here because the plugin may call NPN functions
|
||||
// when we call into the NP_Initialize entry point - NPN functions
|
||||
// require that mBrowserManager be set up
|
||||
if (NS_FAILED((*aResult)->Initialize())) {
|
||||
NS_RELEASE(*aResult);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NPError initError;
|
||||
nsresult initResult = pluginLib->NP_Initialize(&(sBrowserFuncs), &initError);
|
||||
if (initResult != NS_OK || initError != NPERR_NO_ERROR)
|
||||
return NS_ERROR_FAILURE;
|
||||
#endif
|
||||
|
||||
#ifdef XP_OS2
|
||||
PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
|
||||
|
||||
// create the new plugin handler
|
||||
*aResult = new nsNPAPIPlugin(nsnull, pluginLib);
|
||||
|
||||
if (*aResult == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
// we must init here because the plugin may call NPN functions
|
||||
// when we call into the NP_Initialize entry point - NPN functions
|
||||
// require that mBrowserManager be set up
|
||||
if (NS_FAILED((*aResult)->Initialize())) {
|
||||
NS_RELEASE(*aResult);
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
NP_PLUGININIT pfnInitialize =
|
||||
(NP_PLUGININIT)PR_FindSymbol(aLibrary, "NP_Initialize");
|
||||
|
||||
if (!pfnInitialize)
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
// Fixes problem where the OS/2 native multimedia plugins weren't
|
||||
// working on mozilla though did work on 4.x. Problem is that they
|
||||
// expect the current working directory to be the plugins dir.
|
||||
// Since these plugins are no longer maintained and they represent
|
||||
// the majority of the OS/2 plugin contingency, we'll have to make
|
||||
// them work here.
|
||||
|
||||
#define MAP_DISKNUM_TO_LETTER(n) ('A' + (n - 1))
|
||||
#define MAP_LETTER_TO_DISKNUM(c) (toupper(c)-'A'+1)
|
||||
|
||||
unsigned long origDiskNum, pluginDiskNum, logicalDisk;
|
||||
|
||||
char pluginPath[CCHMAXPATH], origPath[CCHMAXPATH];
|
||||
strcpy(pluginPath, aFilePath);
|
||||
char* slash = strrchr(pluginPath, '\\');
|
||||
*slash = '\0';
|
||||
|
||||
DosQueryCurrentDisk( &origDiskNum, &logicalDisk );
|
||||
pluginDiskNum = MAP_LETTER_TO_DISKNUM(pluginPath[0]);
|
||||
|
||||
origPath[0] = MAP_DISKNUM_TO_LETTER(origDiskNum);
|
||||
origPath[1] = ':';
|
||||
origPath[2] = '\\';
|
||||
|
||||
ULONG len = CCHMAXPATH-3;
|
||||
APIRET rc = DosQueryCurrentDir(0, &origPath[3], &len);
|
||||
NS_ASSERTION(NO_ERROR == rc,"DosQueryCurrentDir failed");
|
||||
|
||||
BOOL bChangedDir = FALSE;
|
||||
BOOL bChangedDisk = FALSE;
|
||||
if (pluginDiskNum != origDiskNum) {
|
||||
rc = DosSetDefaultDisk(pluginDiskNum);
|
||||
NS_ASSERTION(NO_ERROR == rc,"DosSetDefaultDisk failed");
|
||||
bChangedDisk = TRUE;
|
||||
}
|
||||
|
||||
if (stricmp(origPath, pluginPath) != 0) {
|
||||
rc = DosSetCurrentDir(pluginPath);
|
||||
NS_ASSERTION(NO_ERROR == rc,"DosSetCurrentDir failed");
|
||||
bChangedDir = TRUE;
|
||||
}
|
||||
|
||||
nsresult rv = pfnInitialize(&(sBrowserFuncs));
|
||||
|
||||
if (bChangedDisk) {
|
||||
rc= DosSetDefaultDisk(origDiskNum);
|
||||
NS_ASSERTION(NO_ERROR == rc,"DosSetDefaultDisk failed");
|
||||
}
|
||||
if (bChangedDir) {
|
||||
rc = DosSetCurrentDir(origPath);
|
||||
NS_ASSERTION(NO_ERROR == rc,"DosSetCurrentDir failed");
|
||||
}
|
||||
|
||||
if (!NS_SUCCEEDED(rv)) {
|
||||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(XP_MACOSX)
|
||||
#ifndef __LP64__
|
||||
short appRefNum = ::CurResFile();
|
||||
short pluginRefNum;
|
||||
|
||||
nsCOMPtr<nsILocalFile> pluginPath;
|
||||
NS_NewNativeLocalFile(nsDependentCString(aFilePath), PR_TRUE,
|
||||
getter_AddRefs(pluginPath));
|
||||
nsPluginFile pluginFile(pluginPath);
|
||||
|
||||
pluginRefNum = pluginFile.OpenPluginResource();
|
||||
#endif
|
||||
|
||||
PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
|
||||
nsNPAPIPlugin* plugin = new nsNPAPIPlugin(nsnull, pluginLib);
|
||||
#ifndef __LP64__
|
||||
::UseResFile(appRefNum);
|
||||
#endif
|
||||
nsRefPtr<nsNPAPIPlugin> plugin = new nsNPAPIPlugin();
|
||||
if (!plugin)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
*aResult = plugin;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
if (NS_FAILED((*aResult)->Initialize())) {
|
||||
NS_RELEASE(*aResult);
|
||||
PluginLibrary* pluginLib = GetNewPluginLibrary(aFilePath, aLibrary);
|
||||
if (!pluginLib) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifndef __LP64__
|
||||
plugin->SetPluginRefNum(pluginRefNum);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef XP_BEOS
|
||||
// I just copied UNIX version.
|
||||
// Makoto Hamanaka <VYA04230@nifty.com>
|
||||
|
||||
// XXX this code won't compile with the new e10s changes
|
||||
|
||||
nsNPAPIPlugin *plptr;
|
||||
|
||||
NPPluginFuncs callbacks;
|
||||
memset((void*) &callbacks, 0, sizeof(callbacks));
|
||||
callbacks.size = sizeof(callbacks);
|
||||
|
||||
NP_PLUGINSHUTDOWN pfnShutdown =
|
||||
(NP_PLUGINSHUTDOWN)PR_FindSymbol(aLibrary, "NP_Shutdown");
|
||||
|
||||
// create the new plugin handler
|
||||
*aResult = plptr = new nsNPAPIPlugin(&callbacks, aLibrary, pfnShutdown);
|
||||
|
||||
if (*aResult == NULL)
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
|
||||
NS_ADDREF(*aResult);
|
||||
|
||||
// we must init here because the plugin may call NPN functions
|
||||
// when we call into the NP_Initialize entry point - NPN functions
|
||||
// require that mBrowserManager be set up
|
||||
plptr->Initialize();
|
||||
|
||||
NP_PLUGINUNIXINIT pfnInitialize =
|
||||
(NP_PLUGINUNIXINIT)PR_FindSymbol(aLibrary, "NP_Initialize");
|
||||
|
||||
if (!pfnInitialize)
|
||||
#ifdef XP_MACOSX
|
||||
if (!pluginLib->HasRequiredFunctions()) {
|
||||
NS_WARNING("Not all necessary functions exposed by plugin, it will not load.");
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
if (pfnInitialize(&(sBrowserFuncs),&callbacks) != NS_OK)
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// now copy function table back to nsNPAPIPlugin instance
|
||||
memcpy((void*) &(plptr->mPluginFuncs), (void*)&callbacks, sizeof(callbacks));
|
||||
}
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
// Exchange NPAPI entry points.
|
||||
#if defined(XP_WIN) || defined(XP_OS2)
|
||||
// NP_GetEntryPoints must be called before NP_Initialize on Windows.
|
||||
rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
|
||||
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// NP_Initialize must be called after NP_GetEntryPoints on Windows.
|
||||
rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
|
||||
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#elif defined(XP_MACOSX)
|
||||
// NP_Initialize must be called before NP_GetEntryPoints on Mac OS X.
|
||||
// We need to match WebKit's behavior.
|
||||
rv = pluginLib->NP_Initialize(&sBrowserFuncs, &pluginCallError);
|
||||
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
rv = pluginLib->NP_GetEntryPoints(&plugin->mPluginFuncs, &pluginCallError);
|
||||
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#else
|
||||
rv = pluginLib->NP_Initialize(&sBrowserFuncs, &plugin->mPluginFuncs, &pluginCallError);
|
||||
if (rv != NS_OK || pluginCallError != NPERR_NO_ERROR) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
*aResult = plugin.forget().get();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -669,14 +458,6 @@ nsNPAPIPlugin::CreatePluginInstance(nsIPluginInstance **aResult)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNPAPIPlugin::Initialize()
|
||||
{
|
||||
if (!mLibrary)
|
||||
return NS_ERROR_FAILURE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsNPAPIPlugin::Shutdown()
|
||||
{
|
||||
|
|
|
@ -76,8 +76,7 @@ private:
|
|||
typedef mozilla::PluginLibrary PluginLibrary;
|
||||
|
||||
public:
|
||||
nsNPAPIPlugin(NPPluginFuncs* callbacks,
|
||||
PluginLibrary* aLibrary /*assume ownership*/);
|
||||
nsNPAPIPlugin();
|
||||
virtual ~nsNPAPIPlugin();
|
||||
|
||||
NS_DECL_ISUPPORTS
|
||||
|
@ -87,7 +86,8 @@ public:
|
|||
// will prevent this from calling NP_Initialize.
|
||||
static nsresult CreatePlugin(const char* aFilePath, PRLibrary* aLibrary,
|
||||
nsIPlugin** aResult);
|
||||
#ifdef XP_MACOSX
|
||||
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
void SetPluginRefNum(short aRefNum);
|
||||
#endif
|
||||
|
||||
|
@ -101,15 +101,11 @@ public:
|
|||
#endif
|
||||
|
||||
protected:
|
||||
// Ensures that the static browser functions are properly initialized
|
||||
static void CheckClassInitialized();
|
||||
|
||||
#ifdef XP_MACOSX
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
short mPluginRefNum;
|
||||
#endif
|
||||
|
||||
// The plugin-side callbacks that the browser calls. One set of
|
||||
// plugin callbacks for each plugin.
|
||||
NPPluginFuncs mPluginFuncs;
|
||||
PluginLibrary* mLibrary;
|
||||
};
|
||||
|
|
|
@ -3040,9 +3040,28 @@ static nsresult CreateNPAPIPlugin(const nsPluginTag *aPluginTag,
|
|||
fullPath = aPluginTag->mFullPath;
|
||||
}
|
||||
|
||||
return nsNPAPIPlugin::CreatePlugin(fullPath.get(),
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
short appRefNum = ::CurResFile();
|
||||
nsCOMPtr<nsILocalFile> pluginPath;
|
||||
NS_NewNativeLocalFile(nsDependentCString(fullPath.get()), PR_TRUE,
|
||||
getter_AddRefs(pluginPath));
|
||||
nsPluginFile pluginFile(pluginPath);
|
||||
short pluginRefNum = pluginFile.OpenPluginResource();
|
||||
#endif
|
||||
|
||||
rv = nsNPAPIPlugin::CreatePlugin(fullPath.get(),
|
||||
aPluginTag->mLibrary,
|
||||
aOutNPAPIPlugin);
|
||||
|
||||
#if defined(XP_MACOSX) && !defined(__LP64__)
|
||||
if (NS_SUCCEEDED(rv))
|
||||
static_cast<nsNPAPIPlugin*>(*aOutNPAPIPlugin)->SetPluginRefNum(pluginRefNum);
|
||||
else if (pluginRefNum > 0)
|
||||
::CloseResFile(pluginRefNum);
|
||||
::UseResFile(appRefNum);
|
||||
#endif
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsPluginHost::GetPlugin(const char *aMimeType, nsIPlugin** aPlugin)
|
||||
|
|
Загрузка…
Ссылка в новой задаче