warren%netscape.com 6cf0255e58 Committed from OJI_19980618_TIP_MERGE1.
git-svn-id: svn://10.0.0.236/trunk@6602 18797224-902f-48f8-a5cc-f745e15eee43
1998-07-28 02:11:07 +00:00

738 lines
19 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.
*/
// TODO: Implement Java callbacks
#include "xp_core.h"
#include "nsplugin.h"
#include "ns4xPlugin.h"
//#include "ns4xPluginInstance.h"
////////////////////////////////////////////////////////////////////////
// XXX These are defined in platform specific FE directories right now :-/
typedef NPError (*NP_GETENTRYPOINTS)(NPPluginFuncs* pCallbacks);
typedef NPError (*NP_PLUGININIT)(const NPNetscapeFuncs* pCallbacks);
typedef NPError (*NP_PLUGINSHUTDOWN)();
////////////////////////////////////////////////////////////////////////
NPNetscapeFuncs ns4xPlugin::CALLBACKS;
nsIPluginManager * ns4xPlugin::mManager;
void
ns4xPlugin::CheckClassInitialized(void)
{
static PRBool initialized = FALSE;
if (initialized)
return;
mManager = nsnull;
// XXX It'd be nice to make this const and initialize it
// statically...
CALLBACKS.size = sizeof(CALLBACKS);
CALLBACKS.version = (NP_VERSION_MAJOR << 8) + NP_VERSION_MINOR;
CALLBACKS.geturl = NewNPN_GetURLProc(_geturl);
CALLBACKS.posturl = NewNPN_PostURLProc(_posturl);
// CALLBACKS.requestread = NewNPN_RequestReadProc(_requestread);
// CALLBACKS.newstream = NewNPN_NewStreamProc(_newstream);
// CALLBACKS.write = NewNPN_WriteProc(_write);
// CALLBACKS.destroystream = NewNPN_DestroyStreamProc(_destroystream);
// CALLBACKS.status = NewNPN_StatusProc(_status);
// CALLBACKS.uagent = NewNPN_UserAgentProc(_useragent);
// CALLBACKS.memalloc = NewNPN_MemAllocProc(_memalloc);
// CALLBACKS.memfree = NewNPN_MemFreeProc(_memfree);
// CALLBACKS.memflush = NewNPN_MemFlushProc(_memflush);
// CALLBACKS.reloadplugins = NewNPN_ReloadPluginsProc(_reloadplugins);
// CALLBACKS.getJavaEnv = NewNPN_GetJavaEnvProc(_getJavaEnv);
// CALLBACKS.getJavaPeer = NewNPN_GetJavaPeerProc(_getJavaPeer);
CALLBACKS.geturlnotify = NewNPN_GetURLNotifyProc(_geturlnotify);
CALLBACKS.posturlnotify = NewNPN_PostURLNotifyProc(_posturlnotify);
// CALLBACKS.getvalue = NewNPN_GetValueProc(_getvalue);
// CALLBACKS.setvalue = NewNPN_SetValueProc(_setvalue);
// CALLBACKS.invalidaterect = NewNPN_InvalidateRectProc(_invalidaterect);
// CALLBACKS.invalidateregion = NewNPN_InvalidateRegionProc(_invalidateregion);
// CALLBACKS.forceredraw = NewNPN_ForceRedrawProc(_forceredraw);
initialized = TRUE;
};
////////////////////////////////////////////////////////////////////////
ns4xPlugin::ns4xPlugin(NPPluginFuncs* callbacks)
{
NS_INIT_REFCNT();
memcpy((void*) &fCallbacks, (void*) callbacks, sizeof(fCallbacks));
mManager = nsnull;
}
ns4xPlugin::~ns4xPlugin(void)
{
NS_IF_RELEASE(mManager);
}
////////////////////////////////////////////////////////////////////////
// nsISupports stuff
NS_IMPL_ADDREF(ns4xPlugin);
NS_IMPL_RELEASE(ns4xPlugin);
static NS_DEFINE_IID(kILiveConnectPluginIID, NS_ILIVECONNECTPLUGIN_IID);
static NS_DEFINE_IID(kIPluginIID, NS_IPLUGIN_IID);
static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
nsresult
ns4xPlugin::QueryInterface(const nsIID& iid, void** instance)
{
if (instance == NULL)
return NS_ERROR_NULL_POINTER;
if (iid.Equals(kIPluginIID) ||
iid.Equals(kISupportsIID)) {
*instance = (void*) this;
AddRef();
return NS_OK;
}
if (iid.Equals(kILiveConnectPluginIID)) {
// Check the 4.x plugin callbacks to see if it supports
// LiveConnect...
if (fCallbacks.javaClass == NULL)
return NS_NOINTERFACE;
*instance = (void*) this;
AddRef();
return NS_OK;
}
return NS_NOINTERFACE;
}
////////////////////////////////////////////////////////////////////////
// Static factory method.
//
nsresult
ns4xPlugin::CreatePlugin(PRLibrary *library,
nsIPlugin **result)
{
CheckClassInitialized();
NP_GETENTRYPOINTS pfnGetEntryPoints =
(NP_GETENTRYPOINTS)PR_FindSymbol(library, "NP_GetEntryPoints");
if (pfnGetEntryPoints == NULL)
return NS_ERROR_FAILURE;
NPPluginFuncs callbacks;
memset((void*) &callbacks, 0, sizeof(callbacks));
callbacks.size = sizeof(callbacks);
if (pfnGetEntryPoints(&callbacks) != NS_OK)
return NS_ERROR_FAILURE; // XXX
#ifdef XP_WIN // XXX This is really XP, but we need to figure out how to do HIBYTE()
if (HIBYTE(callbacks.version) < NP_VERSION_MAJOR)
return NS_ERROR_FAILURE;
#endif
// the NP_Initialize entry point was misnamed as NP_PluginInit,
// early in plugin project development. Its correct name is
// documented now, and new developers expect it to work. However,
// I don't want to break the plugins already in the field, so
// we'll accept either name
NP_PLUGININIT pfnInitialize =
(NP_PLUGININIT)PR_FindSymbol(library, "NP_Initialize");
if (!pfnInitialize) {
pfnInitialize =
(NP_PLUGININIT)PR_FindSymbol(library, "NP_PluginInit");
}
if (pfnInitialize == NULL)
return NS_ERROR_UNEXPECTED; // XXX Right error?
if (pfnInitialize(&ns4xPlugin::CALLBACKS) != NS_OK)
return NS_ERROR_UNEXPECTED; // XXX shoudl convert the 4.x error...
(*result) = new ns4xPlugin(&callbacks);
if ((*result) == NULL)
return NS_ERROR_OUT_OF_MEMORY;
return NS_OK;
}
nsresult ns4xPlugin :: CreateInstance(nsISupports *aOuter,
const nsIID &aIID,
void **aResult)
{
if (aResult == NULL) {
return NS_ERROR_NULL_POINTER;
}
*aResult = NULL;
nsISupports *inst;
inst = nsnull;
// inst = (nsISupports *)(nsIPluginInstance *)new ns4xPluginInstance();
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 ns4xPlugin :: LockFactory(PRBool aLock)
{
// Not implemented in simplest case.
return NS_OK;
}
static NS_DEFINE_IID(kIPluginManagerIID, NS_IPLUGINMANAGER_IID);
nsresult
ns4xPlugin::Initialize(nsISupports* browserInterfaces)
{
if (nsnull == mManager)
return browserInterfaces->QueryInterface(kIPluginManagerIID, (void **)&mManager);
else
return NS_OK;
}
nsresult
ns4xPlugin::Shutdown(void)
{
NS_IF_RELEASE(mManager);
return NS_OK;
}
nsresult
ns4xPlugin::GetMIMEDescription(const char* *resultingDesc)
{
*resultingDesc = "";
return NS_OK; // XXX make a callback, etc.
}
nsresult
ns4xPlugin::GetValue(nsPluginVariable variable, void *value)
{
return NS_OK;
}
nsresult
ns4xPlugin::SetValue(nsPluginVariable variable, void *value)
{
return NS_OK;
}
nsresult
ns4xPlugin::GetJavaClass(jclass *resultingClass)
{
*resultingClass = fCallbacks.javaClass;
return NS_OK;
}
////////////////////////////////////////////////////////////////////////
//
// Static callbacks that get routed back through the new C++ API
//
nsresult NP_EXPORT
ns4xPlugin::_geturl(NPP npp, const char* relativeURL, const char* target)
{
nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata;
NS_ASSERTION(peer != NULL, "null peer");
NS_ASSERTION(mManager != NULL, "null manager");
if (peer == NULL)
return NS_ERROR_UNEXPECTED; // XXX
#if 0
nsURLInfo urlinfo;
urlinfo.version = nsURLInfo_Version;
urlinfo.url = relativeURL;
urlinfo.target = target;
urlinfo.notifyData = nsnull;
urlinfo.altHost = nsnull;
urlinfo.referrer = nsnull;
urlinfo.forceJSEnabled = PR_FALSE;
urlinfo.postData = nsnull;
urlinfo.postDataLength = 0;
urlinfo.postHeaders = nsnull;
urlinfo.postHeadersLength = 0;
urlinfo.postFile = PR_FALSE;
return mManager->FetchURL(peer, &urlinfo);
#endif
return NS_OK;
}
nsresult NP_EXPORT
ns4xPlugin::_geturlnotify(NPP npp, const char* relativeURL, const char* target,
void* notifyData)
{
nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata;
NS_ASSERTION(peer != NULL, "null peer");
NS_ASSERTION(mManager != NULL, "null manager");
if (peer == NULL)
return NS_ERROR_UNEXPECTED; // XXX
#if 0
nsURLInfo urlinfo;
urlinfo.version = nsURLInfo_Version;
urlinfo.url = relativeURL;
urlinfo.target = target;
urlinfo.notifyData = notifyData;
urlinfo.altHost = nsnull;
urlinfo.referrer = nsnull;
urlinfo.forceJSEnabled = PR_FALSE;
urlinfo.postData = nsnull;
urlinfo.postDataLength = 0;
urlinfo.postHeaders = nsnull;
urlinfo.postHeadersLength = 0;
urlinfo.postFile = PR_FALSE;
return mManager->FetchURL(peer, &urlinfo);
#endif
return NS_OK;
}
nsresult NP_EXPORT
ns4xPlugin::_posturlnotify(NPP npp, const char* relativeURL, const char *target,
uint32 len, const char *buf, NPBool file,
void* notifyData)
{
nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata;
NS_ASSERTION(peer != NULL, "null peer");
NS_ASSERTION(mManager != NULL, "null manager");
if (peer == NULL)
return NS_ERROR_UNEXPECTED; // XXX
#if 0
nsURLInfo urlinfo;
urlinfo.version = nsURLInfo_Version;
urlinfo.url = relativeURL;
urlinfo.target = target;
urlinfo.notifyData = notifyData;
urlinfo.altHost = nsnull;
urlinfo.referrer = nsnull;
urlinfo.forceJSEnabled = PR_FALSE;
urlinfo.postData = buf;
urlinfo.postDataLength = len;
urlinfo.postHeaders = nsnull;
urlinfo.postHeadersLength = 0;
urlinfo.postFile = file;
return mManager->FetchURL(peer, &urlinfo);
#endif
return NS_OK;
}
nsresult NP_EXPORT
ns4xPlugin::_posturl(NPP npp, const char* relativeURL, const char *target, uint32 len,
const char *buf, NPBool file)
{
nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata;
NS_ASSERTION(peer != NULL, "null peer");
NS_ASSERTION(mManager != NULL, "null manager");
if (peer == NULL)
return NS_ERROR_UNEXPECTED; // XXX
#if 0
nsURLInfo urlinfo;
urlinfo.version = nsURLInfo_Version;
urlinfo.url = relativeURL;
urlinfo.target = target;
urlinfo.notifyData = nsnull;
urlinfo.altHost = nsnull;
urlinfo.referrer = nsnull;
urlinfo.forceJSEnabled = PR_FALSE;
urlinfo.postData = buf;
urlinfo.postDataLength = len;
urlinfo.postHeaders = nsnull;
urlinfo.postHeadersLength = 0;
urlinfo.postFile = file;
return mManager->FetchURL(peer, &urlinfo);
#endif
return NS_OK;
}
#if 0
////////////////////////////////////////////////////////////////////////
/**
* A little helper class used to wrap up plugin manager streams (that is,
* streams from the plugin to the browser).
*/
class ns4xStreamWrapper {
protected:
NPIPluginManagerStream* fStream;
NPStream fNPStream;
public:
ns4xStreamWrapper(NPIPluginManagerStream* stream);
~ns4xStreamWrapper();
NPIPluginManagerStream*
GetStream(void);
NPStream*
GetNPStream(void) {
return &fNPStream;
};
};
ns4xStreamWrapper::ns4xStreamWrapper(NPIPluginManagerStream* stream)
: fStream(stream)
{
PR_ASSERT(stream != NULL);
fStream->AddRef();
memset(&fNPStream, 0, sizeof(fNPStream));
fNPStream.ndata = (void*) this;
}
ns4xStreamWrapper::~ns4xStreamWrapper(void)
{
if (fStream != NULL)
fStream->Release();
}
NPIPluginManagerStream*
ns4xStreamWrapper::GetStream(void)
{
if (fStream != NULL)
fStream->AddRef();
return fStream;
}
////////////////////////////////////////////////////////////////////////
nsresult NP_EXPORT
ns4xPlugin::_newstream(NPP npp, NPMIMEType type, const char* window, NPStream* *result)
{
nsIPluginInstancePeer* peer = (nsIPluginInstancePeer*) npp->ndata;
NS_ASSERTION(peer != NULL, "null peer");
if (peer == NULL)
return NS_ERROR_UNEXPECTED; // XXX
nsresult error;
nsIPluginStream* stream;
if ((error = peer->NewStream((const char*) type, window, &stream))
!= NPPluginError_NoError)
return (NPError) error;
ns4xStreamWrapper* wrapper = new ns4xStreamWrapper(stream);
if (wrapper == NULL) {
stream->Release();
return NPERR_OUT_OF_MEMORY_ERROR;
}
(*result) = wrapper->GetNPStream();
return NPERR_NO_ERROR;
}
int32 NP_EXPORT
ns4xPlugin::_write(NPP npp, NPStream *pstream, int32 len, void *buffer)
{
ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) npp->ndata;
PR_ASSERT(wrapper != NULL);
if (wrapper == NULL)
return 0;
NPIPluginManagerStream* stream = wrapper->GetStream();
PRUint32 count = 0;
while (count < ((PRUint32) len)) {
PRUint32 ready = stream->WriteReady();
ready = (ready > ((PRUint32) len)) ? ((PRUint32) len) : ready;
PRUint32 written = stream->Write(ready, ((const char*) buffer) + count);
count += written;
}
stream->Release();
return count;
}
NPError NP_EXPORT
ns4xPlugin::_destroystream(NPP npp, NPStream *pstream, NPError reason)
{
ns4xStreamWrapper* wrapper = (ns4xStreamWrapper*) npp->ndata;
PR_ASSERT(wrapper != NULL);
if (wrapper == NULL)
return 0;
// This will release the wrapped NPIPluginManagerStream.
delete wrapper;
return NPERR_NO_ERROR;
}
void NP_EXPORT
ns4xPlugin::_status(NPP npp, const char *message)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return;
peer->ShowStatus(message);
}
void NP_EXPORT
ns4xPlugin::_memfree (void *ptr)
{
thePluginManager->MemFree(ptr);
}
uint32 NP_EXPORT
ns4xPlugin::_memflush(uint32 size)
{
return thePluginManager->MemFlush(size);
}
void NP_EXPORT
ns4xPlugin::_reloadplugins(NPBool reloadPages)
{
thePluginManager->ReloadPlugins(reloadPages);
}
void NP_EXPORT
ns4xPlugin::_invalidaterect(NPP npp, NPRect *invalidRect)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return;
// XXX nsRect & NPRect are structurally equivalent
peer->InvalidateRect((nsRect*) invalidRect);
}
void NP_EXPORT
ns4xPlugin::_invalidateregion(NPP npp, NPRegion invalidRegion)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return;
// XXX nsRegion & NPRegion are typedef'd to the same thing
peer->InvalidateRegion((nsRegion*) invalidRegion);
}
void NP_EXPORT
ns4xPlugin::_forceredraw(NPP npp)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return;
peer->ForceRedraw();
}
NPError NP_EXPORT
ns4xPlugin::_getvalue(NPP npp, NPNVariable variable, void *result)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return NPERR_INVALID_PLUGIN_ERROR; // XXX
// XXX Note that for backwards compatibility, the old NPNVariables
// map correctly to NPPluginManagerVariables.
return (NPError) peer->GetValue((NPPluginManagerVariable) variable, result);
}
NPError NP_EXPORT
ns4xPlugin::_setvalue(NPP npp, NPPVariable variable, void *result)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return NPERR_INVALID_PLUGIN_ERROR; // XXX
// XXX Note that for backwards compatibility, the old NPPVariables
// map correctly to NPPluginVariables.
return (NPError) peer->SetValue((NPPluginVariable) variable, result);
}
NPError NP_EXPORT
ns4xPlugin::_requestread(NPStream *pstream, NPByteRange *rangeList)
{
NPIPluginStreamPeer* streamPeer = (NPIPluginStreamPeer*) pstream->ndata;
PR_ASSERT(streamPeer != NULL);
if (streamPeer == NULL)
return NPERR_INVALID_PLUGIN_ERROR; // XXX
NPISeekablePluginStreamPeer* seekablePeer = NULL;
static NS_DEFINE_IID(kISeekablePluginStreamPeerIID, NP_ISEEKABLEPLUGINSTREAMPEER_IID);
if (streamPeer->QueryInterface(kISeekablePluginStreamPeerIID,
(void**) seekablePeer) == NS_OK) {
NPError error;
// XXX nsByteRange & NPByteRange are structurally equivalent.
error = (NPError) seekablePeer->RequestRead((nsByteRange*) rangeList);
seekablePeer->Release();
return error;
}
return NPERR_STREAM_NOT_SEEKABLE;
}
////////////////////////////////////////////////////////////////////////
//
// On 68K Mac (XXX still supported?), we need to make sure that the
// pointers are in D0 for the following functions that return pointers.
//
#if defined(XP_MAC) && !defined(powerc)
#pragma pointers_in_D0
#endif
JRIEnv* NP_EXPORT
ns4xPlugin::_getJavaEnv(void)
{
return NULL;
}
const char * NP_EXPORT
ns4xPlugin::_useragent(NPP npp)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return NULL;
return peer->UserAgent();
}
void * NP_EXPORT
ns4xPlugin::_memalloc (uint32 size)
{
return thePluginManager->MemAlloc(size);
}
#ifdef JAVA
java_lang_Class* NP_EXPORT
ns4xPlugin::_getJavaClass(void* handle)
{
// Is this just a generic call into the Java VM?
return NULL;
}
#endif
jref NP_EXPORT
ns4xPlugin::_getJavaPeer(NPP npp)
{
NPIPluginInstancePeer* peer = (NPIPluginInstancePeer*) npp->ndata;
PR_ASSERT(peer != NULL);
if (peer == NULL)
return NULL;
static NS_DEFINE_IID(kILiveConnectPluginInstancePeerIID,
NP_ILIVECONNECTPLUGININSTANCEPEER_IID);
NPILiveConnectPluginInstancePeer* lcPeer = NULL;
if (peer->QueryInterface(kILiveConnectPluginInstancePeerIID,
(void**) &lcPeer) == NS_OK) {
jobject result = lcPeer->GetJavaPeer();
lcPeer->Release();
return result;
}
return NULL;
}
#if defined(XP_MAC) && !defined(powerc)
#pragma pointers_in_A0
#endif
//
////////////////////////////////////////////////////////////////////////
#endif