update credits
[LibreOffice.git] / extensions / source / plugin / unx / nppapi.cxx
blobff4733f12a15354ad8c7d7d2171f26dbcb40d648
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 <cstdarg>
38 #include <vcl/svapp.hxx>
40 #include <plugin/unx/plugcon.hxx>
41 #include <plugin/impl.hxx>
43 std::vector<PluginConnector*> PluginConnector::allConnectors;
45 PluginConnector::PluginConnector( int nSocket ) :
46 Mediator( nSocket )
48 allConnectors.push_back( this );
49 SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) );
52 PluginConnector::~PluginConnector()
54 osl::MutexGuard aGuard( m_aUserEventMutex );
55 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
56 it != allConnectors.end(); ++it )
58 if( *it == this )
60 allConnectors.erase( it );
61 break;
66 IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, /*pMediator*/ )
68 osl::MutexGuard aGuard( m_aUserEventMutex );
69 bool bFound = false;
70 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
71 it != allConnectors.end() && bFound == false; ++it )
73 if( *it == this )
74 bFound = true;
76 if( ! bFound )
77 return 0;
78 Application::PostUserEvent( LINK( this, PluginConnector, WorkOnNewMessageHdl ) );
79 return 0;
82 IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ )
84 bool bFound = false;
85 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
86 it != allConnectors.end() && bFound == false; ++it )
88 if( *it == this )
89 bFound = true;
91 if( ! bFound )
92 return 0;
94 MediatorMessage* pMessage;
95 CommandAtoms nCommand;
96 while( (pMessage = GetNextMessage( sal_False )) )
98 nCommand = (CommandAtoms)pMessage->GetUINT32();
99 SAL_INFO("extensions.plugin", GetCommandName(nCommand));
100 switch( nCommand )
102 case eNPN_GetURL:
104 sal_uInt32 nInstance = pMessage->GetUINT32();
105 NPP instance = m_aInstances[ nInstance ]->instance;
106 char* pUrl = pMessage->GetString();
107 char* pWindow = pMessage->GetString();
108 NPError aRet = NPN_GetURL( instance, pUrl, pWindow );
109 Respond( pMessage->m_nID,
110 (char*)(&aRet), sizeof( NPError ), NULL );
111 delete [] pUrl;
112 delete [] pWindow;
114 break;
115 case eNPN_GetURLNotify:
117 sal_uInt32 nInstance = pMessage->GetUINT32();
118 NPP instance = m_aInstances[ nInstance ]->instance;
119 char* pUrl = pMessage->GetString();
120 char* pWindow = pMessage->GetString();
121 void** pNotifyData = (void**)pMessage->GetBytes();
122 NPError aRet = NPN_GetURLNotify( instance, pUrl, pWindow,
123 *pNotifyData );
124 Respond( pMessage->m_nID,
125 (char*)(&aRet), sizeof( NPError ), NULL );
126 delete [] pUrl;
127 delete [] pWindow;
128 delete [] pNotifyData;
130 break;
131 case eNPN_DestroyStream:
133 sal_uInt32 nInstance = pMessage->GetUINT32();
134 NPP instance = m_aInstances[ nInstance ]->instance;
135 sal_uInt32 nFileID = pMessage->GetUINT32();
136 char* pUrl = pMessage->GetString();
137 NPError* pReason = (NPError*)pMessage->GetBytes();
138 NPError aRet = NPERR_FILE_NOT_FOUND;
139 if( nFileID < static_cast<sal_uInt32>(m_aNPWrapStreams.size()) )
141 if( ! strcmp( m_aNPWrapStreams[ nFileID ]->url, pUrl ) )
143 aRet =
144 NPN_DestroyStream( instance, m_aNPWrapStreams[ nFileID ],
145 *pReason );
146 m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
148 else
149 SAL_WARN(
150 "extensions.plugin",
151 "StreamID " << nFileID << " has incoherent urls "
152 << pUrl << " and "
153 << m_aNPWrapStreams[nFileID]->url);
155 else
156 SAL_WARN(
157 "extensions.plugin",
158 "nonexistent StreamID " << nFileID);
160 Respond( pMessage->m_nID,
161 (char*)(&aRet), sizeof( NPError ), NULL );
163 delete [] pUrl;
164 delete [] pReason;
166 break;
167 case eNPN_NewStream:
169 sal_uInt32 nInstance = pMessage->GetUINT32();
170 NPP instance = m_aInstances[ nInstance ]->instance;
171 NPMIMEType pType = pMessage->GetString();
172 char* pTarget = pMessage->GetString();
174 NPStream* pStream = NULL;
176 NPError aRet = NPN_NewStream( instance, pType, pTarget, &pStream );
178 if( aRet != NPERR_NO_ERROR )
180 sal_uInt32 nDummy = 0;
181 Respond( pMessage->m_nID,
182 (char*)&aRet, sizeof( aRet ),
183 "", 0,
184 &nDummy, sizeof(sal_uInt32),
185 &nDummy, sizeof(sal_uInt32),
186 NULL );
188 else
190 m_aNPWrapStreams.push_back( pStream );
192 sal_uLong nLen = strlen( pStream->url );
193 Respond( pMessage->m_nID,
194 (char*)&aRet, sizeof( aRet ),
195 pStream->url, nLen,
196 &pStream->end, sizeof(sal_uInt32),
197 &pStream->lastmodified, sizeof(sal_uInt32),
198 NULL );
201 delete [] pTarget;
202 delete [] pType;
204 break;
205 case eNPN_PostURLNotify:
207 sal_uInt32 nInstance = pMessage->GetUINT32();
208 NPP instance = m_aInstances[ nInstance ]->instance;
209 char* pUrl = pMessage->GetString();
210 char* pTarget = pMessage->GetString();
211 sal_uInt32 nLen = pMessage->GetUINT32();
212 char* pBuf = (char*)pMessage->GetBytes();
213 NPBool* pFile = (NPBool*)pMessage->GetBytes();
214 void** pNData = (void**)pMessage->GetBytes();
215 NPError aRet =
216 NPN_PostURLNotify( instance, pUrl, pTarget, nLen, pBuf, *pFile, *pNData );
217 Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL );
218 delete [] pUrl;
219 delete [] pTarget;
220 delete [] pBuf;
221 delete [] pFile;
222 delete [] pNData;
224 break;
225 case eNPN_PostURL:
227 sal_uInt32 nInstance = pMessage->GetUINT32();
228 NPP instance = m_aInstances[ nInstance ]->instance;
229 char* pUrl = pMessage->GetString();
230 char* pWindow = pMessage->GetString();
231 sal_uInt32 nLen = pMessage->GetUINT32();
232 char* pBuf = (char*)pMessage->GetBytes();
233 NPBool* pFile = (NPBool*)pMessage->GetBytes();
234 NPError aRet =
235 NPN_PostURL( instance, pUrl, pWindow, nLen, pBuf, *pFile );
236 Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL );
237 delete [] pUrl;
238 delete [] pWindow;
239 delete [] pBuf;
240 delete [] pFile;
242 break;
243 case eNPN_RequestRead:
245 sal_uInt32 nFileID = pMessage->GetUINT32();
246 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
247 sal_uInt32 nRanges = pMessage->GetUINT32();
248 sal_uInt32* pArray = (sal_uInt32*)pMessage->GetBytes();
249 // build ranges table
250 NPByteRange* pFirst = new NPByteRange;
251 NPByteRange* pRun = pFirst;
252 for( sal_uInt32 n = 0; n < nRanges; n++ )
254 pRun->offset = pArray[ 2*n ];
255 pRun->length = pArray[ 2*n+1 ];
256 pRun->next = n < nRanges-1 ? new NPByteRange : NULL;
257 pRun = pRun->next;
259 NPError aRet = NPN_RequestRead( pStream, pFirst );
260 Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL );
261 while( pFirst )
263 pRun = pFirst->next;
264 delete pFirst;
265 pFirst = pRun;
267 delete [] pArray;
269 break;
270 case eNPN_Status:
272 sal_uInt32 nInstance = pMessage->GetUINT32();
273 NPP instance = m_aInstances[ nInstance ]->instance;
274 char* pString = pMessage->GetString();
275 NPN_Status( instance, pString );
276 delete [] pString;
278 break;
279 case eNPN_Version:
281 int major, minor, net_major, net_minor;
282 NPN_Version( &major, &minor, &net_major, &net_minor );
283 Respond( pMessage->m_nID,
284 (char*)&major, sizeof( int ),
285 &minor, sizeof( int ),
286 &net_major, sizeof( int ),
287 &net_minor, sizeof( int ),
288 NULL );
290 break;
291 case eNPN_Write:
293 sal_uInt32 nInstance = pMessage->GetUINT32();
294 NPP instance = m_aInstances[ nInstance ]->instance;
295 sal_uInt32 nFileID = pMessage->GetUINT32();
296 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
297 sal_Int32 nLen = pMessage->GetUINT32();
298 void* pBuffer = pMessage->GetBytes();
299 sal_Int32 nRet = NPN_Write( instance, pStream, nLen, pBuffer );
300 Respond( pMessage->m_nID,
301 (char*)&nRet, sizeof( nRet ),
302 NULL );
303 delete [] (char*)pBuffer;
304 delete instance;
306 break;
307 case eNPN_UserAgent:
309 sal_uInt32 nInstance = pMessage->GetUINT32();
310 NPP instance = m_aInstances[ nInstance ]->instance;
311 const char* pAnswer = NPN_UserAgent( instance );
312 Respond( pMessage->m_nID,
313 (char*)pAnswer, strlen( pAnswer ),
314 NULL );
316 break;
317 default:
318 SAL_WARN(
319 "extensions.plugin",
320 "caught unknown NPN request " << +nCommand);
323 delete pMessage;
325 return 0;
328 #define GET_INSTANCE() \
329 sal_uInt32 nInstance; \
330 nInstance = GetNPPID( instance );
332 #define GET_INSTANCE_RET( err ) \
333 GET_INSTANCE() \
334 if( nInstance == PluginConnector::UnknownNPPID ) \
335 return err
338 #define POST_INSTANCE() (char*)&nInstance, sizeof( nInstance )
340 NPError UnxPluginComm::NPP_Destroy( NPP instance, NPSavedData** save )
342 NPError aRet = NPERR_GENERIC_ERROR;
343 GET_INSTANCE_RET( aRet );
344 MediatorMessage* pMes =
345 Transact( eNPP_Destroy,
346 POST_INSTANCE(),
347 NULL );
348 if( ! pMes )
349 return NPERR_GENERIC_ERROR;
350 delete pMes;
352 pMes = Transact( eNPP_DestroyPhase2,
353 POST_INSTANCE(),
354 NULL );
355 if( ! pMes )
356 return NPERR_GENERIC_ERROR;
358 aRet = GetNPError( pMes );
359 sal_uLong nSaveBytes;
360 void* pSaveData = pMes->GetBytes( nSaveBytes );
361 if( nSaveBytes == 4 && *(sal_uInt32*)pSaveData == 0 )
362 *save = NULL;
363 else
365 *save = new NPSavedData;
366 (*save)->len = nSaveBytes;
367 (*save)->buf = pSaveData;
369 delete pMes;
371 return aRet;
374 NPError UnxPluginComm::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason )
376 NPError aRet = NPERR_GENERIC_ERROR;
377 GET_INSTANCE_RET( aRet );
378 sal_uInt32 nFileID = GetStreamID( stream );
379 if( nFileID == PluginConnector::UnknownStreamID )
380 return NPERR_GENERIC_ERROR;
382 MediatorMessage* pMes =
383 Transact( eNPP_DestroyStream,
384 POST_INSTANCE(),
385 &nFileID, sizeof( nFileID ),
386 &reason, sizeof( reason ),
387 NULL );
388 m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
389 if( ! pMes )
390 return NPERR_GENERIC_ERROR;
392 aRet = GetNPError( pMes );
393 delete pMes;
394 return aRet;
397 void* UnxPluginComm::NPP_GetJavaClass()
399 return NULL;
402 NPError UnxPluginComm::NPP_Initialize()
404 MediatorMessage* pMes =
405 Transact( eNPP_Initialize,
406 NULL );
407 if( ! pMes )
408 return NPERR_GENERIC_ERROR;
410 NPError aRet = GetNPError( pMes );
411 delete pMes;
412 return aRet;
415 NPError UnxPluginComm::NPP_New( NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc,
416 char* argn[], char* argv[], NPSavedData *saved )
418 m_aInstances.push_back(
419 new ConnectorInstance( instance, pluginType, 0,
420 NULL, 0, NULL, 0,
421 saved ? (char*)saved->buf : NULL,
422 saved ? saved->len : 0 ) );
424 char *pArgnBuf, *pArgvBuf;
425 size_t nArgnLen = 0, nArgvLen = 0;
426 int i;
427 for( i = 0; i < argc; i++ )
429 nArgnLen += strlen( argn[i] ) +1;
430 nArgvLen += strlen( argv[i] ) +1;
432 pArgnBuf = new char[ nArgnLen ];
433 pArgvBuf = new char[ nArgvLen ];
434 char* pRunArgn = pArgnBuf;
435 char* pRunArgv = pArgvBuf;
436 for( i = 0; i < argc; i++ )
438 strcpy( pRunArgn, argn[i] );
439 strcpy( pRunArgv, argv[i] );
440 pRunArgn += strlen( argn[i] ) +1;
441 pRunArgv += strlen( argv[i] ) +1;
444 MediatorMessage* pMes;
445 if( saved )
446 pMes =
447 Transact( eNPP_New,
448 pluginType, strlen( pluginType ),
449 &mode, sizeof( mode ),
450 &argc, sizeof( argc ),
451 pArgnBuf, nArgnLen,
452 pArgvBuf, nArgvLen,
453 saved->buf, static_cast<size_t>(saved->len),
454 NULL );
455 else
456 pMes =
457 Transact( eNPP_New,
458 pluginType, strlen( pluginType ),
459 &mode, sizeof( mode ),
460 &argc, sizeof( argc ),
461 pArgnBuf, nArgnLen,
462 pArgvBuf, nArgvLen,
463 "0000", size_t(4),
464 NULL );
465 delete [] pArgnBuf;
466 delete [] pArgvBuf;
467 if( ! pMes )
468 return NPERR_GENERIC_ERROR;
470 NPError aRet = GetNPError( pMes );
471 delete pMes;
473 return aRet;
476 NPError UnxPluginComm::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream,
477 NPBool seekable, uint16_t* stype )
479 NPError aRet = NPERR_GENERIC_ERROR;
480 GET_INSTANCE_RET( aRet );
482 m_aNPWrapStreams.push_back( stream );
483 MediatorMessage* pMes =
484 Transact( eNPP_NewStream,
485 POST_INSTANCE(),
486 type, strlen( type ),
487 stream->url, strlen( stream->url ),
488 &stream->end, sizeof( stream->end ),
489 &stream->lastmodified, sizeof( stream->lastmodified ),
490 &seekable, sizeof( seekable ),
491 NULL );
493 if( ! pMes )
494 return NPERR_GENERIC_ERROR;
496 aRet = GetNPError( pMes );
497 uint16_t* pSType = (uint16_t*)pMes->GetBytes();
498 *stype = *pSType;
500 delete [] pSType;
501 delete pMes;
502 return aRet;
505 void UnxPluginComm::NPP_Print( NPP /*instance*/, NPPrint* /*platformPrint*/ )
509 NPError UnxPluginComm::NPP_SetWindow( NPP instance, NPWindow* window )
511 NPError aRet = NPERR_GENERIC_ERROR;
512 GET_INSTANCE_RET( aRet );
514 MediatorMessage* pMes =
515 Transact( eNPP_SetWindow,
516 POST_INSTANCE(),
517 window, sizeof( NPWindow ),
518 NULL );
519 if( ! pMes )
520 return NPERR_GENERIC_ERROR;
522 aRet = GetNPError( pMes );
523 delete pMes;
524 return aRet;
527 void UnxPluginComm::NPP_Shutdown()
529 Send( eNPP_Shutdown, NULL );
532 void UnxPluginComm::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname )
534 GET_INSTANCE();
535 sal_uInt32 nFileID = GetStreamID( stream );
536 if( nFileID == PluginConnector::UnknownStreamID )
537 return;
539 Send( eNPP_StreamAsFile,
540 POST_INSTANCE(),
541 &nFileID, sizeof( nFileID ),
542 fname, strlen( fname ),
543 NULL );
546 void UnxPluginComm::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData )
548 GET_INSTANCE();
550 Send( eNPP_URLNotify,
551 POST_INSTANCE(),
552 url, strlen( url ),
553 &reason, sizeof( reason ),
554 &notifyData, sizeof( void* ),
555 NULL );
558 int32_t UnxPluginComm::NPP_Write( NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer )
560 GET_INSTANCE_RET( -1 );
561 sal_uInt32 nFileID = GetStreamID( stream );
562 if( nFileID == PluginConnector::UnknownStreamID )
563 return -1;
565 MediatorMessage* pMes =
566 Transact( eNPP_Write,
567 POST_INSTANCE(),
568 &nFileID, sizeof( nFileID ),
569 &offset, sizeof( offset ),
570 buffer, static_cast<size_t>(len),
571 NULL );
572 if( ! pMes )
573 return 0;
575 int32_t aRet = pMes->GetUINT32();
576 delete pMes;
578 return aRet;
581 int32_t UnxPluginComm::NPP_WriteReady( NPP instance, NPStream* stream )
583 GET_INSTANCE_RET( -1 );
584 sal_uInt32 nFileID = GetStreamID( stream );
585 if( nFileID == PluginConnector::UnknownStreamID )
586 return -1;
588 MediatorMessage* pMes =
589 Transact( eNPP_WriteReady,
590 POST_INSTANCE(),
591 &nFileID, sizeof( nFileID ),
592 NULL );
594 if( ! pMes )
595 return 0;
597 int32_t aRet = pMes->GetUINT32();
598 delete pMes;
600 return aRet;
603 char* UnxPluginComm::NPP_GetMIMEDescription()
605 static char* pDesc = NULL;
606 MediatorMessage* pMes =
607 Transact( eNPP_GetMIMEDescription,
608 NULL );
609 if( ! pMes )
610 return (char*)"";
612 if( pDesc )
613 delete [] pDesc;
614 pDesc = pMes->GetString();
615 delete pMes;
616 return pDesc;
619 NPError UnxPluginComm::NPP_GetValue( NPP /*instance*/, NPPVariable /*variable*/, void* /*value*/ )
621 return 0;
624 NPError UnxPluginComm::NPP_SetValue( NPP /*instance*/, NPNVariable /*variable*/, void* /*value*/ )
626 return 0;
629 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */