gecko-dev/modules/plugin/nglsrc/nsPluginHostImpl.cpp

1596 строки
38 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "nsPluginHostImpl.h"
#include <stdio.h>
#include "prio.h"
#include "prmem.h"
#include "ns4xPlugin.h"
#include "nsMalloc.h" //this is evil...
#include "nsPluginInstancePeer.h"
#include "nsPluginStreamPeer.h"
#include "nsIStreamListener.h"
#include "nsIURL.h"
#include "nsIInputStream.h"
#include "prprf.h"
#include "gui.h"
#ifdef XP_PC
#include "windows.h"
#include "winbase.h"
#endif
static NS_DEFINE_IID(kIPluginInstanceIID, NS_IPLUGININSTANCE_IID);
static NS_DEFINE_IID(kIPluginInstancePeerIID, NS_IPLUGININSTANCEPEER_IID);
static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID);
static NS_DEFINE_IID(kIPluginManager2IID, NS_IPLUGINMANAGER2_IID);
static NS_DEFINE_IID(kIPluginHostIID, NS_IPLUGINHOST_IID);
static NS_DEFINE_IID(kIPluginStreamPeerIID, NS_IPLUGINSTREAMPEER_IID);
static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID);
static NS_DEFINE_IID(kIMallocIID, NS_IMALLOC_IID);
static NS_DEFINE_IID(kIFactoryIID, NS_IFACTORY_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
static NS_DEFINE_IID(kIStreamListenerIID, NS_ISTREAMLISTENER_IID);
static NS_DEFINE_IID(kIStreamObserverIID, NS_ISTREAMOBSERVER_IID);
nsPluginTag :: nsPluginTag()
{
mNext = nsnull;
mName = nsnull;
mDescription = nsnull;
mMimeType = nsnull;
mMimeDescription = nsnull;
mExtensions = nsnull;
mVariants = 0;
mMimeTypeArray = nsnull;
mMimeDescriptionArray = nsnull;
mExtensionsArray = nsnull;
mLibrary = nsnull;
mEntryPoint = nsnull;
mFlags = NS_PLUGIN_FLAG_ENABLED;
}
nsPluginTag :: ~nsPluginTag()
{
NS_IF_RELEASE(mEntryPoint);
if (nsnull != mName)
{
PR_Free(mName);
mName = nsnull;
}
if (nsnull != mDescription)
{
PR_Free(mDescription);
mDescription = nsnull;
}
if (nsnull != mMimeType)
{
PR_Free(mMimeType);
mMimeType = nsnull;
}
if (nsnull != mMimeDescription)
{
PR_Free(mMimeDescription);
mMimeDescription = nsnull;
}
if (nsnull != mExtensions)
{
PR_Free(mExtensions);
mExtensions = nsnull;
}
if (nsnull != mMimeTypeArray)
{
PR_Free(mMimeTypeArray);
mMimeTypeArray = nsnull;
}
if (nsnull != mMimeDescriptionArray)
{
PR_Free(mMimeDescriptionArray);
mMimeDescriptionArray = nsnull;
}
if (nsnull != mExtensionsArray)
{
PR_Free(mExtensionsArray);
mExtensionsArray = nsnull;
}
if (nsnull != mLibrary)
{
PR_UnloadLibrary(mLibrary);
mLibrary = nsnull;
}
}
class nsPluginStreamListener : public nsIStreamListener
{
public:
nsPluginStreamListener();
~nsPluginStreamListener();
NS_DECL_ISUPPORTS
//nsIStreamObserver interface
NS_IMETHOD OnStartBinding(nsIURL* aURL, const char *aContentType);
NS_IMETHOD OnProgress(nsIURL* aURL, PRInt32 aProgress, PRInt32 aProgressMax);
NS_IMETHOD OnStatus(nsIURL* aURL, const nsString &aMsg);
NS_IMETHOD OnStopBinding(nsIURL* aURL, PRInt32 aStatus, const nsString &aMsg);
//nsIStreamListener interface
NS_IMETHOD GetBindInfo(nsIURL* aURL);
NS_IMETHOD OnDataAvailable(nsIURL* aURL, nsIInputStream *aIStream,
PRInt32 aLength);
//locals
nsresult Initialize(nsIURL *aURL, nsIPluginInstance *aInstance, void *aNotifyData);
nsresult Initialize(nsIURL *aURL, nsIPluginInstanceOwner *aOwner,
nsIPluginHost *aHost, void *aNotifyData);
nsresult Initialize(nsIPluginInstance *aInstance, void *aNotifyData);
private:
nsIURL *mURL;
nsPluginStreamPeer *mPeer;
nsIPluginInstanceOwner *mOwner;
nsIPluginInstance *mInstance;
PRBool mBound;
nsIPluginStream *mStream;
char *mMIMEType;
PRUint8 *mBuffer;
PRUint32 mBufSize;
void *mNotifyData;
nsIPluginHost *mHost;
PRInt32 mLength;
PRBool mGotProgress;
nsPluginStreamType mStreamType;
FILE *mStreamFile;
};
nsPluginStreamListener :: nsPluginStreamListener()
{
NS_INIT_REFCNT();
mURL = nsnull;
mPeer = nsnull;
mOwner = nsnull;
mInstance = nsnull;
mBound = PR_FALSE;
mStream = nsnull;
mMIMEType = nsnull;
mBuffer = nsnull;
mBufSize = 0;
mNotifyData = nsnull;
mHost = nsnull;
mLength = 0;
mGotProgress = PR_FALSE;
mStreamType = nsPluginStreamType_Normal;
mStreamFile = nsnull;
}
nsPluginStreamListener :: ~nsPluginStreamListener()
{
#ifdef NS_DEBUG
printf("killing stream for %s\n", mURL ? mURL->GetSpec() : "(unknown URL)");
#endif
NS_IF_RELEASE(mURL);
NS_IF_RELEASE(mOwner);
NS_IF_RELEASE(mInstance);
NS_IF_RELEASE(mStream);
NS_IF_RELEASE(mPeer);
if (nsnull != mMIMEType)
{
PR_Free(mMIMEType);
mMIMEType = nsnull;
}
if (nsnull != mBuffer)
{
PR_Free(mBuffer);
mBuffer = nsnull;
}
mNotifyData = nsnull;
NS_IF_RELEASE(mHost);
if (nsnull != mStreamFile)
{
fclose(mStreamFile);
mStreamFile = nsnull;
}
}
NS_IMPL_ADDREF(nsPluginStreamListener)
NS_IMPL_RELEASE(nsPluginStreamListener)
nsresult nsPluginStreamListener :: QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
if (nsnull == aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(kIStreamListenerIID))
{
*aInstancePtrResult = (void *)((nsIStreamListener *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIStreamObserverIID))
{
*aInstancePtrResult = (void *)((nsIStreamObserver *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kISupportsIID))
{
*aInstancePtrResult = (void *)((nsISupports *)((nsIStreamListener *)this));
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
nsresult nsPluginStreamListener :: Initialize(nsIURL *aURL, nsIPluginInstance *aInstance, void *aNotifyData)
{
#ifdef NS_DEBUG
printf("created stream for %s\n", aURL->GetSpec());
#endif
mURL = aURL;
NS_ADDREF(mURL);
mInstance = aInstance;
NS_ADDREF(mInstance);
mNotifyData = aNotifyData;
return NS_OK;
}
nsresult nsPluginStreamListener :: Initialize(nsIURL *aURL, nsIPluginInstanceOwner *aOwner,
nsIPluginHost *aHost, void *aNotifyData)
{
#ifdef NS_DEBUG
printf("created stream for %s\n", aURL->GetSpec());
#endif
mURL = aURL;
NS_ADDREF(mURL);
mOwner = aOwner;
NS_ADDREF(mOwner);
mHost = aHost;
NS_IF_ADDREF(mHost);
return NS_OK;
}
nsresult nsPluginStreamListener :: Initialize(nsIPluginInstance *aInstance, void *aNotifyData)
{
#ifdef NS_DEBUG
printf("created stream for (unknown URL)\n");
#endif
mInstance = aInstance;
NS_ADDREF(mInstance);
mNotifyData = aNotifyData;
return NS_OK;
}
NS_IMETHODIMP nsPluginStreamListener :: OnStartBinding(nsIURL* aURL, const char *aContentType)
{
nsresult rv = NS_OK;
if (nsnull != aContentType)
{
PRInt32 len = PL_strlen(aContentType);
mMIMEType = (char *)PR_Malloc(len + 1);
if (nsnull != mMIMEType)
PL_strcpy(mMIMEType, aContentType);
else
rv = NS_ERROR_OUT_OF_MEMORY;
}
//now that we have the mime type, see if we need
//to load a plugin...
nsIPluginInstance *instance = nsnull;
nsPluginWindow *window = nsnull;
if ((nsnull == mInstance) && (nsnull != mOwner))
{
mOwner->GetInstance(instance);
mOwner->GetWindow(window);
if ((nsnull == instance) && (nsnull != mHost) && (nsnull != window))
{
rv = mHost->InstantiatePlugin(aContentType, aURL, mOwner);
if (NS_OK == rv)
{
mOwner->GetInstance(instance);
if (nsnull != instance)
{
instance->Start();
mOwner->CreateWidget();
instance->SetWindow(window);
}
}
}
}
else
{
instance = mInstance;
NS_ADDREF(instance);
}
if ((PR_TRUE == mGotProgress) && (nsnull == mPeer) &&
(nsnull != instance) && (PR_FALSE == mBound))
{
//need to create new peer and tell plugin that we have new stream...
mPeer = (nsPluginStreamPeer *)new nsPluginStreamPeer();
NS_ADDREF(mPeer);
mPeer->Initialize(aURL, mLength, 0, aContentType, mNotifyData);
instance->NewStream(mPeer, &mStream);
if (nsnull != mStream)
mStream->GetStreamType(&mStreamType);
if ((mStreamType == nsPluginStreamType_AsFile) ||
(mStreamType == nsPluginStreamType_AsFileOnly))
{
char buf[400], tpath[300];
#ifdef XP_PC
::GetTempPath(sizeof(tpath), tpath);
PRInt32 len = PL_strlen(tpath);
if ((len > 0) && (tpath[len - 1] != '\\'))
{
tpath[len] = '\\';
tpath[len + 1] = 0;
}
#elif defined (XP_UNIX)
PL_strcpy(tpath, "/tmp/");
#else
tpath[0] = 0;
#endif
PR_snprintf(buf, sizeof(buf), "%s%08X.ngl", tpath, mStream);
mStreamFile = fopen(buf, "wb");
}
}
NS_IF_RELEASE(instance);
mBound = PR_TRUE;
return rv;
}
NS_IMETHODIMP nsPluginStreamListener :: OnProgress(nsIURL* aURL, PRInt32 aProgress, PRInt32 aProgressMax)
{
if ((aProgress == 0) && (nsnull == mPeer))
{
nsIPluginInstance *instance = nsnull;
if (nsnull == mInstance)
mOwner->GetInstance(instance);
else
{
instance = mInstance;
NS_ADDREF(instance);
}
if (nsnull != instance)
{
//need to create new peer and and tell plugin that we have new stream...
mPeer = (nsPluginStreamPeer *)new nsPluginStreamPeer();
NS_ADDREF(mPeer);
mPeer->Initialize(aURL, aProgressMax, 0, mMIMEType, mNotifyData);
instance->NewStream(mPeer, &mStream);
if (nsnull != mStream)
mStream->GetStreamType(&mStreamType);
if ((mStreamType == nsPluginStreamType_AsFile) ||
(mStreamType == nsPluginStreamType_AsFileOnly))
{
char buf[400], tpath[300];
#ifdef XP_PC
::GetTempPath(sizeof(tpath), tpath);
PRInt32 len = PL_strlen(tpath);
if ((len > 0) && (tpath[len - 1] != '\\'))
{
tpath[len] = '\\';
tpath[len + 1] = 0;
}
#elif defined (XP_UNIX)
PL_strcpy(tpath, "/tmp/");
#else
tpath[0] = 0;
#endif
PR_snprintf(buf, sizeof(buf), "%s%08X.ngl", tpath, mStream);
mStreamFile = fopen(buf, "wb");
}
NS_RELEASE(instance);
}
}
mLength = aProgressMax;
mGotProgress = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP nsPluginStreamListener :: OnStatus(nsIURL* aURL, const nsString &aMsg)
{
return NS_OK;
}
NS_IMETHODIMP nsPluginStreamListener :: OnStopBinding(nsIURL* aURL, PRInt32 aStatus, const nsString &aMsg)
{
nsresult rv;
nsPluginReason reason = nsPluginReason_NoReason;
//XXX this is incomplete... MMP
if (nsnull != mPeer)
{
if (aStatus == NS_BINDING_SUCCEEDED)
reason = nsPluginReason_Done;
else
reason = nsPluginReason_UserBreak;
mPeer->SetReason(reason);
rv = NS_OK;
}
else
rv = NS_ERROR_UNEXPECTED;
if (nsnull != mStream)
{
if ((mStreamType == nsPluginStreamType_AsFile) ||
(mStreamType == nsPluginStreamType_AsFileOnly))
{
if (nsnull != mStreamFile)
{
fclose(mStreamFile);
mStreamFile = nsnull;
char buf[400], tpath[300];
#ifdef XP_PC
::GetTempPath(sizeof(tpath), tpath);
PRInt32 len = PL_strlen(tpath);
if ((len > 0) && (tpath[len - 1] != '\\'))
{
tpath[len] = '\\';
tpath[len + 1] = 0;
}
#elif defined (XP_UNIX)
PL_strcpy(tpath, "/tmp/");
#else
tpath[0] = 0;
#endif
PR_snprintf(buf, sizeof(buf), "%s%08X.ngl", tpath, mStream);
mStream->AsFile(buf);
}
}
nsIPluginInstance *instance = nsnull;
if (nsnull == mInstance)
mOwner->GetInstance(instance);
else
{
instance = mInstance;
NS_ADDREF(instance);
}
mStream->Close();
if (nsnull != instance)
{
if (nsnull != mNotifyData)
{
const char *url;
if (nsnull != mURL)
url = mURL->GetSpec();
else
url = "";
//XXX target is bad. MMP
instance->URLNotify(url, "", reason, mNotifyData);
}
NS_RELEASE(instance);
}
}
return rv;
}
NS_IMETHODIMP nsPluginStreamListener :: GetBindInfo(nsIURL* aURL)
{
return NS_OK;
}
NS_IMETHODIMP nsPluginStreamListener :: OnDataAvailable(nsIURL* aURL, nsIInputStream *aIStream,
PRInt32 aLength)
{
if ((PRUint32)aLength > mBufSize)
{
if (nsnull != mBuffer)
PR_Free((void *)mBuffer);
mBuffer = (PRUint8 *)PR_Malloc(aLength);
mBufSize = aLength;
}
if ((nsnull != mBuffer) && (nsnull != mStream))
{
PRInt32 readlen;
aIStream->Read((char *)mBuffer, 0, aLength, &readlen);
if (nsnull != mStreamFile)
fwrite(mBuffer, 1, aLength, mStreamFile);
if (mStreamType != nsPluginStreamType_AsFileOnly)
mStream->Write((char *)mBuffer, 0, aLength, &readlen);
}
return NS_OK;
}
nsPluginHostImpl :: nsPluginHostImpl()
{
NS_INIT_REFCNT();
}
nsPluginHostImpl :: ~nsPluginHostImpl()
{
#ifdef NS_DEBUG
printf("killing plugin host\n");
#endif
if (nsnull != mPluginPath)
{
PR_Free(mPluginPath);
mPluginPath = nsnull;
}
while (nsnull != mPlugins)
{
nsPluginTag *temp = mPlugins->mNext;
delete mPlugins;
mPlugins = temp;
}
NS_IF_RELEASE(mMalloc);
}
NS_IMPL_ADDREF(nsPluginHostImpl)
NS_IMPL_RELEASE(nsPluginHostImpl)
nsresult nsPluginHostImpl :: QueryInterface(const nsIID& aIID,
void** aInstancePtrResult)
{
NS_PRECONDITION(nsnull != aInstancePtrResult, "null pointer");
if (nsnull == aInstancePtrResult)
return NS_ERROR_NULL_POINTER;
if (aIID.Equals(kIPluginManagerIID))
{
*aInstancePtrResult = (void *)((nsIPluginManager *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIPluginManager2IID))
{
*aInstancePtrResult = (void *)((nsIPluginManager2 *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIPluginHostIID))
{
*aInstancePtrResult = (void *)((nsIPluginHost *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIFactoryIID))
{
*aInstancePtrResult = (void *)((nsIFactory *)this);
AddRef();
return NS_OK;
}
if (aIID.Equals(kIMallocIID))
{
*aInstancePtrResult = mMalloc;
NS_IF_ADDREF(mMalloc);
return NS_OK;
}
if (aIID.Equals(kISupportsIID))
{
*aInstancePtrResult = (void *)((nsISupports *)((nsIPluginHost *)this));
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
NS_IMETHODIMP nsPluginHostImpl :: GetValue(nsPluginManagerVariable variable, void *value)
{
printf("manager getvalue %d called\n", variable);
return NS_OK;
}
nsresult nsPluginHostImpl :: ReloadPlugins(PRBool reloadPages)
{
mPluginsLoaded = PR_FALSE;
return LoadPlugins();
}
//XXX need to find out score on this one... MMP
nsresult nsPluginHostImpl :: UserAgent(const char **retstring)
{
*retstring = (const char *)"Mozilla/5.0 [en] (Windows;I)";
return NS_OK;
}
NS_IMETHODIMP nsPluginHostImpl :: GetURL(nsISupports* inst, const char* url,
const char* target,
void* notifyData, const char* altHost,
const char* referrer, PRBool forceJSEnabled)
{
nsAutoString string = nsAutoString(url);
nsIPluginInstance *instance;
nsresult rv;
rv = inst->QueryInterface(kIPluginInstanceIID, (void **)&instance);
if (NS_OK == rv)
{
if (nsnull != target)
{
nsPluginInstancePeerImpl *peer;
rv = instance->GetPeer((nsIPluginInstancePeer **)&peer);
if (NS_OK == rv)
{
nsIPluginInstanceOwner *owner;
rv = peer->GetOwner(owner);
if (NS_OK == rv)
{
if ((0 == PL_strcmp(target, "newwindow")) ||
(0 == PL_strcmp(target, "_new")))
target = "_blank";
else if (0 == PL_strcmp(target, "_current"))
target = "_self";
rv = owner->GetURL(url, target, nsnull);
NS_RELEASE(owner);
}
NS_RELEASE(peer);
}
}
if ((nsnull != notifyData) || (nsnull == target))
rv = NewPluginStream(string, instance, notifyData);
NS_RELEASE(instance);
}
return rv;
}
NS_IMETHODIMP nsPluginHostImpl :: PostURL(nsISupports* inst,
const char* url, const char* target,
PRUint32 postDataLen, const char* postData,
PRBool isFile, void* notifyData,
const char* altHost, const char* referrer,
PRBool forceJSEnabled,
PRUint32 postHeadersLength, const char* postHeaders)
{
printf("plugin manager posturl called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: BeginWaitCursor(void)
{
printf("plugin manager2 beginwaitcursor called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: EndWaitCursor(void)
{
printf("plugin manager2 posturl called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: SupportsURLProtocol(const char* protocol, PRBool *result)
{
printf("plugin manager2 supportsurlprotocol called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: NotifyStatusChange(nsIPlugin* plugin, nsresult errorStatus)
{
printf("plugin manager2 notifystatuschange called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: FindProxyForURL(const char* url, char* *result)
{
printf("plugin manager2 findproxyforurl called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: RegisterWindow(nsIEventHandler* handler, nsPluginPlatformWindowRef window)
{
printf("plugin manager2 registerwindow called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: UnregisterWindow(nsIEventHandler* handler, nsPluginPlatformWindowRef window)
{
printf("plugin manager2 unregisterwindow called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: AllocateMenuID(nsIEventHandler* handler, PRBool isSubmenu, PRInt16 *result)
{
printf("plugin manager2 allocatemenuid called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: DeallocateMenuID(nsIEventHandler* handler, PRInt16 menuID)
{
printf("plugin manager2 deallocatemenuid called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: HasAllocatedMenuID(nsIEventHandler* handler, PRInt16 menuID, PRBool *result)
{
printf("plugin manager2 hasallocatedmenuid called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
NS_IMETHODIMP nsPluginHostImpl :: ProcessNextEvent(PRBool *bEventHandled)
{
printf("plugin manager2 processnextevent called\n");
return NS_ERROR_NOT_IMPLEMENTED;
}
nsresult nsPluginHostImpl :: Init(void)
{
nsresult rv;
nsISupports *object;
// rv = nsMalloc::Create(nsnull, kIMallocIID, (void **)&mMalloc);
rv = nsMalloc::Create(nsnull, kIMallocIID, (void **)&object);
//it should be possible to kill this now... MMP
if (NS_OK == rv)
{
rv = object->QueryInterface(kIMallocIID, (void **)&mMalloc);
NS_RELEASE(object);
}
return rv;
}
nsresult nsPluginHostImpl :: Destroy(void)
{
nsPluginTag *plug = mPlugins;
while (nsnull != plug)
{
if (nsnull != plug->mEntryPoint)
plug->mEntryPoint->Shutdown();
plug = plug->mNext;
}
return NS_OK;
}
nsresult nsPluginHostImpl :: LoadPlugins(void)
{
#ifdef XP_PC
long result;
HKEY keyloc;
DWORD type, pathlen;
char path[2000];
PRDir *dir = nsnull;
if (::GetModuleFileName(NULL, path, sizeof(path)) > 0)
{
pathlen = PL_strlen(path) - 1;
while (pathlen > 0)
{
if (path[pathlen] == '\\')
break;
pathlen--;
}
if (pathlen > 0)
{
PL_strcpy(&path[pathlen + 1], "plugins");
dir = PR_OpenDir(path);
}
}
if (nsnull == dir)
{
path[0] = 0;
result = ::RegOpenKeyEx(HKEY_CURRENT_USER,
"Software\\Netscape\\Netscape Navigator\\Main",
0, KEY_READ, &keyloc);
if (result == ERROR_SUCCESS)
{
pathlen = sizeof(path);
result = ::RegQueryValueEx(keyloc, "Install Directory",
NULL, &type, (LPBYTE)&path, &pathlen);
if (result == ERROR_SUCCESS)
{
PL_strcat(path, "\\Program\\Plugins");
}
::RegCloseKey(keyloc);
}
dir = PR_OpenDir(path);
}
#ifdef NS_DEBUG
if (path[0] != 0)
printf("plugins at: %s\n", path);
#endif
if (nsnull != dir)
{
PRDirEntry *dent;
char *verbuf = NULL;
DWORD verbufsize = 0;
pathlen = PL_strlen(path);
mPluginPath = (char *)PR_Malloc(pathlen + 2);
if (nsnull != mPluginPath)
{
PL_strcpy(mPluginPath, path);
mPluginPath[pathlen] = '\\';
mPluginPath[pathlen + 1] = 0;
}
while (nsnull != mPlugins)
{
nsPluginTag *temp = mPlugins->mNext;
delete mPlugins;
mPlugins = temp;
}
while (dent = PR_ReadDir(dir, PR_SKIP_BOTH))
{
PRInt32 len = PL_strlen(dent->name);
if (len > 6) //np*.dll
{
if ((0 == stricmp(&dent->name[len - 4], ".dll")) && //ends in '.dll'
(0 == PL_strncasecmp(dent->name, "np", 2))) //starts with 'np'
{
PRLibrary *plugin;
PL_strcpy(path, mPluginPath);
PL_strcat(path, dent->name);
plugin = PR_LoadLibrary(path);
if (NULL != plugin)
{
DWORD zerome, versionsize;
versionsize = ::GetFileVersionInfoSize(path, &zerome);
if (versionsize > 0)
{
if (versionsize > verbufsize)
{
if (nsnull != verbuf)
PR_Free(verbuf);
verbuf = (char *)PR_Malloc(versionsize);
verbufsize = versionsize;
}
if ((nsnull != verbuf) && ::GetFileVersionInfo(path, NULL, verbufsize, verbuf))
{
char *buf = NULL;
UINT blen;
nsPluginTag *plugintag;
PRBool completetag = PR_FALSE;
PRInt32 variants;
plugintag = new nsPluginTag();
while (nsnull != plugintag)
{
plugintag->mName = (char *)PR_Malloc(PL_strlen(dent->name) + 1);
if (nsnull == plugintag->mName)
break;
else
PL_strcpy(plugintag->mName, dent->name);
::VerQueryValue(verbuf,
TEXT("\\StringFileInfo\\040904E4\\FileDescription"),
(void **)&buf, &blen);
if (NULL == buf)
break;
else
{
plugintag->mDescription = (char *)PR_Malloc(blen + 1);
if (nsnull == plugintag->mDescription)
break;
else
PL_strcpy(plugintag->mDescription, buf);
}
::VerQueryValue(verbuf,
TEXT("\\StringFileInfo\\040904E4\\MIMEType"),
(void **)&buf, &blen);
if (NULL == buf)
break;
else
{
plugintag->mMimeType = (char *)PR_Malloc(blen + 1);
if (nsnull == plugintag->mMimeType)
break;
else
PL_strcpy(plugintag->mMimeType, buf);
buf = plugintag->mMimeType;
variants = 1;
while (*buf)
{
if (*buf == '|')
variants++;
buf++;
}
plugintag->mVariants = variants;
plugintag->mMimeTypeArray = (char **)PR_Malloc(variants * sizeof(char *));
if (nsnull == plugintag->mMimeTypeArray)
break;
else
{
variants = 0;
plugintag->mMimeTypeArray[variants++] = plugintag->mMimeType;
buf = plugintag->mMimeType;
while (*buf)
{
if (*buf == '|')
{
plugintag->mMimeTypeArray[variants++] = buf + 1;
*buf = 0;
}
buf++;
}
}
}
::VerQueryValue(verbuf,
TEXT("\\StringFileInfo\\040904E4\\FileOpenName"),
(void **)&buf, &blen);
if (NULL == buf)
break;
else
{
plugintag->mMimeDescription = (char *)PR_Malloc(blen + 1);
if (nsnull == plugintag->mMimeDescription)
break;
else
PL_strcpy(plugintag->mMimeDescription, buf);
buf = plugintag->mMimeDescription;
variants = 1;
while (*buf)
{
if (*buf == '|')
variants++;
buf++;
}
if (variants != plugintag->mVariants)
break;
plugintag->mMimeDescriptionArray = (char **)PR_Malloc(variants * sizeof(char *));
if (nsnull == plugintag->mMimeDescriptionArray)
break;
else
{
variants = 0;
plugintag->mMimeDescriptionArray[variants++] = plugintag->mMimeDescription;
buf = plugintag->mMimeDescription;
while (*buf)
{
if (*buf == '|')
{
plugintag->mMimeDescriptionArray[variants++] = buf + 1;
*buf = 0;
}
buf++;
}
}
}
::VerQueryValue(verbuf,
TEXT("\\StringFileInfo\\040904E4\\FileExtents"),
(void **)&buf, &blen);
if (NULL == buf)
break;
else
{
plugintag->mExtensions = (char *)PR_Malloc(blen + 1);
if (nsnull == plugintag->mExtensions)
break;
else
PL_strcpy(plugintag->mExtensions, buf);
buf = plugintag->mExtensions;
variants = 1;
while (*buf)
{
if (*buf == '|')
variants++;
buf++;
}
if (variants != plugintag->mVariants)
break;
plugintag->mExtensionsArray = (char **)PR_Malloc(variants * sizeof(char *));
if (nsnull == plugintag->mExtensionsArray)
break;
else
{
variants = 0;
plugintag->mExtensionsArray[variants++] = plugintag->mExtensions;
buf = plugintag->mExtensions;
while (*buf)
{
if (*buf == '|')
{
plugintag->mExtensionsArray[variants++] = buf + 1;
*buf = 0;
}
buf++;
}
}
}
completetag = PR_TRUE;
break;
}
if (PR_FALSE == completetag)
delete plugintag;
else
{
if (nsnull == PR_FindSymbol(plugin, "NSGetFactory"))
plugintag->mFlags |= NS_PLUGIN_FLAG_OLDSCHOOL;
#ifdef NS_DEBUG
printf("plugin %s added to list %s\n", plugintag->mName, (plugintag->mFlags & NS_PLUGIN_FLAG_OLDSCHOOL) ? "(old school)" : "");
#endif
plugintag->mNext = mPlugins;
mPlugins = plugintag;
}
}
}
PR_UnloadLibrary(plugin);
}
}
}
}
if (nsnull != verbuf)
PR_Free(verbuf);
PR_CloseDir(dir);
}
#else
#ifdef NS_DEBUG
printf("Don't know how to locate plugins directory on Unix yet...\n");
#endif
#endif
mPluginsLoaded = PR_TRUE;
return NS_OK;
}
nsresult nsPluginHostImpl :: InstantiatePlugin(const char *aMimeType, nsIURL *aURL,
nsIPluginInstanceOwner *aOwner)
{
nsPluginTag *plugins = nsnull;
PRInt32 variants, cnt;
if (PR_FALSE == mPluginsLoaded)
LoadPlugins();
if (nsnull != aMimeType)
{
plugins = mPlugins;
while (nsnull != plugins)
{
variants = plugins->mVariants;
for (cnt = 0; cnt < variants; cnt++)
{
if (0 == strcmp(plugins->mMimeTypeArray[cnt], aMimeType))
break;
}
if (cnt < variants)
break;
plugins = plugins->mNext;
}
}
if ((nsnull == plugins) && (nsnull != aURL))
{
const char *name = aURL->GetSpec();
PRInt32 len = PL_strlen(name);
//find the plugin by filename extension.
if ((nsnull != name) && (len > 1))
{
len--;
while ((name[len] != 0) && (name[len] != '.'))
len--;
if (name[len] == '.')
{
const char *ext = name + len + 1;
len = PL_strlen(ext);
plugins = mPlugins;
while (nsnull != plugins)
{
variants = plugins->mVariants;
for (cnt = 0; cnt < variants; cnt++)
{
char *extensions = plugins->mExtensionsArray[cnt];
char *nextexten;
PRInt32 extlen;
while (nsnull != extensions)
{
nextexten = strchr(extensions, ',');
if (nsnull != nextexten)
extlen = nextexten - extensions;
else
extlen = PL_strlen(extensions);
if (extlen == len)
{
if (PL_strncasecmp(extensions, ext, extlen) == 0)
break;
}
if (nsnull != nextexten)
extensions = nextexten + 1;
else
extensions = nsnull;
}
if (nsnull != extensions)
break;
}
if (cnt < variants)
{
aMimeType = plugins->mMimeTypeArray[cnt];
#ifdef NS_DEBUG
printf("found plugin via extension %s\n", ext);
#endif
break;
}
plugins = plugins->mNext;
}
}
}
}
if (nsnull != plugins)
{
if (nsnull == plugins->mLibrary)
{
char path[2000];
PL_strcpy(path, mPluginPath);
PL_strcat(path, plugins->mName);
plugins->mLibrary = PR_LoadLibrary(path);
#ifdef NS_DEBUG
printf("loaded plugin %s for mime type %s\n", plugins->mName, aMimeType);
#endif
}
if (nsnull != plugins->mLibrary)
{
if (nsnull == plugins->mEntryPoint)
{
//create the plugin object
if (plugins->mFlags & NS_PLUGIN_FLAG_OLDSCHOOL)
{
nsresult rv = ns4xPlugin::CreatePlugin(plugins->mLibrary, (nsIPlugin **)&plugins->mEntryPoint);
#ifdef NS_DEBUG
printf("result of creating plugin adapter: %d\n", rv);
#endif
}
else
{
nsFactoryProc fact = (nsFactoryProc)PR_FindSymbol(plugins->mLibrary, "NSGetFactory");
if (nsnull != fact)
{
nsIFactory *factory;
if (NS_OK == (fact)(kIFactoryIID, &factory))
{
factory->QueryInterface(kIPluginIID, (void **)&plugins->mEntryPoint);
NS_RELEASE(factory);
}
}
}
if (nsnull != plugins->mEntryPoint)
plugins->mEntryPoint->Initialize((nsISupports *)(nsIPluginManager *)this);
}
if (nsnull != plugins->mEntryPoint)
{
nsIPluginInstance *instance;
//create an instance
if (NS_OK == plugins->mEntryPoint->CreateInstance(nsnull, kIPluginInstanceIID, (void **)&instance))
{
#ifdef NS_DEBUG
printf("successfully created plugin instance %08x for %s, mimetype %s\n", instance, plugins->mName, aMimeType ? aMimeType : "(none)");
#endif
aOwner->SetInstance(instance);
nsPluginInstancePeerImpl *peer = new nsPluginInstancePeerImpl();
peer->Initialize(aOwner, aMimeType); //this will not add a ref to the instance (or owner). MMP
instance->Initialize(peer);
NS_RELEASE(instance);
}
}
}
else
return NS_ERROR_UNEXPECTED;
return NS_OK;
}
else
{
if ((nsnull != aURL) || (nsnull != aMimeType))
#ifdef NS_DEBUG
printf("unable to find plugin to handle %s\n", aMimeType ? aMimeType : "(mime type unspecified)")
#endif
;
return NS_ERROR_FAILURE;
}
}
nsresult nsPluginHostImpl :: InstantiatePlugin(const char *aMimeType, nsString& aURLSpec,
nsIPluginInstanceOwner *aOwner)
{
nsresult rv;
rv = InstantiatePlugin(aMimeType, nsnull, aOwner);
if ((rv != NS_OK) || (nsnull == aMimeType))
{
//either the plugin could not be identified based
//on the mime type or there was no mime type
if (aURLSpec.Length() > 0)
{
//we need to stream in enough to get the mime type...
rv = NewPluginStream(aURLSpec, aOwner, nsnull);
}
else
rv = NS_ERROR_FAILURE;
}
else
{
nsIPluginInstance *instance = nsnull;
nsPluginWindow *window = nsnull;
//we got a plugin built, now stream
aOwner->GetInstance(instance);
aOwner->GetWindow(window);
if (nsnull != instance)
{
instance->Start();
aOwner->CreateWidget();
instance->SetWindow(window);
rv = NewPluginStream(aURLSpec, instance, nsnull);
NS_RELEASE(instance);
}
}
return rv;
}
nsresult nsPluginHostImpl :: InstantiatePlugin(const char *aMimeType, nsString& aURLSpec,
nsIStreamListener *&aStreamListener,
nsIPluginInstanceOwner *aOwner)
{
nsresult rv;
nsIURL *url;
//create a URL so that the instantiator can do file ext.
//based plugin lookups...
rv = NS_NewURL(&url, aURLSpec);
if (rv != NS_OK)
url = nsnull;
rv = InstantiatePlugin(aMimeType, url, aOwner);
NS_IF_RELEASE(url);
if (NS_OK == rv)
{
nsIPluginInstance *instance = nsnull;
nsPluginWindow *window = nsnull;
//we got a plugin built, now stream
aOwner->GetInstance(instance);
aOwner->GetWindow(window);
if (nsnull != instance)
{
instance->Start();
aOwner->CreateWidget();
instance->SetWindow(window);
rv = NewPluginStream(aStreamListener, instance, nsnull);
NS_RELEASE(instance);
}
}
return rv;
}
NS_IMETHODIMP nsPluginHostImpl :: NewPluginStream(const nsString& aURL,
nsIPluginInstance *aInstance,
void *aNotifyData)
{
nsIURL *url;
nsPluginStreamListener *listener = (nsPluginStreamListener *)new nsPluginStreamListener();
nsresult rv;
if (aURL.Length() <= 0)
return NS_OK;
rv = NS_NewURL(&url, aURL);
if (NS_OK == rv)
{
rv = listener->Initialize(url, aInstance, aNotifyData);
if (NS_OK == rv)
rv = url->Open(listener);
NS_RELEASE(url);
}
return rv;
}
NS_IMETHODIMP nsPluginHostImpl :: NewPluginStream(const nsString& aURL,
nsIPluginInstanceOwner *aOwner,
void *aNotifyData)
{
nsIURL *url;
nsPluginStreamListener *listener = (nsPluginStreamListener *)new nsPluginStreamListener();
nsresult rv;
if (aURL.Length() <= 0)
return NS_OK;
rv = NS_NewURL(&url, aURL);
if (NS_OK == rv)
{
rv = listener->Initialize(url, aOwner, (nsIPluginHost *)this, aNotifyData);
if (NS_OK == rv)
rv = url->Open(listener);
NS_RELEASE(url);
}
return rv;
}
NS_IMETHODIMP nsPluginHostImpl :: NewPluginStream(nsIStreamListener *&aStreamListener,
nsIPluginInstance *aInstance,
void *aNotifyData)
{
nsPluginStreamListener *listener = (nsPluginStreamListener *)new nsPluginStreamListener();
nsresult rv;
rv = listener->Initialize(aInstance, aNotifyData);
aStreamListener = (nsIStreamListener *)listener;
NS_IF_ADDREF(listener);
return rv;
}
nsresult nsPluginHostImpl :: CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (aResult == NULL)
return NS_ERROR_NULL_POINTER;
nsISupports *inst = nsnull;
if (aIID.Equals(kIPluginStreamPeerIID))
inst = (nsISupports *)(nsIPluginStreamPeer *)new nsPluginStreamPeer();
if (inst == NULL)
return NS_ERROR_OUT_OF_MEMORY;
nsresult res = inst->QueryInterface(aIID, aResult);
if (res != NS_OK) {
// We didn't get the right interface, so clean up
delete inst;
}
return res;
}
nsresult nsPluginHostImpl :: LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}