merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / plugin / unx / nppapi.cxx
blob5e5c2dba1cf56f2f0404b1aef415d6955c4faf8c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #if STLPORT_VERSION>=321
32 #include <cstdarg>
33 #endif
35 #include <plugin/impl.hxx>
36 #include <vcl/svapp.hxx>
38 std::vector<PluginConnector*> PluginConnector::allConnectors;
40 PluginConnector::PluginConnector( int nSocket ) :
41 Mediator( nSocket )
43 allConnectors.push_back( this );
44 SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) );
47 PluginConnector::~PluginConnector()
49 NAMESPACE_VOS(OGuard) aGuard( m_aUserEventMutex );
50 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
51 it != allConnectors.end(); ++it )
53 if( *it == this )
55 allConnectors.erase( it );
56 break;
61 IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, /*pMediator*/ )
63 NAMESPACE_VOS(OGuard) aGuard( m_aUserEventMutex );
64 bool bFound = false;
65 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
66 it != allConnectors.end() && bFound == false; ++it )
68 if( *it == this )
69 bFound = true;
71 if( ! bFound )
72 return 0;
73 Application::PostUserEvent( LINK( this, PluginConnector, WorkOnNewMessageHdl ) );
74 return 0;
77 IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ )
79 bool bFound = false;
80 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
81 it != allConnectors.end() && bFound == false; ++it )
83 if( *it == this )
84 bFound = true;
86 if( ! bFound )
87 return 0;
90 NAMESPACE_VOS(OGuard) aGuard( m_aUserEventMutex );
91 m_aUserEventIDs.pop_front();
95 MediatorMessage* pMessage;
96 CommandAtoms nCommand;
97 while( (pMessage = GetNextMessage( FALSE )) )
99 nCommand = (CommandAtoms)pMessage->GetUINT32();
100 medDebug( 1, "%s\n", GetCommandName( nCommand ) );
101 switch( nCommand )
103 case eNPN_GetURL:
105 UINT32 nInstance = pMessage->GetUINT32();
106 NPP instance = m_aInstances[ nInstance ]->instance;
107 char* pUrl = pMessage->GetString();
108 char* pWindow = pMessage->GetString();
109 NPError aRet = NPN_GetURL( instance, pUrl, pWindow );
110 Respond( pMessage->m_nID,
111 (char*)(&aRet), sizeof( NPError ), NULL );
112 delete [] pUrl;
113 delete [] pWindow;
115 break;
116 case eNPN_GetURLNotify:
118 UINT32 nInstance = pMessage->GetUINT32();
119 NPP instance = m_aInstances[ nInstance ]->instance;
120 char* pUrl = pMessage->GetString();
121 char* pWindow = pMessage->GetString();
122 void** pNotifyData = (void**)pMessage->GetBytes();
123 NPError aRet = NPN_GetURLNotify( instance, pUrl, pWindow,
124 *pNotifyData );
125 Respond( pMessage->m_nID,
126 (char*)(&aRet), sizeof( NPError ), NULL );
127 delete [] pUrl;
128 delete [] pWindow;
129 delete [] pNotifyData;
131 break;
132 case eNPN_DestroyStream:
134 UINT32 nInstance = pMessage->GetUINT32();
135 NPP instance = m_aInstances[ nInstance ]->instance;
136 UINT32 nFileID = pMessage->GetUINT32();
137 char* pUrl = pMessage->GetString();
138 NPError* pReason = (NPError*)pMessage->GetBytes();
139 NPError aRet = NPERR_FILE_NOT_FOUND;
140 if( nFileID < static_cast<UINT32>(m_aNPWrapStreams.size()) )
142 if( ! strcmp( m_aNPWrapStreams[ nFileID ]->url, pUrl ) )
144 aRet =
145 NPN_DestroyStream( instance, m_aNPWrapStreams[ nFileID ],
146 *pReason );
147 m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
149 else
150 medDebug( 1, "StreamID %d has incoherent urls %s and %s\n",
151 nFileID, pUrl, m_aNPWrapStreams[ nFileID ]->url );
153 else
154 medDebug( 1, "Nonexistent StreamID %d\n", nFileID );
156 Respond( pMessage->m_nID,
157 (char*)(&aRet), sizeof( NPError ), NULL );
159 delete [] pUrl;
160 delete [] pReason;
162 break;
163 case eNPN_NewStream:
165 UINT32 nInstance = pMessage->GetUINT32();
166 NPP instance = m_aInstances[ nInstance ]->instance;
167 NPMIMEType pType = pMessage->GetString();
168 char* pTarget = pMessage->GetString();
170 NPStream* pStream = NULL;
172 NPError aRet = NPN_NewStream( instance, pType, pTarget, &pStream );
174 if( aRet != NPERR_NO_ERROR )
176 UINT32 nDummy = 0;
177 Respond( pMessage->m_nID,
178 (char*)&aRet, sizeof( aRet ),
179 "", 0,
180 &nDummy, sizeof(UINT32),
181 &nDummy, sizeof(UINT32),
182 NULL );
184 else
186 m_aNPWrapStreams.push_back( pStream );
188 ULONG nLen = strlen( pStream->url );
189 Respond( pMessage->m_nID,
190 (char*)&aRet, sizeof( aRet ),
191 pStream->url, nLen,
192 &pStream->end, sizeof(UINT32),
193 &pStream->lastmodified, sizeof(UINT32),
194 NULL );
197 delete [] pTarget;
198 delete [] pType;
200 break;
201 case eNPN_PostURLNotify:
203 UINT32 nInstance = pMessage->GetUINT32();
204 NPP instance = m_aInstances[ nInstance ]->instance;
205 char* pUrl = pMessage->GetString();
206 char* pTarget = pMessage->GetString();
207 UINT32 nLen = pMessage->GetUINT32();
208 char* pBuf = (char*)pMessage->GetBytes();
209 NPBool* pFile = (NPBool*)pMessage->GetBytes();
210 void** pNData = (void**)pMessage->GetBytes();
211 NPError aRet =
212 NPN_PostURLNotify( instance, pUrl, pTarget, nLen, pBuf, *pFile, *pNData );
213 Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL );
214 delete [] pUrl;
215 delete [] pTarget;
216 delete [] pBuf;
217 delete [] pFile;
218 delete [] pNData;
220 break;
221 case eNPN_PostURL:
223 UINT32 nInstance = pMessage->GetUINT32();
224 NPP instance = m_aInstances[ nInstance ]->instance;
225 char* pUrl = pMessage->GetString();
226 char* pWindow = pMessage->GetString();
227 UINT32 nLen = pMessage->GetUINT32();
228 char* pBuf = (char*)pMessage->GetBytes();
229 NPBool* pFile = (NPBool*)pMessage->GetBytes();
230 NPError aRet =
231 NPN_PostURL( instance, pUrl, pWindow, nLen, pBuf, *pFile );
232 Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL );
233 delete [] pUrl;
234 delete [] pWindow;
235 delete [] pBuf;
236 delete [] pFile;
238 break;
239 case eNPN_RequestRead:
241 UINT32 nFileID = pMessage->GetUINT32();
242 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
243 UINT32 nRanges = pMessage->GetUINT32();
244 UINT32* pArray = (UINT32*)pMessage->GetBytes();
245 // build ranges table
246 NPByteRange* pFirst = new NPByteRange;
247 NPByteRange* pRun = pFirst;
248 for( UINT32 n = 0; n < nRanges; n++ )
250 pRun->offset = pArray[ 2*n ];
251 pRun->length = pArray[ 2*n+1 ];
252 pRun->next = n < nRanges-1 ? new NPByteRange : NULL;
253 pRun = pRun->next;
255 NPError aRet = NPN_RequestRead( pStream, pFirst );
256 Respond( pMessage->m_nID, (char*)&aRet, sizeof( aRet ), NULL );
257 while( pFirst )
259 pRun = pFirst->next;
260 delete pFirst;
261 pFirst = pRun;
263 delete [] pArray;
265 break;
266 case eNPN_Status:
268 UINT32 nInstance = pMessage->GetUINT32();
269 NPP instance = m_aInstances[ nInstance ]->instance;
270 char* pString = pMessage->GetString();
271 NPN_Status( instance, pString );
272 delete [] pString;
274 break;
275 case eNPN_Version:
277 int major, minor, net_major, net_minor;
278 NPN_Version( &major, &minor, &net_major, &net_minor );
279 Respond( pMessage->m_nID,
280 (char*)&major, sizeof( int ),
281 &minor, sizeof( int ),
282 &net_major, sizeof( int ),
283 &net_minor, sizeof( int ),
284 NULL );
286 break;
287 case eNPN_Write:
289 UINT32 nInstance = pMessage->GetUINT32();
290 NPP instance = m_aInstances[ nInstance ]->instance;
291 UINT32 nFileID = pMessage->GetUINT32();
292 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
293 INT32 nLen = pMessage->GetUINT32();
294 void* pBuffer = pMessage->GetBytes();
295 INT32 nRet = NPN_Write( instance, pStream, nLen, pBuffer );
296 Respond( pMessage->m_nID,
297 (char*)&nRet, sizeof( nRet ),
298 NULL );
299 delete [] (char*)pBuffer;
300 delete instance;
302 break;
303 case eNPN_UserAgent:
305 UINT32 nInstance = pMessage->GetUINT32();
306 NPP instance = m_aInstances[ nInstance ]->instance;
307 const char* pAnswer = NPN_UserAgent( instance );
308 Respond( pMessage->m_nID,
309 (char*)pAnswer, strlen( pAnswer ),
310 NULL );
312 break;
313 default:
314 medDebug( 1, "caught unknown NPN request %d\n", nCommand );
317 delete pMessage;
319 return 0;
322 #define GET_INSTANCE() \
323 UINT32 nInstance; \
324 nInstance = GetNPPID( instance );
326 #define GET_INSTANCE_RET( err ) \
327 GET_INSTANCE() \
328 if( nInstance == PluginConnector::UnknownNPPID ) \
329 return err
332 #define POST_INSTANCE() (char*)&nInstance, sizeof( nInstance )
334 NPError UnxPluginComm::NPP_Destroy( NPP instance, NPSavedData** save )
336 NPError aRet = NPERR_GENERIC_ERROR;
337 GET_INSTANCE_RET( aRet );
338 MediatorMessage* pMes =
339 Transact( eNPP_Destroy,
340 POST_INSTANCE(),
341 NULL );
342 if( ! pMes )
343 return NPERR_GENERIC_ERROR;
344 delete pMes;
346 pMes = Transact( eNPP_DestroyPhase2,
347 POST_INSTANCE(),
348 NULL );
349 if( ! pMes )
350 return NPERR_GENERIC_ERROR;
352 aRet = GetNPError( pMes );
353 ULONG nSaveBytes;
354 void* pSaveData = pMes->GetBytes( nSaveBytes );
355 if( nSaveBytes == 4 && *(UINT32*)pSaveData == 0 )
356 *save = NULL;
357 else
359 *save = new NPSavedData;
360 (*save)->len = nSaveBytes;
361 (*save)->buf = pSaveData;
363 delete pMes;
365 return aRet;
368 NPError UnxPluginComm::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason )
370 NPError aRet = NPERR_GENERIC_ERROR;
371 GET_INSTANCE_RET( aRet );
372 UINT32 nFileID = GetStreamID( stream );
373 if( nFileID == PluginConnector::UnknownStreamID )
374 return NPERR_GENERIC_ERROR;
376 MediatorMessage* pMes =
377 Transact( eNPP_DestroyStream,
378 POST_INSTANCE(),
379 &nFileID, sizeof( nFileID ),
380 &reason, sizeof( reason ),
381 NULL );
382 m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
383 if( ! pMes )
384 return NPERR_GENERIC_ERROR;
386 aRet = GetNPError( pMes );
387 delete pMes;
388 return aRet;
391 void* UnxPluginComm::NPP_GetJavaClass()
393 return NULL;
396 NPError UnxPluginComm::NPP_Initialize()
398 MediatorMessage* pMes =
399 Transact( eNPP_Initialize,
400 NULL );
401 if( ! pMes )
402 return NPERR_GENERIC_ERROR;
404 NPError aRet = GetNPError( pMes );
405 delete pMes;
406 return aRet;
409 NPError UnxPluginComm::NPP_New( NPMIMEType pluginType, NPP instance, uint16 mode, int16 argc,
410 char* argn[], char* argv[], NPSavedData *saved )
412 m_aInstances.push_back(
413 new ConnectorInstance( instance, pluginType, 0,
414 NULL, 0, NULL, 0,
415 saved ? (char*)saved->buf : NULL,
416 saved ? saved->len : 0 ) );
418 char *pArgnBuf, *pArgvBuf;
419 size_t nArgnLen = 0, nArgvLen = 0;
420 int i;
421 for( i = 0; i < argc; i++ )
423 nArgnLen += strlen( argn[i] ) +1;
424 nArgvLen += strlen( argv[i] ) +1;
426 pArgnBuf = new char[ nArgnLen ];
427 pArgvBuf = new char[ nArgvLen ];
428 char* pRunArgn = pArgnBuf;
429 char* pRunArgv = pArgvBuf;
430 for( i = 0; i < argc; i++ )
432 strcpy( pRunArgn, argn[i] );
433 strcpy( pRunArgv, argv[i] );
434 pRunArgn += strlen( argn[i] ) +1;
435 pRunArgv += strlen( argv[i] ) +1;
438 MediatorMessage* pMes;
439 if( saved )
440 pMes =
441 Transact( eNPP_New,
442 pluginType, strlen( pluginType ),
443 &mode, sizeof( mode ),
444 &argc, sizeof( argc ),
445 pArgnBuf, nArgnLen,
446 pArgvBuf, nArgvLen,
447 saved->buf, static_cast<size_t>(saved->len),
448 NULL );
449 else
450 pMes =
451 Transact( eNPP_New,
452 pluginType, strlen( pluginType ),
453 &mode, sizeof( mode ),
454 &argc, sizeof( argc ),
455 pArgnBuf, nArgnLen,
456 pArgvBuf, nArgvLen,
457 "0000", size_t(4),
458 NULL );
459 delete [] pArgnBuf;
460 delete [] pArgvBuf;
461 if( ! pMes )
462 return NPERR_GENERIC_ERROR;
464 NPError aRet = GetNPError( pMes );
465 delete pMes;
467 return aRet;
470 NPError UnxPluginComm::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream,
471 NPBool seekable, uint16* stype )
473 NPError aRet = NPERR_GENERIC_ERROR;
474 GET_INSTANCE_RET( aRet );
476 m_aNPWrapStreams.push_back( stream );
477 MediatorMessage* pMes =
478 Transact( eNPP_NewStream,
479 POST_INSTANCE(),
480 type, strlen( type ),
481 stream->url, strlen( stream->url ),
482 &stream->end, sizeof( stream->end ),
483 &stream->lastmodified, sizeof( stream->lastmodified ),
484 &seekable, sizeof( seekable ),
485 NULL );
487 if( ! pMes )
488 return NPERR_GENERIC_ERROR;
490 aRet = GetNPError( pMes );
491 uint16* pSType = (uint16*)pMes->GetBytes();
492 *stype = *pSType;
494 delete [] pSType;
495 delete pMes;
496 return aRet;
499 void UnxPluginComm::NPP_Print( NPP /*instance*/, NPPrint* /*platformPrint*/ )
503 NPError UnxPluginComm::NPP_SetWindow( NPP instance, NPWindow* window )
505 NPError aRet = NPERR_GENERIC_ERROR;
506 GET_INSTANCE_RET( aRet );
508 MediatorMessage* pMes =
509 Transact( eNPP_SetWindow,
510 POST_INSTANCE(),
511 window, sizeof( NPWindow ),
512 NULL );
513 if( ! pMes )
514 return NPERR_GENERIC_ERROR;
516 aRet = GetNPError( pMes );
517 delete pMes;
518 return aRet;
521 void UnxPluginComm::NPP_Shutdown()
523 Send( eNPP_Shutdown, NULL );
526 void UnxPluginComm::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname )
528 GET_INSTANCE();
529 UINT32 nFileID = GetStreamID( stream );
530 if( nFileID == PluginConnector::UnknownStreamID )
531 return;
533 Send( eNPP_StreamAsFile,
534 POST_INSTANCE(),
535 &nFileID, sizeof( nFileID ),
536 fname, strlen( fname ),
537 NULL );
540 void UnxPluginComm::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData )
542 GET_INSTANCE();
544 Send( eNPP_URLNotify,
545 POST_INSTANCE(),
546 url, strlen( url ),
547 &reason, sizeof( reason ),
548 &notifyData, sizeof( void* ),
549 NULL );
552 int32 UnxPluginComm::NPP_Write( NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer )
554 GET_INSTANCE_RET( -1 );
555 UINT32 nFileID = GetStreamID( stream );
556 if( nFileID == PluginConnector::UnknownStreamID )
557 return -1;
559 MediatorMessage* pMes =
560 Transact( eNPP_Write,
561 POST_INSTANCE(),
562 &nFileID, sizeof( nFileID ),
563 &offset, sizeof( offset ),
564 buffer, static_cast<size_t>(len),
565 NULL );
566 if( ! pMes )
567 return 0;
569 int32 aRet = pMes->GetUINT32();
570 delete pMes;
572 return aRet;
575 int32 UnxPluginComm::NPP_WriteReady( NPP instance, NPStream* stream )
577 GET_INSTANCE_RET( -1 );
578 UINT32 nFileID = GetStreamID( stream );
579 if( nFileID == PluginConnector::UnknownStreamID )
580 return -1;
582 MediatorMessage* pMes =
583 Transact( eNPP_WriteReady,
584 POST_INSTANCE(),
585 &nFileID, sizeof( nFileID ),
586 NULL );
588 if( ! pMes )
589 return 0;
591 int32 aRet = pMes->GetUINT32();
592 delete pMes;
594 return aRet;
597 char* UnxPluginComm::NPP_GetMIMEDescription()
599 static char* pDesc = NULL;
600 MediatorMessage* pMes =
601 Transact( eNPP_GetMIMEDescription,
602 NULL );
603 if( ! pMes )
604 return (char*)"";
606 if( pDesc )
607 delete [] pDesc;
608 pDesc = pMes->GetString();
609 delete pMes;
610 return pDesc;
613 NPError UnxPluginComm::NPP_GetValue( NPP /*instance*/, NPPVariable /*variable*/, void* /*value*/ )
615 return 0;
618 NPError UnxPluginComm::NPP_SetValue( NPP /*instance*/, NPNVariable /*variable*/, void* /*value*/ )
620 return 0;