bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / plugin / unx / npnapi.cxx
blobc56f37b5c3f5862612cb25573db69d3a59d781bf
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #ifdef AIX
31 #define _LINUX_SOURCE_COMPAT
32 #include <sys/timer.h>
33 #undef _LINUX_SOURCE_COMPAT
34 #endif
36 #include <plugin/unx/plugcon.hxx>
38 #include <unistd.h>
39 #include <dlfcn.h>
41 #include <osl/module.h>
42 #include <sal/log.hxx>
44 #include <config_vclplug.h>
46 #include <npwrap.hxx>
48 extern PluginConnector* pConnector;
49 extern XtAppContext app_context;
50 extern int wakeup_fd[];
51 extern Widget topLevel, topBox;
52 extern Display* pAppDisplay;
53 extern Display* pXtAppDisplay;
54 extern int nAppArguments;
55 extern char** pAppArguments;
57 // begin Netscape plugin api calls
58 extern "C" {
60 static void* l_NPN_MemAlloc( uint32_t nBytes )
62 void* pMem = new char[nBytes];
63 return pMem;
66 static void l_NPN_MemFree( void* pMem )
68 delete [] static_cast<char*>(pMem);
71 static uint32_t l_NPN_MemFlush( uint32_t /*nSize*/ )
73 return 0;
76 static NPError l_NPN_DestroyStream( NPP instance, NPStream* stream, NPError reason )
78 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
79 if( nInstance == PluginConnector::UnknownNPPID )
80 return NPERR_GENERIC_ERROR;
82 sal_uInt32 nFileID = pConnector->GetStreamID( stream );
83 MediatorMessage* pMes=
84 pConnector->
85 Transact( eNPN_DestroyStream,
86 &nInstance, sizeof( nInstance ),
87 &nFileID, sizeof( nFileID ),
88 POST_STRING( stream->url ),
89 &reason, sizeof( reason ),
90 NULL );
92 if( ! pMes )
93 return NPERR_GENERIC_ERROR;
95 for( std::vector< NPStream* >::iterator it = pConnector->getStreamList().begin();
96 it != pConnector->getStreamList().end(); ++it )
98 if( *it == stream )
100 pConnector->getStreamList().erase( it );
101 break;
104 delete [] stream->url;
105 delete stream;
106 // returns NPError
107 NPError aRet = PluginConnector::GetNPError( pMes );
108 delete pMes;
109 return aRet;
112 #ifdef OJI
113 static JRIEnv* l_NPN_GetJavaEnv()
115 // no java in this program
116 SAL_INFO("extensions.plugin", "SNI: NPN_GetJavaEnv");
117 return NULL;
120 static jref l_NPN_GetJavaPeer( NPP /*instance*/ )
122 SAL_INFO("extensions.plugin", "SNI: NPN_GetJavaPeer");
123 return NULL;
125 #endif
127 static NPError l_NPN_GetURL( NPP instance, const char* url, const char* window )
129 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
130 if( nInstance == PluginConnector::UnknownNPPID )
131 return NPERR_GENERIC_ERROR;
133 MediatorMessage* pMes=
134 pConnector->
135 Transact( eNPN_GetURL,
136 &nInstance, sizeof( nInstance ),
137 POST_STRING(url),
138 POST_STRING(window),
139 NULL );
140 SAL_WARN_IF(!pMes, "extensions.plugin", "geturl: message unanswered");
141 if( ! pMes )
142 return NPERR_GENERIC_ERROR;
144 // returns NPError
145 NPError aRet = PluginConnector::GetNPError( pMes );
146 SAL_WARN_IF(aRet, "extensions.plugin", "geturl returns " << aRet);
147 delete pMes;
148 return aRet;
151 static NPError l_NPN_GetURLNotify( NPP instance, const char* url, const char* target,
152 void* notifyData )
154 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
155 if( nInstance == PluginConnector::UnknownNPPID )
156 return NPERR_GENERIC_ERROR;
158 MediatorMessage* pMes=
159 pConnector->
160 Transact( eNPN_GetURLNotify,
161 &nInstance, sizeof( nInstance ),
162 POST_STRING(url),
163 POST_STRING(target),
164 &notifyData, sizeof( void* ), // transmit the actual pointer
165 // since it is a pointer to private data fed back
166 // by NPP_URLNotify; this can be thought of as an ID
167 NULL );
168 if( ! pMes )
169 return NPERR_GENERIC_ERROR;
171 // returns NPError
172 NPError aRet = PluginConnector::GetNPError( pMes );
173 delete pMes;
174 return aRet;
177 static NPError l_NPN_NewStream( NPP instance, NPMIMEType type, const char* target,
178 NPStream** stream )
179 // stream is a return value
181 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
182 if( nInstance == PluginConnector::UnknownNPPID )
183 return NPERR_GENERIC_ERROR;
185 MediatorMessage* pMes=
186 pConnector->
187 Transact( eNPN_NewStream,
188 &nInstance, sizeof( nInstance ),
189 POST_STRING(type),
190 POST_STRING(target),
191 NULL );
192 if( ! pMes )
193 return NPERR_GENERIC_ERROR;
195 // returns a new NPStream and an error
196 NPError aRet = PluginConnector::GetNPError( pMes );
197 if( ! aRet )
199 NPStream* pStream = new NPStream;
200 pStream->url = pMes->GetString();
201 pStream->end = pMes->GetUINT32();
202 pStream->lastmodified = pMes->GetUINT32();
203 pStream->ndata = pStream->pdata = pStream->notifyData = NULL;
205 pConnector->getStreamList().push_back( pStream );
206 *stream = pStream;
209 delete pMes;
210 return aRet;
213 static NPError l_NPN_PostURLNotify( NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData )
215 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
216 if( nInstance == PluginConnector::UnknownNPPID )
217 return NPERR_GENERIC_ERROR;
219 MediatorMessage* pMes = pConnector->
220 Transact( eNPN_PostURLNotify,
221 &nInstance, sizeof( nInstance ),
222 POST_STRING( url ),
223 POST_STRING( target ),
224 &len, sizeof( len ),
225 buf, len,
226 &file, sizeof( NPBool ),
227 &notifyData, sizeof( void* ), // send the real pointer
228 NULL );
230 if( ! pMes )
231 return NPERR_GENERIC_ERROR;
233 NPError aRet = PluginConnector::GetNPError( pMes );
234 delete pMes;
235 return aRet;
238 static NPError l_NPN_PostURL( NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file )
240 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
241 if( nInstance == PluginConnector::UnknownNPPID )
242 return NPERR_GENERIC_ERROR;
244 MediatorMessage* pMes = pConnector->
245 Transact( eNPN_PostURL,
246 &nInstance, sizeof( nInstance ),
247 POST_STRING( url ),
248 POST_STRING( window ),
249 &len, sizeof( len ),
250 buf, len,
251 &file, sizeof( NPBool ),
252 NULL );
253 if( ! pMes )
254 return NPERR_GENERIC_ERROR;
256 NPError aRet = PluginConnector::GetNPError( pMes );
257 delete pMes;
258 return aRet;
261 static NPError l_NPN_RequestRead( NPStream* stream, NPByteRange* rangeList )
263 SAL_INFO("extensions.plugin", "pluginapp: NPN_RequestRead");
265 NPByteRange* pRange = rangeList;
266 sal_uInt32 nRanges = 0;
267 while( pRange )
269 nRanges++;
270 pRange = pRange->next;
273 sal_uInt32* pArray = new sal_uInt32[ 2 * nRanges ];
274 pRange = rangeList;
275 sal_uInt32 n = 0;
276 while( pRange )
278 pArray[ 2*n ] = (sal_uInt32)pRange->offset;
279 pArray[ 2*n + 1] = (sal_uInt32)pRange->length;
280 n++;
281 pRange = pRange->next;
283 sal_uInt32 nFileID = pConnector->GetStreamID( stream );
284 MediatorMessage* pMes = pConnector->
285 Transact( eNPN_RequestRead,
286 &nFileID, sizeof( nFileID ),
287 &nRanges, sizeof( nRanges ),
288 pArray, sizeof( sal_uInt32 ) * 2 * nRanges,
289 NULL );
291 if( ! pMes )
293 delete[] pArray;
294 return NPERR_GENERIC_ERROR;
297 NPError aRet = PluginConnector::GetNPError( pMes );
298 delete [] pArray;
299 delete pMes;
300 return aRet;
303 static void l_NPN_Status( NPP instance, const char* message )
305 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
306 if( nInstance == PluginConnector::UnknownNPPID )
307 return;
309 pConnector->Send( eNPN_Status,
310 &nInstance, sizeof( nInstance ),
311 POST_STRING( message ),
312 NULL );
315 static const char* l_NPN_UserAgent( NPP instance )
317 static char* pAgent = NULL;
319 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
320 if( nInstance == PluginConnector::UnknownNPPID )
322 if( instance )
323 return "Mozilla 3.0";
324 else // e.g. flashplayer calls NPN_UserAgent with NULL
325 nInstance = 0;
328 MediatorMessage* pMes = pConnector->
329 Transact( eNPN_UserAgent,
330 &nInstance, sizeof( nInstance ),
331 NULL );
333 if( ! pMes )
334 return pAgent;
336 if( pAgent )
337 delete [] pAgent;
338 pAgent = pMes->GetString();
340 delete pMes;
342 SAL_INFO("extensions.plugin", "NPN_UserAgent returns " << pAgent);
344 return pAgent;
347 static int32_t l_NPN_Write( NPP instance, NPStream* stream, int32_t len, void* buffer )
349 sal_uInt32 nFileID = pConnector->GetStreamID( stream );
350 if( nFileID == PluginConnector::UnknownStreamID )
351 return NPERR_GENERIC_ERROR;
352 sal_uInt32 nInstance = pConnector->GetNPPID( instance );
353 if( nInstance == PluginConnector::UnknownNPPID )
354 return NPERR_GENERIC_ERROR;
356 MediatorMessage* pMes = pConnector->
357 Transact( eNPN_Write,
358 &nInstance, sizeof( nInstance ),
359 &nFileID, sizeof( nFileID ),
360 &len, sizeof( len ),
361 buffer, len,
362 NULL );
364 if( ! pMes )
365 return 0;
367 sal_Int32 nRet = pMes->GetUINT32();
368 return nRet;
371 static void l_NPN_ReloadPlugins( NPBool /*reloadPages*/ )
373 SAL_INFO("extensions.plugin", "NPN_ReloadPlugins: SNI");
376 static NPError l_NPN_GetValue( NPP, NPNVariable variable, void* value )
379 * We want to handle values injected into a NPNVariable which aren't in
380 * the old enum we build against, but that we know are in the new enum
381 * we want to support
383 switch( (int)variable )
385 case NPNVxDisplay:
386 *static_cast<Display**>(value) = pXtAppDisplay;
387 SAL_INFO("extensions.plugin", "Display requested");
388 break;
389 case NPNVxtAppContext:
390 *static_cast<XtAppContext*>(value) = app_context;
391 SAL_INFO("extensions.plugin", "AppContext requested");
392 break;
393 case NPNVjavascriptEnabledBool:
394 // no javascript
395 *static_cast<NPBool*>(value) = false;
396 SAL_INFO("extensions.plugin", "javascript enabled requested");
397 break;
398 case NPNVasdEnabledBool:
399 // no SmartUpdate
400 *static_cast<NPBool*>(value) = false;
401 SAL_INFO("extensions.plugin", "smart update enabled requested");
402 break;
403 case NPNVisOfflineBool:
404 // no offline browsing
405 *static_cast<NPBool*>(value) = false;
406 SAL_INFO("extensions.plugin", "offline browsing requested");
407 break;
408 case NPNVSupportsXEmbedBool:
409 // asking xembed
410 *static_cast<int*>(value) = int(true);
411 SAL_INFO("extensions.plugin", "xembed requested");
412 break;
413 case NPNVToolkit:
414 # if ENABLE_GTK
415 *static_cast<int*>(value) = NPNVGtk2;
416 # else
417 *(int*)value = 0;
418 # endif
419 SAL_INFO("extensions.plugin", "toolkit requested");
420 break;
421 default:
422 SAL_WARN(
423 "extensions.plugin",
424 "unknown NPNVariable " << +variable << " requested");
425 return NPERR_INVALID_PARAM;
427 return NPERR_NO_ERROR;
430 static NPError l_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void *value)
432 SAL_INFO("extensions.plugin", "NPN_SetValue " << +variable << "=" << value);
433 return 0;
436 static void l_NPN_InvalidateRect(NPP /*instance*/, NPRect* /*invalidRect*/)
438 SAL_INFO("extensions.plugin", "NPN_InvalidateRect");
441 static void l_NPN_InvalidateRegion(NPP /*instance*/, NPRegion /*invalidRegion*/)
443 SAL_INFO("extensions.plugin", "NPN_InvalidateRegion");
446 static void l_NPN_ForceRedraw(NPP /*instance*/)
448 SAL_INFO("extensions.plugin", "NPN_ForceRedraw");
453 static NPNetscapeFuncs aNetscapeFuncs =
455 sizeof(aNetscapeFuncs),
456 (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR,
457 l_NPN_GetURL,
458 l_NPN_PostURL,
459 l_NPN_RequestRead,
460 l_NPN_NewStream,
461 l_NPN_Write,
462 l_NPN_DestroyStream,
463 l_NPN_Status,
464 l_NPN_UserAgent,
465 l_NPN_MemAlloc,
466 l_NPN_MemFree,
467 l_NPN_MemFlush,
468 l_NPN_ReloadPlugins,
469 # ifdef OJI
470 l_NPN_GetJavaEnv,
471 l_NPN_GetJavaPeer,
472 # else
473 NULL,
474 NULL,
475 # endif
476 l_NPN_GetURLNotify,
477 l_NPN_PostURLNotify,
478 l_NPN_GetValue,
479 l_NPN_SetValue,
480 l_NPN_InvalidateRect,
481 l_NPN_InvalidateRegion,
482 l_NPN_ForceRedraw
485 static NPPluginFuncs aPluginFuncs =
487 sizeof(aPluginFuncs),
488 (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR,
489 NULL,
490 NULL,
491 NULL,
492 NULL,
493 NULL,
494 NULL,
495 NULL,
496 NULL,
497 NULL,
498 NULL,
499 NULL,
500 NULL,
501 NULL,
502 NULL
506 oslModule pPluginLib = NULL;
507 char*(*pNPP_GetMIMEDescription)() = NULL;
508 NPError (*pNP_Initialize)(NPNetscapeFuncs*,NPPluginFuncs*) = NULL;
509 NPError (*pNP_Shutdown)() = NULL;
511 std::vector< PluginConnector* > PluginConnector::allConnectors;
513 PluginConnector::PluginConnector( int nSocket ) :
514 Mediator( nSocket )
516 SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) );
519 PluginConnector::~PluginConnector()
523 IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ )
525 MediatorMessage* pMessage;
526 CommandAtoms nCommand;
527 while( (pMessage = GetNextMessage( false )) )
529 nCommand = (CommandAtoms)pMessage->GetUINT32();
530 SAL_INFO(
531 "extensions.plugin", "pluginapp: " << GetCommandName(nCommand));
532 switch( nCommand )
534 case eNPP_DestroyStream:
536 sal_uInt32 nInstance = pMessage->GetUINT32();
537 NPP instance = m_aInstances[ nInstance ]->instance;
538 sal_uInt32 nFileID = pMessage->GetUINT32();
539 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
540 NPError aReason = GetNPError( pMessage );
541 m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
543 aReason = aPluginFuncs.destroystream( instance, pStream, aReason );
544 Respond( pMessage->m_nID,
545 reinterpret_cast<char*>(&aReason), sizeof( aReason ),
546 NULL );
548 delete [] pStream->url;
549 delete pStream;
551 break;
552 case eNPP_Destroy:
554 sal_uInt32 nInstance = pMessage->GetUINT32();
555 ConnectorInstance* pInst= m_aInstances[ nInstance ];
557 // some plugin rely on old netscapes behaviour
558 // to first destroy the widget and then destroy
559 // the instance, so mimic that behaviour here
560 if( pInst->pShell )
561 XtDestroyWidget( static_cast<Widget>(pInst->pShell) );
563 pInst->pWidget = pInst->pShell = NULL;
565 // the other side will call eNPP_DestroyPhase2 after this
566 NPError aReason = NPERR_NO_ERROR;
567 Respond( pMessage->m_nID, reinterpret_cast<char*>(&aReason), sizeof( aReason ), NULL );
569 break;
570 case eNPP_DestroyPhase2:
572 // now really destroy the instance
573 sal_uInt32 nInstance = pMessage->GetUINT32();
574 ConnectorInstance* pInst= m_aInstances[ nInstance ];
575 NPP instance = pInst->instance;
576 NPSavedData* pSave = NULL;
578 NPError aRet = aPluginFuncs.destroy( instance, &pSave );
579 if( pSave )
581 Respond( pMessage->m_nID,
582 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
583 pSave->buf, pSave->len,
584 NULL );
585 delete [] static_cast<char*>(pSave->buf);
587 else
588 Respond( pMessage->m_nID,
589 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
590 "0000", 4,
591 NULL );
593 #if ENABLE_GTK
594 if( pInst->pGtkWindow )
595 g_object_unref( G_OBJECT(pInst->pGtkWindow) );
596 if( pInst->pGtkWidget )
597 g_object_unref( G_OBJECT(pInst->pGtkWidget) );
598 #endif
600 m_aInstances.erase( m_aInstances.begin() + nInstance );
601 delete pInst;
602 delete instance;
603 SAL_INFO(
604 "extensions.plugin",
605 "destroyed instance (returning " << aRet << ")");
607 break;
608 case eNPP_NewStream:
610 sal_uInt32 nInstance = pMessage->GetUINT32();
611 NPP instance = m_aInstances[ nInstance ]->instance;
612 char* pType = pMessage->GetString();
613 NPStream* pStream = new NPStream;
614 pStream->url = pMessage->GetString();
615 pStream->end = pMessage->GetUINT32();
616 pStream->lastmodified = pMessage->GetUINT32();
617 pStream->pdata = pStream->ndata = pStream->notifyData = NULL;
618 NPBool* pSeekable = static_cast<NPBool*>(pMessage->GetBytes());
619 m_aNPWrapStreams.push_back( pStream );
620 uint16_t nStype = NP_ASFILE;
621 NPError aRet = aPluginFuncs.newstream( instance, pType, pStream,
622 *pSeekable, &nStype );
623 SAL_INFO(
624 "extensions.plugin",
625 "pluginapp: NPP_NewStream(" << instance << ", " << pType
626 << ", " << pStream << ", "
627 << (*pSeekable ? "seekable" : "not seekable") << ", "
628 << &nStype << ") returns " << aRet
629 << "; stream = { pdata = " << pStream->pdata
630 << ", ndata = " << pStream->ndata << ", url = "
631 << pStream->url << ", end = " << pStream->end
632 << ", lastmodified = " << pStream->lastmodified
633 << ", notifyData = " << pStream->notifyData << " }");
634 Respond( pMessage->m_nID,
635 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
636 &nStype, sizeof( nStype ),
637 NULL );
638 delete [] pType;
639 delete [] pSeekable;
641 break;
642 case eNPP_New:
644 char* pType = pMessage->GetString();
645 uint16_t* pMode = static_cast<uint16_t*>(pMessage->GetBytes());
646 int16_t* pArgc = static_cast<int16_t*>(pMessage->GetBytes());
647 NPP instance = new NPP_t;
648 instance->pdata = instance->ndata = NULL;
649 sal_uLong nArgnBytes, nArgvBytes;
650 char* pArgn = static_cast<char*>(pMessage->GetBytes( nArgnBytes ));
651 char* pArgv = static_cast<char*>(pMessage->GetBytes( nArgvBytes ));
652 sal_uLong nSaveBytes;
653 char* pSavedData = static_cast<char*>(pMessage->GetBytes( nSaveBytes ));
654 ConnectorInstance* pInst =
655 new ConnectorInstance( instance, pType,
656 *pArgc,
657 pArgn, nArgnBytes,
658 pArgv, nArgvBytes,
659 pSavedData, nSaveBytes );
660 m_aInstances.push_back( pInst );
661 NPError aRet;
662 aRet = aPluginFuncs.newp( pInst->pMimeType, instance, *pMode, *pArgc,
663 pInst->nArg ? pInst->argn : NULL,
664 pInst->nArg ? pInst->argv : NULL,
665 ( nSaveBytes == 4 && *reinterpret_cast<sal_uInt32*>(pSavedData) == 0 ) ?
666 &(pInst->aData) : NULL );
667 SAL_INFO(
668 "extensions.plugin",
669 "pluginapp: NPP_New( " << pInst->pMimeType << ", "
670 << instance << ", " << *pMode << ", " << pInst->nArg
671 << ", " << pInst->argn << ", " << pInst->argv << ", "
672 << &pInst->aData << ") returns" << aRet);
673 for( int i = 0; i < pInst->nArg; i++ )
674 SAL_INFO(
675 "extensions.plugin",
676 " \"" << pInst->argn[i] << "\"=\"" << pInst->argv[i]
677 << "\"");
679 #if ENABLE_GTK
680 // check if XEMBED is to be used
681 // ask for Bool. there seems to be no clear definition whether the
682 // return value should be an int or unsigned char
683 // int can hold both and will be nonzero in case of "true"
684 if( aPluginFuncs.getvalue )
686 int bNeedsXEmbed = 0;
687 NPError error = aPluginFuncs.getvalue( instance, NPPVpluginNeedsXEmbed, (void *)&bNeedsXEmbed );
688 if( error == NPERR_NO_ERROR )
689 pInst->bShouldUseXEmbed = (bNeedsXEmbed != 0);
690 SAL_INFO(
691 "extensions.plugin",
692 "should use xembed = "
693 << (pInst->bShouldUseXEmbed ? "true" : "false"));
695 #endif
697 Respond( pMessage->m_nID,
698 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
699 NULL );
700 delete [] pMode;
701 delete [] pArgc;
702 delete [] pType;
704 break;
705 case eNPP_SetWindow:
707 sal_uInt32 nInstance = pMessage->GetUINT32();
708 ConnectorInstance* pInst= m_aInstances[ nInstance ];
709 NPWindow* pWindow = static_cast<NPWindow*>(pMessage->GetBytes());
711 if( pWindow->width < 1 )
712 pWindow->width = 1;
713 if( pWindow->height < 1 )
714 pWindow->height = 1;
716 #if ENABLE_GTK
717 if( pInst->bShouldUseXEmbed )
719 if( ! pInst->pGtkWidget )
721 SAL_INFO(
722 "extensions.plugin",
723 "creating gtk plug and socket");
725 pInst->pGtkWindow = gtk_plug_new((GdkNativeWindow)reinterpret_cast<sal_uIntPtr>(pWindow->window));
726 gtk_widget_show( pInst->pGtkWindow );
727 pInst->pGtkWidget = gtk_socket_new();
728 gtk_widget_show( pInst->pGtkWidget );
729 gtk_container_add( GTK_CONTAINER(pInst->pGtkWindow), pInst->pGtkWidget );
730 gtk_widget_show_all( pInst->pGtkWindow );
731 pInst->window.window = reinterpret_cast<void *>(gtk_socket_get_id( GTK_SOCKET(pInst->pGtkWidget ) ));
733 XSync( pAppDisplay, False );
735 XMapWindow( pAppDisplay, GDK_WINDOW_XWINDOW(pInst->pGtkWindow->window) );
737 XSync( pAppDisplay, False );
740 // update widget size; alas out parent is not yet really XEMBED conformant
741 gtk_widget_set_size_request( pInst->pGtkWidget, pWindow->width, pWindow->height );
742 gtk_window_resize( GTK_WINDOW(pInst->pGtkWindow), pWindow->width, pWindow->height );
744 GdkScreen* pGdkScreen = gtk_widget_get_screen( pInst->pGtkWidget );
745 Screen* pScreen = ScreenOfDisplay( pAppDisplay, gdk_screen_get_number( pGdkScreen ) );
747 pInst->window.x = 0;
748 pInst->window.y = 0;
749 pInst->window.width = pWindow->width;
750 pInst->window.height = pWindow->height;
751 pInst->window.clipRect.left = 0;
752 pInst->window.clipRect.top = 0;
753 pInst->window.clipRect.right = pWindow->width;
754 pInst->window.clipRect.bottom = pWindow->height;
755 pInst->window.ws_info = &pInst->ws_info;
756 pInst->window.type = NPWindowTypeWindow;
757 pInst->ws_info.type = NP_SETWINDOW;
758 pInst->ws_info.display = pAppDisplay;
759 pInst->ws_info.visual = DefaultVisualOfScreen( pScreen );
760 pInst->ws_info.colormap = DefaultColormapOfScreen( pScreen );
761 pInst->ws_info.depth = DefaultDepthOfScreen( pScreen );
763 else
764 #endif
766 if( ! pInst->pWidget )
768 pInst->pWidget = CreateNewShell( &(pInst->pShell), reinterpret_cast<Window>(pWindow->window) );
771 // fill in NPWindow and NPCallbackStruct
772 pInst->window.window = reinterpret_cast<void*>(XtWindow( static_cast<Widget>(pInst->pWidget) ));
773 pInst->window.x = 0;
774 pInst->window.y = 0;
775 pInst->window.width = pWindow->width;
776 pInst->window.height = pWindow->height;
777 pInst->window.clipRect.left = 0;
778 pInst->window.clipRect.top = 0;
779 pInst->window.clipRect.right = pWindow->width;
780 pInst->window.clipRect.bottom = pWindow->height;
781 pInst->window.ws_info = &pInst->ws_info;
782 pInst->window.type = NPWindowTypeWindow;
783 pInst->ws_info.type = NP_SETWINDOW;
784 pInst->ws_info.display = XtDisplay( static_cast<Widget>(pInst->pWidget) );
785 pInst->ws_info.visual = DefaultVisualOfScreen( XtScreen( static_cast<Widget>(pInst->pWidget) ) );
786 pInst->ws_info.colormap = DefaultColormapOfScreen( XtScreen( static_cast<Widget>(pInst->pWidget) ) );
787 pInst->ws_info.depth = DefaultDepthOfScreen( XtScreen( static_cast<Widget>(pInst->pWidget) ) );
789 XtResizeWidget( static_cast<Widget>(pInst->pShell),
790 pInst->window.width,
791 pInst->window.height,
792 0 );
793 XtResizeWidget( static_cast<Widget>(pInst->pWidget),
794 pInst->window.width,
795 pInst->window.height,
796 0 );
799 NPError aRet = aPluginFuncs.setwindow( pInst->instance, &pInst->window );
800 SAL_INFO(
801 "extensions.plugin",
802 "pluginapp: NPP_SetWindow returns " << aRet);
803 Respond( pMessage->m_nID,
804 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
805 NULL );
806 delete [] reinterpret_cast<char*>(pWindow);
808 break;
809 case eNPP_StreamAsFile:
811 sal_uInt32 nInstance = pMessage->GetUINT32();
812 NPP instance = m_aInstances[ nInstance ]->instance;
813 sal_uInt32 nFileID = pMessage->GetUINT32();
814 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
815 char* fname = pMessage->GetString();
816 SAL_INFO(
817 "extensions.plugin",
818 "pluginapp: NPP_StreamAsFile " << fname);
819 aPluginFuncs.asfile( instance, pStream, fname );
820 delete [] fname;
822 break;
823 case eNPP_URLNotify:
825 sal_uInt32 nInstance = pMessage->GetUINT32();
826 NPP instance = m_aInstances[ nInstance ]->instance;
827 char* url = pMessage->GetString();
828 NPReason* pReason = static_cast<NPReason*>(pMessage->GetBytes());
829 void** notifyData = static_cast<void**>(pMessage->GetBytes());
830 aPluginFuncs.urlnotify( instance, url, *pReason, *notifyData );
831 delete [] url;
832 delete [] pReason;
833 delete [] notifyData;
835 break;
836 case eNPP_WriteReady:
838 sal_uInt32 nInstance = pMessage->GetUINT32();
839 NPP instance = m_aInstances[ nInstance ]->instance;
840 sal_uInt32 nFileID = pMessage->GetUINT32();
841 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
842 int32_t nRet = aPluginFuncs.writeready( instance, pStream );
844 SAL_INFO(
845 "extensions.plugin",
846 "pluginapp: NPP_WriteReady(" << instance << ", " << pStream
847 << ") (stream id = " << nFileID << ") returns "
848 << nRet);
850 Respond( pMessage->m_nID,
851 reinterpret_cast<char*>(&nRet), sizeof( nRet ),
852 NULL );
854 break;
855 case eNPP_Write:
857 sal_uInt32 nInstance = pMessage->GetUINT32();
858 NPP instance = m_aInstances[ nInstance ]->instance;
859 sal_uInt32 nFileID = pMessage->GetUINT32();
860 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
861 int32_t offset = pMessage->GetUINT32();
862 sal_uLong len;
863 char* buffer = static_cast<char*>(pMessage->GetBytes( len ));
864 int32_t nRet = aPluginFuncs.write( instance, pStream, offset, len, buffer );
866 SAL_INFO(
867 "extensions.plugin",
868 "pluginapp: NPP_Write(" << instance << ", " << pStream
869 << ", " << offset << ", " << len << ", " << buffer
870 << ") returns " << nRet << "; stream = { pdata = "
871 << pStream->pdata << ", ndata = " << pStream->ndata
872 << ", url = " << pStream->url << ", end = "
873 << pStream->end << ", lastmodified = "
874 << pStream->lastmodified << ", notifyData = "
875 << pStream->notifyData << " }");
877 Respond( pMessage->m_nID,
878 reinterpret_cast<char*>(&nRet), sizeof( nRet ),
879 NULL );
880 delete [] buffer;
882 break;
883 case eNPP_GetMIMEDescription:
885 if( ! pNPP_GetMIMEDescription )
886 pNPP_GetMIMEDescription = reinterpret_cast<char*(*)()>(
887 osl_getAsciiFunctionSymbol( pPluginLib, "NPP_GetMIMEDescription" ));
888 char* pMIME = pNPP_GetMIMEDescription();
889 Respond( pMessage->m_nID,
890 POST_NONCONST_STRING( pMIME ),
891 NULL );
893 break;
894 case eNPP_Initialize:
897 pNP_Initialize =
898 reinterpret_cast<NPError(*)(NPNetscapeFuncs*, NPPluginFuncs*)>(
899 osl_getAsciiFunctionSymbol( pPluginLib, "NP_Initialize" ));
900 SAL_WARN_IF(
901 !pNP_Initialize, "extensions.plugin",
902 "no NP_Initialize, " << dlerror());
903 pNP_Shutdown = reinterpret_cast<NPError(*)()>(
904 osl_getAsciiFunctionSymbol( pPluginLib, "NP_Shutdown" ));
905 SAL_WARN_IF(
906 !pNP_Initialize, "extensions.plugin",
907 "no NP_Shutdown, " << dlerror());
909 SAL_INFO("extensions.plugin", "entering NP_Initialize");
910 NPError aRet = pNP_Initialize( &aNetscapeFuncs, &aPluginFuncs );
911 SAL_INFO(
912 "extensions.plugin",
913 "pluginapp: NP_Initialize returns " << aRet);
914 Respond( pMessage->m_nID, reinterpret_cast<char*>(&aRet), sizeof( aRet ), NULL );
916 break;
917 case eNPP_Shutdown:
919 bool bSuccess = (4 == write(wakeup_fd[1], "xxxx", 4));
920 SAL_WARN_IF(!bSuccess, "extensions.plugin", "short write");
922 break;
923 default:
924 SAL_WARN(
925 "extensions.plugin",
926 "caught unknown NPP request " << +nCommand);
927 break;
929 delete pMessage;
931 return 0;
934 void LoadAdditionalLibs( const char* _pPluginLib )
936 SAL_INFO("extensions.plugin", "LoadAdditionalLibs " << _pPluginLib);
938 if( ! strncmp( _pPluginLib, "libflashplayer.so", 17 ) )
940 /* #b4951312# flash 7 implicitly assumes a gtk application
941 * if the API version is greater or equal to 12 (probably
942 * because they think they run in mozilla then). In that
943 * case they try to find gtk within the process and crash
944 * when they don't find it.
946 aNetscapeFuncs.version = 11;
947 aPluginFuncs.version = 11;
951 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */