diff options
Diffstat (limited to 'extensions/source/plugin/unx/npnapi.cxx')
-rw-r--r-- | extensions/source/plugin/unx/npnapi.cxx | 917 |
1 files changed, 917 insertions, 0 deletions
diff --git a/extensions/source/plugin/unx/npnapi.cxx b/extensions/source/plugin/unx/npnapi.cxx new file mode 100644 index 000000000000..4a88577c5b71 --- /dev/null +++ b/extensions/source/plugin/unx/npnapi.cxx @@ -0,0 +1,917 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" +#include <plugin/unx/plugcon.hxx> + +#include <unistd.h> +#include <dlfcn.h> + +#include <osl/module.h> + +extern PluginConnector* pConnector; +extern XtAppContext app_context; +extern int wakeup_fd[]; +extern Widget topLevel, topBox; +extern Display* pAppDisplay; +extern Display* pXtAppDisplay; +extern int nAppArguments; +extern char** pAppArguments; + +void* CreateNewShell( void**, XLIB_Window ); + +// begin Netscape plugin api calls +extern "C" { + +static void* l_NPN_MemAlloc( uint32 nBytes ) +{ + void* pMem = new char[nBytes]; + return pMem; +} + +static void l_NPN_MemFree( void* pMem ) +{ + delete [] (char*)pMem; +} + +static uint32 l_NPN_MemFlush( uint32 /*nSize*/ ) +{ + return 0; +} + +static NPError l_NPN_DestroyStream( NPP instance, NPStream* stream, NPError reason ) +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + UINT32 nFileID = pConnector->GetStreamID( stream ); + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_DestroyStream, + &nInstance, sizeof( nInstance ), + &nFileID, sizeof( nFileID ), + POST_STRING( stream->url ), + &reason, sizeof( reason ), + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + for( std::vector< NPStream* >::iterator it = pConnector->getStreamList().begin(); + it != pConnector->getStreamList().end(); ++it ) + { + if( *it == stream ) + { + pConnector->getStreamList().erase( it ); + break; + } + } + delete [] stream->url; + delete stream; + // returns NPError + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +#ifdef OJI +static JRIEnv* l_NPN_GetJavaEnv() +{ + // no java in this program + medDebug( 1, "SNI: NPN_GetJavaEnv\n" ); + return NULL; +} + +static jref l_NPN_GetJavaPeer( NPP /*instance*/ ) +{ + medDebug( 1, "SNI: NPN_GetJavaPeer\n" ); + return NULL; +} +#endif + +static NPError l_NPN_GetURL( NPP instance, const char* url, const char* window ) +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_GetURL, + &nInstance, sizeof( nInstance ), + POST_STRING(url), + POST_STRING(window), + NULL ); + medDebug( !pMes, "geturl: message unaswered\n" ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + // returns NPError + NPError aRet = pConnector->GetNPError( pMes ); + medDebug( aRet, "geturl returns %d\n", (int)aRet ); + delete pMes; + return aRet; +} + +static NPError l_NPN_GetURLNotify( NPP instance, const char* url, const char* target, + void* notifyData ) +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_GetURLNotify, + &nInstance, sizeof( nInstance ), + POST_STRING(url), + POST_STRING(target), + ¬ifyData, sizeof( void* ), // transmit the actual pointer + // since it is a pointer to private data fed back + // by NPP_URLNotify; this can be thought of as an ID + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + // returns NPError + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +static NPError l_NPN_NewStream( NPP instance, NPMIMEType type, const char* target, + NPStream** stream ) + // stream is a return value +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes= + pConnector-> + Transact( eNPN_NewStream, + &nInstance, sizeof( nInstance ), + POST_STRING(type), + POST_STRING(target), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + // returns a new NPStream and an error + NPError aRet = pConnector->GetNPError( pMes ); + if( ! aRet ) + { + NPStream* pStream = new NPStream; + pStream->url = pMes->GetString(); + pStream->end = pMes->GetUINT32(); + pStream->lastmodified = pMes->GetUINT32(); + pStream->ndata = pStream->pdata = pStream->notifyData = NULL; + + pConnector->getStreamList().push_back( pStream ); + *stream = pStream; + } + + delete pMes; + return aRet; +} + +static NPError l_NPN_PostURLNotify( NPP instance, const char* url, const char* target, uint32 len, const char* buf, NPBool file, void* notifyData ) +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_PostURLNotify, + &nInstance, sizeof( nInstance ), + POST_STRING( url ), + POST_STRING( target ), + &len, sizeof( len ), + buf, len, + &file, sizeof( NPBool ), + ¬ifyData, sizeof( void* ), // send the real pointer + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +static NPError l_NPN_PostURL( NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file ) +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_PostURL, + &nInstance, sizeof( nInstance ), + POST_STRING( url ), + POST_STRING( window ), + &len, sizeof( len ), + buf, len, + &file, sizeof( NPBool ), + NULL ); + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = pConnector->GetNPError( pMes ); + delete pMes; + return aRet; +} + +static NPError l_NPN_RequestRead( NPStream* stream, NPByteRange* rangeList ) +{ + medDebug( 1, "pluginapp: NPN_RequestRead\n" ); + + NPByteRange* pRange = rangeList; + UINT32 nRanges = 0; + while( pRange ) + { + nRanges++; + pRange = pRange->next; + } + + UINT32* pArray = new UINT32[ 2 * nRanges ]; + pRange = rangeList; + UINT32 n = 0; + while( pRange ) + { + pArray[ 2*n ] = (UINT32)pRange->offset; + pArray[ 2*n + 1] = (UINT32)pRange->length; + n++; + pRange = pRange->next; + } + UINT32 nFileID = pConnector->GetStreamID( stream ); + MediatorMessage* pMes = pConnector-> + Transact( eNPN_RequestRead, + &nFileID, sizeof( nFileID ), + &nRanges, sizeof( nRanges ), + pArray, sizeof( UINT32 ) * 2 * nRanges, + NULL ); + + if( ! pMes ) + return NPERR_GENERIC_ERROR; + + NPError aRet = pConnector->GetNPError( pMes ); + delete [] pArray; + delete pMes; + return aRet; +} + +static void l_NPN_Status( NPP instance, const char* message ) +{ + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return; + + pConnector->Send( eNPN_Status, + &nInstance, sizeof( nInstance ), + POST_STRING( message ), + NULL ); +} + +static const char* l_NPN_UserAgent( NPP instance ) +{ + static char* pAgent = NULL; + + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + { + if( instance ) + return "Mozilla 3.0"; + else // e.g. flashplayer calls NPN_UserAgent with NULL + nInstance = 0; + } + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_UserAgent, + &nInstance, sizeof( nInstance ), + NULL ); + + if( ! pMes ) + return pAgent; + + if( pAgent ) + delete [] pAgent; + pAgent = pMes->GetString(); + + delete pMes; + + medDebug( 1, "NPN_UserAgent returns %s\n", pAgent ); + + return pAgent; +} + +#if 0 +static void l_NPN_Version( int* major, int* minor, int* net_major, int* net_minor ) +{ + MediatorMessage* pMes = pConnector-> + Transact( eNPN_Version, + NULL ); + + if( ! pMes ) + return; + + *major = pMes->GetUINT32(); + *minor = pMes->GetUINT32(); + *net_major = pMes->GetUINT32(); + *net_minor = pMes->GetUINT32(); + + medDebug( 1, "pluginapp: NPN_Version: results %d %d, %d %d\n", *major, *minor, *net_major, *net_minor ); + + delete pMes; +} +#endif + +static int32 l_NPN_Write( NPP instance, NPStream* stream, int32 len, void* buffer ) +{ + UINT32 nFileID = pConnector->GetStreamID( stream ); + if( nFileID == PluginConnector::UnknownStreamID ) + return NPERR_GENERIC_ERROR; + UINT32 nInstance = pConnector->GetNPPID( instance ); + if( nInstance == PluginConnector::UnknownNPPID ) + return NPERR_GENERIC_ERROR; + + MediatorMessage* pMes = pConnector-> + Transact( eNPN_Write, + &nInstance, sizeof( nInstance ), + &nFileID, sizeof( nFileID ), + &len, sizeof( len ), + buffer, len, + NULL ); + + if( ! pMes ) + return 0; + + INT32 nRet = pMes->GetUINT32(); + return nRet; +} + +static void l_NPN_ReloadPlugins( NPBool /*reloadPages*/ ) +{ + medDebug( 1, "NPN_ReloadPlugins: SNI\n" ); +} + +static NPError l_NPN_GetValue( NPP, NPNVariable variable, void* value ) +{ + /* + * We want to handle values injected into a NPNVariable which aren't in + * the old enum we build against, but that we know are in the new enum + * we want to support + */ + switch( (int)variable ) + { + case NPNVxDisplay: + *((Display**)value) = pXtAppDisplay; + medDebug( 1, "Display requested\n" ); + break; + case NPNVxtAppContext: + *((XtAppContext*)value) = app_context; + medDebug( 1, "AppContext requested\n" ); + break; + case NPNVjavascriptEnabledBool: + // no javascript + *(NPBool*)value = false; + medDebug( 1, "javascript enabled requested\n" ); + break; + case NPNVasdEnabledBool: + // no SmartUpdate + *(NPBool*)value = false; + medDebug( 1, "smart update enabled requested\n" ); + break; + case NPNVisOfflineBool: + // no offline browsing + *(NPBool*)value = false; + medDebug( 1, "offline browsing requested\n" ); + break; + case NPNVSupportsXEmbedBool: + // asking xembed + *(int*)value = true; + medDebug( 1, "xembed requested\n" ); + break; + case NPNVToolkit: +# ifdef ENABLE_GTK + *(int*)value = NPNVGtk2; +# else + *(int*)value = 0; +# endif + medDebug( 1, "toolkit requested\n" ); + break; + default: + medDebug( 1, "unknown NPNVariable %x requested\n", variable ); + return NPERR_INVALID_PARAM; + } + return NPERR_NO_ERROR; +} + +static NPError l_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void *value) +{ + medDebug( 1, "NPN_SetValue %d=%p\n", variable, value ); + return 0; +} + +static void l_NPN_InvalidateRect(NPP /*instance*/, NPRect* /*invalidRect*/) +{ + medDebug( 1, "NPN_InvalidateRect\n" ); +} + +static void l_NPN_InvalidateRegion(NPP /*instance*/, NPRegion /*invalidRegion*/) +{ + medDebug( 1, "NPN_InvalidateRegion\n" ); +} + +static void l_NPN_ForceRedraw(NPP /*instance*/) +{ + medDebug( 1, "NPN_ForceRedraw\n" ); +} + +} + +static NPNetscapeFuncs aNetscapeFuncs = +{ + sizeof(aNetscapeFuncs), + (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR, + l_NPN_GetURL, + l_NPN_PostURL, + l_NPN_RequestRead, + l_NPN_NewStream, + l_NPN_Write, + l_NPN_DestroyStream, + l_NPN_Status, + l_NPN_UserAgent, + l_NPN_MemAlloc, + l_NPN_MemFree, + l_NPN_MemFlush, + l_NPN_ReloadPlugins, +# ifdef OJI + l_NPN_GetJavaEnv, + l_NPN_GetJavaPeer, +# else + NULL, + NULL, +# endif + l_NPN_GetURLNotify, + l_NPN_PostURLNotify, + l_NPN_GetValue, + l_NPN_SetValue, + l_NPN_InvalidateRect, + l_NPN_InvalidateRegion, + l_NPN_ForceRedraw +}; + +static NPPluginFuncs aPluginFuncs = +{ + sizeof(aPluginFuncs), + (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL, + NULL +}; + + +oslModule pPluginLib = NULL; +char*(*pNPP_GetMIMEDescription)() = NULL; +NPError (*pNP_Initialize)(NPNetscapeFuncs*,NPPluginFuncs*) = NULL; +NPError (*pNP_Shutdown)() = NULL; + +std::vector< PluginConnector* > PluginConnector::allConnectors; + +PluginConnector::PluginConnector( int nSocket ) : + Mediator( nSocket ) +{ + SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) ); +} + +PluginConnector::~PluginConnector() +{ +} + +IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ ) +{ + MediatorMessage* pMessage; + CommandAtoms nCommand; + while( (pMessage = GetNextMessage( FALSE )) ) + { + nCommand = (CommandAtoms)pMessage->GetUINT32(); + medDebug( 1, "pluginapp: %s\n", GetCommandName( nCommand ) ); + switch( nCommand ) + { + case eNPP_DestroyStream: + { + UINT32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + UINT32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + NPError aReason = GetNPError( pMessage ); + m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID ); + + aReason = aPluginFuncs.destroystream( instance, pStream, aReason ); + Respond( pMessage->m_nID, + (char*)&aReason, sizeof( aReason ), + NULL ); + + delete [] pStream->url; + delete pStream; + } + break; + case eNPP_Destroy: + { + UINT32 nInstance = pMessage->GetUINT32(); + ConnectorInstance* pInst= m_aInstances[ nInstance ]; + + // some plugin rely on old netscapes behaviour + // to first destroy the widget and then destroy + // the instance, so mimic that behaviour here + if( pInst->pShell ) + XtDestroyWidget( (Widget)pInst->pShell ); + + pInst->pWidget = pInst->pShell = NULL; + + // the other side will call eNPP_DestroyPhase2 after this + NPError aReason = NPERR_NO_ERROR; + Respond( pMessage->m_nID, (char*)&aReason, sizeof( aReason ), NULL ); + } + break; + case eNPP_DestroyPhase2: + { + // now really destroy the instance + UINT32 nInstance = pMessage->GetUINT32(); + ConnectorInstance* pInst= m_aInstances[ nInstance ]; + NPP instance = pInst->instance; + NPSavedData* pSave = NULL; + + NPError aRet = aPluginFuncs.destroy( instance, &pSave ); + if( pSave ) + { + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + pSave->buf, pSave->len, + NULL ); + delete [] (char*)pSave->buf; + } + else + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + "0000", 4, + NULL ); + + #ifdef ENABLE_GTK + if( pInst->pGtkWindow ) + g_object_unref( G_OBJECT(pInst->pGtkWindow) ); + if( pInst->pGtkWidget ) + g_object_unref( G_OBJECT(pInst->pGtkWidget) ); + #endif + + m_aInstances.erase( m_aInstances.begin() + nInstance ); + delete pInst; + delete instance; + medDebug( 1, "destroyed instance (returning %d)\n", aRet ); + } + break; + case eNPP_NewStream: + { + UINT32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* pType = pMessage->GetString(); + NPStream* pStream = new NPStream; + pStream->url = pMessage->GetString(); + pStream->end = pMessage->GetUINT32(); + pStream->lastmodified = pMessage->GetUINT32(); + pStream->pdata = pStream->ndata = pStream->notifyData = NULL; + NPBool* pSeekable = (NPBool*)pMessage->GetBytes(); + m_aNPWrapStreams.push_back( pStream ); + uint16 nStype = NP_ASFILE; + NPError aRet = aPluginFuncs.newstream( instance, pType, pStream, + *pSeekable, &nStype ); + medDebug( 1, "pluginapp: NPP_NewStream( %p, %s, %p, %s, %p ) returns %d\n" + "stream = { pdata = %p, ndata = %p, url = %s, end = %d, lastmodified = %d, notifyData = %p }\n", + instance, pType, pStream, *pSeekable ? "seekable" : "not seekable", &nStype, (int)aRet, + pStream->pdata, pStream->ndata, pStream->url, pStream->end, pStream->lastmodified, pStream->notifyData ); + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + &nStype, sizeof( nStype ), + NULL ); + delete [] pType; + delete [] pSeekable; + } + break; + case eNPP_New: + { + char* pType = pMessage->GetString(); + uint16* pMode = (uint16*)pMessage->GetBytes(); + int16* pArgc = (int16*)pMessage->GetBytes(); + NPP instance = new NPP_t; + instance->pdata = instance->ndata = NULL; + ULONG nArgnBytes, nArgvBytes; + char* pArgn = (char*)pMessage->GetBytes( nArgnBytes ); + char* pArgv = (char*)pMessage->GetBytes( nArgvBytes ); + ULONG nSaveBytes; + char* pSavedData = (char*)pMessage->GetBytes( nSaveBytes ); + ConnectorInstance* pInst = + new ConnectorInstance( instance, pType, + *pArgc, + pArgn, nArgnBytes, + pArgv, nArgvBytes, + pSavedData, nSaveBytes ); + m_aInstances.push_back( pInst ); + NPError aRet; + aRet = aPluginFuncs.newp( pInst->pMimeType, instance, *pMode, *pArgc, + pInst->nArg ? pInst->argn : NULL, + pInst->nArg ? pInst->argv : NULL, + ( nSaveBytes == 4 && *(UINT32*)pSavedData == 0 ) ? + &(pInst->aData) : NULL ); + medDebug( 1, "pluginapp: NPP_New( %s, %p, %d, %d, %p, %p, %p ) returns %d\n", + pInst->pMimeType, + instance, *pMode, pInst->nArg, pInst->argn, pInst->argv, &pInst->aData, + (int) aRet ); +#if OSL_DEBUG_LEVEL > 1 + for( int i = 0; i < pInst->nArg; i++ ) + medDebug( 1, " \"%s\"=\"%s\"\n", pInst->argn[i], pInst->argv[i] ); +#endif + + #ifdef ENABLE_GTK + // check if XEMBED is to be used + // ask for Bool. there seems to be no clear definition whether the + // return value should be an int or unsigned char + // int can hold both and will be nonzero in case of "true" + if( aPluginFuncs.getvalue ) + { + int bNeedsXEmbed = 0; + NPError error = aPluginFuncs.getvalue( instance, NPPVpluginNeedsXEmbed, (void *)&bNeedsXEmbed ); + if( error == NPERR_NO_ERROR ) + pInst->bShouldUseXEmbed = (bNeedsXEmbed != 0); + medDebug( 1, "should use xembed = %s\n", pInst->bShouldUseXEmbed ? "true" : "false" ); + } + #endif + + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + NULL ); + delete [] pMode; + delete [] pArgc; + delete [] pType; + } + break; + case eNPP_SetWindow: + { + UINT32 nInstance = pMessage->GetUINT32(); + ConnectorInstance* pInst= m_aInstances[ nInstance ]; + NPWindow* pWindow = (NPWindow*)pMessage->GetBytes(); + + if( pWindow->width < 1 ) + pWindow->width = 1; + if( pWindow->height < 1 ) + pWindow->height = 1; + + #ifdef ENABLE_GTK + if( pInst->bShouldUseXEmbed ) + { + if( ! pInst->pGtkWidget ) + { + medDebug( 1, "creating gtk plug and socket\n" ); + + pInst->pGtkWindow = gtk_plug_new((GdkNativeWindow)reinterpret_cast<sal_uIntPtr>(pWindow->window)); + gtk_widget_show( pInst->pGtkWindow ); + pInst->pGtkWidget = gtk_socket_new(); + gtk_widget_show( pInst->pGtkWidget ); + gtk_container_add( GTK_CONTAINER(pInst->pGtkWindow), pInst->pGtkWidget ); + gtk_widget_show_all( pInst->pGtkWindow ); + pInst->window.window = (void *)gtk_socket_get_id( GTK_SOCKET(pInst->pGtkWidget ) ); + + XSync( pAppDisplay, False ); + + XMapWindow( pAppDisplay, GDK_WINDOW_XWINDOW(pInst->pGtkWindow->window) ); + + XSync( pAppDisplay, False ); + } + + // update widget size; alas out parent is not yet really XEMBED conformant + gtk_widget_set_size_request( pInst->pGtkWidget, pWindow->width, pWindow->height ); + gtk_window_resize( GTK_WINDOW(pInst->pGtkWindow), pWindow->width, pWindow->height ); + + GdkScreen* pGdkScreen = gtk_widget_get_screen( pInst->pGtkWidget ); + Screen* pScreen = ScreenOfDisplay( pAppDisplay, gdk_screen_get_number( pGdkScreen ) ); + + pInst->window.x = 0; + pInst->window.y = 0; + pInst->window.width = pWindow->width; + pInst->window.height = pWindow->height; + pInst->window.clipRect.left = 0; + pInst->window.clipRect.top = 0; + pInst->window.clipRect.right = pWindow->width; + pInst->window.clipRect.bottom = pWindow->height; + pInst->window.ws_info = &pInst->ws_info; + pInst->window.type = NPWindowTypeWindow; + pInst->ws_info.type = NP_SETWINDOW; + pInst->ws_info.display = pAppDisplay; + pInst->ws_info.visual = DefaultVisualOfScreen( pScreen ); + pInst->ws_info.colormap = DefaultColormapOfScreen( pScreen ); + pInst->ws_info.depth = DefaultDepthOfScreen( pScreen ); + } + else + #endif + { + if( ! pInst->pWidget ) + { + pInst->pWidget = CreateNewShell( &(pInst->pShell), (XLIB_Window)pWindow->window ); + } + + // fill in NPWindow and NPCallbackStruct + pInst->window.window = (void*)XtWindow( (Widget)pInst->pWidget ); + pInst->window.x = 0; + pInst->window.y = 0; + pInst->window.width = pWindow->width; + pInst->window.height = pWindow->height; + pInst->window.clipRect.left = 0; + pInst->window.clipRect.top = 0; + pInst->window.clipRect.right = pWindow->width; + pInst->window.clipRect.bottom = pWindow->height; + pInst->window.ws_info = &pInst->ws_info; + pInst->window.type = NPWindowTypeWindow; + pInst->ws_info.type = NP_SETWINDOW; + pInst->ws_info.display = XtDisplay( (Widget)pInst->pWidget ); + pInst->ws_info.visual = DefaultVisualOfScreen( XtScreen( (Widget)pInst->pWidget ) ); + pInst->ws_info.colormap = DefaultColormapOfScreen( XtScreen( (Widget)pInst->pWidget ) ); + pInst->ws_info.depth = DefaultDepthOfScreen( XtScreen( (Widget)pInst->pWidget ) ); + + XtResizeWidget( (Widget)pInst->pShell, + pInst->window.width, + pInst->window.height, + 0 ); + XtResizeWidget( (Widget)pInst->pWidget, + pInst->window.width, + pInst->window.height, + 0 ); + } + + NPError aRet = aPluginFuncs.setwindow( pInst->instance, &pInst->window ); + medDebug( 1, "pluginapp: NPP_SetWindow returns %d\n", (int) aRet ); + Respond( pMessage->m_nID, + (char*)&aRet, sizeof( aRet ), + NULL ); + delete [] (char*)pWindow; + } + break; + case eNPP_StreamAsFile: + { + UINT32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + UINT32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + char* fname = pMessage->GetString(); + medDebug( 1, "pluginapp: NPP_StreamAsFile %s\n", fname ); + aPluginFuncs.asfile( instance, pStream, fname ); + delete [] fname; + } + break; + case eNPP_URLNotify: + { + UINT32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + char* url = pMessage->GetString(); + NPReason* pReason = (NPReason*)pMessage->GetBytes(); + void** notifyData = (void**)pMessage->GetBytes(); + aPluginFuncs.urlnotify( instance, url, *pReason, *notifyData ); + delete [] url; + delete [] pReason; + delete [] notifyData; + } + break; + case eNPP_WriteReady: + { + UINT32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + UINT32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + int32 nRet = aPluginFuncs.writeready( instance, pStream ); + + medDebug( 1, "pluginapp: NPP_WriteReady( %p, %p ) (stream id = %d) returns %d\n", + instance, pStream, nFileID, nRet ); + + Respond( pMessage->m_nID, + (char*)&nRet, sizeof( nRet ), + NULL ); + } + break; + case eNPP_Write: + { + UINT32 nInstance = pMessage->GetUINT32(); + NPP instance = m_aInstances[ nInstance ]->instance; + UINT32 nFileID = pMessage->GetUINT32(); + NPStream* pStream = m_aNPWrapStreams[ nFileID ]; + int32 offset = pMessage->GetUINT32(); + ULONG len; + char* buffer = (char*)pMessage->GetBytes( len ); + int32 nRet = aPluginFuncs.write( instance, pStream, offset, len, buffer ); + + medDebug( 1,"pluginapp: NPP_Write( %p, %p, %d, %d, %p ) returns %d\n" + "stream = { pdata = %p, ndata = %p, url = %s, end = %d, lastmodified = %d, notifyData = %p }\n", + instance, pStream, offset, len, buffer, nRet, + pStream->pdata, pStream->ndata, pStream->url, pStream->end, pStream->lastmodified, pStream->notifyData ); + + Respond( pMessage->m_nID, + (char*)&nRet, sizeof( nRet ), + NULL ); + delete [] buffer; + } + break; + case eNPP_GetMIMEDescription: + { + if( ! pNPP_GetMIMEDescription ) + pNPP_GetMIMEDescription = (char*(*)()) + osl_getAsciiFunctionSymbol( pPluginLib, "NPP_GetMIMEDescription" ); + char* pMIME = pNPP_GetMIMEDescription(); + Respond( pMessage->m_nID, + POST_STRING( pMIME ), + NULL ); + } + break; + case eNPP_Initialize: + { + + pNP_Initialize = + (NPError(*)(NPNetscapeFuncs*, NPPluginFuncs*)) + osl_getAsciiFunctionSymbol( pPluginLib, "NP_Initialize" ); + medDebug( !pNP_Initialize, "no NP_Initialize, %s\n", dlerror() ); + pNP_Shutdown = (NPError(*)()) + osl_getAsciiFunctionSymbol( pPluginLib, "NP_Shutdown" ); + medDebug( !pNP_Initialize, "no NP_Shutdown, %s\n", dlerror() ); + + medDebug( 1, "entering NP_Initialize\n" ); + NPError aRet = pNP_Initialize( &aNetscapeFuncs, &aPluginFuncs ); + medDebug( 1, "pluginapp: NP_Initialize returns %d\n", (int) aRet ); + Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL ); + } + break; + case eNPP_Shutdown: + { + write( wakeup_fd[1], "xxxx", 4 ); + } + break; + default: + medDebug( 1, "caught unknown NPP request %d\n", nCommand ); + break; + } + delete pMessage; + } + return 0; +} + +void LoadAdditionalLibs( const char* _pPluginLib ) +{ + medDebug( 1, "LoadAdditionalLibs %s\n", _pPluginLib ); + + if( ! strncmp( _pPluginLib, "libflashplayer.so", 17 ) ) + { + /* #b4951312# flash 7 implicitly assumes a gtk application + * if the API version is greater or equal to 12 (probably + * because they think they run in mozilla then). In that + * case they try to find gtk within the process and crash + * when they don't find it. + */ + aNetscapeFuncs.version = 11; + aPluginFuncs.version = 11; + } +} + |