bump product version to 5.0.4.1
[LibreOffice.git] / extensions / source / plugin / unx / nppapi.cxx
blob9fbf3d3afd66af50d2ed5f3bc6dd8747810ece85
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 <sal/log.hxx>
39 #include <vcl/svapp.hxx>
41 #include <plugin/unx/plugcon.hxx>
42 #include <plugin/impl.hxx>
44 std::vector<PluginConnector*> PluginConnector::allConnectors;
46 PluginConnector::PluginConnector( int nSocket ) :
47 Mediator( nSocket )
49 allConnectors.push_back( this );
50 SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) );
53 PluginConnector::~PluginConnector()
55 osl::MutexGuard aGuard( m_aUserEventMutex );
56 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
57 it != allConnectors.end(); ++it )
59 if( *it == this )
61 allConnectors.erase( it );
62 break;
67 IMPL_LINK( PluginConnector, NewMessageHdl, Mediator*, /*pMediator*/ )
69 osl::MutexGuard aGuard( m_aUserEventMutex );
70 bool bFound = false;
71 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
72 it != allConnectors.end() && !bFound; ++it )
74 if( *it == this )
75 bFound = true;
77 if( ! bFound )
78 return 0;
79 Application::PostUserEvent( LINK( this, PluginConnector, WorkOnNewMessageHdl ) );
80 return 0;
83 IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ )
85 bool bFound = false;
86 for( std::vector< PluginConnector* >::iterator it = allConnectors.begin();
87 it != allConnectors.end() && !bFound; ++it )
89 if( *it == this )
90 bFound = true;
92 if( ! bFound )
93 return 0;
95 MediatorMessage* pMessage;
96 CommandAtoms nCommand;
97 while( (pMessage = GetNextMessage( false )) )
99 nCommand = (CommandAtoms)pMessage->GetUINT32();
100 SAL_INFO("extensions.plugin", GetCommandName(nCommand));
101 switch( nCommand )
103 case eNPN_GetURL:
105 sal_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 reinterpret_cast<char*>(&aRet), sizeof( NPError ), NULL );
112 delete [] pUrl;
113 delete [] pWindow;
115 break;
116 case eNPN_GetURLNotify:
118 sal_uInt32 nInstance = pMessage->GetUINT32();
119 NPP instance = m_aInstances[ nInstance ]->instance;
120 char* pUrl = pMessage->GetString();
121 char* pWindow = pMessage->GetString();
122 void** pNotifyData = static_cast<void**>(pMessage->GetBytes());
123 NPError aRet = NPN_GetURLNotify( instance, pUrl, pWindow,
124 *pNotifyData );
125 Respond( pMessage->m_nID,
126 reinterpret_cast<char*>(&aRet), sizeof( NPError ), NULL );
127 delete [] pUrl;
128 delete [] pWindow;
129 delete [] pNotifyData;
131 break;
132 case eNPN_DestroyStream:
134 sal_uInt32 nInstance = pMessage->GetUINT32();
135 NPP instance = m_aInstances[ nInstance ]->instance;
136 sal_uInt32 nFileID = pMessage->GetUINT32();
137 char* pUrl = pMessage->GetString();
138 NPError* pReason = static_cast<NPError*>(pMessage->GetBytes());
139 NPError aRet = NPERR_FILE_NOT_FOUND;
140 if( nFileID < static_cast<sal_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 SAL_WARN(
151 "extensions.plugin",
152 "StreamID " << nFileID << " has incoherent urls "
153 << pUrl << " and "
154 << m_aNPWrapStreams[nFileID]->url);
156 else
157 SAL_WARN(
158 "extensions.plugin",
159 "nonexistent StreamID " << nFileID);
161 Respond( pMessage->m_nID,
162 reinterpret_cast<char*>(&aRet), sizeof( NPError ), NULL );
164 delete [] pUrl;
165 delete [] pReason;
167 break;
168 case eNPN_NewStream:
170 sal_uInt32 nInstance = pMessage->GetUINT32();
171 NPP instance = m_aInstances[ nInstance ]->instance;
172 NPMIMEType pType = pMessage->GetString();
173 char* pTarget = pMessage->GetString();
175 NPStream* pStream = NULL;
177 NPError aRet = NPN_NewStream( instance, pType, pTarget, &pStream );
179 if( aRet != NPERR_NO_ERROR )
181 sal_uInt32 nDummy = 0;
182 Respond( pMessage->m_nID,
183 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
184 "", 0,
185 &nDummy, sizeof(sal_uInt32),
186 &nDummy, sizeof(sal_uInt32),
187 NULL );
189 else
191 m_aNPWrapStreams.push_back( pStream );
193 sal_uLong nLen = strlen( pStream->url );
194 Respond( pMessage->m_nID,
195 reinterpret_cast<char*>(&aRet), sizeof( aRet ),
196 pStream->url, nLen,
197 &pStream->end, sizeof(sal_uInt32),
198 &pStream->lastmodified, sizeof(sal_uInt32),
199 NULL );
202 delete [] pTarget;
203 delete [] pType;
205 break;
206 case eNPN_PostURLNotify:
208 sal_uInt32 nInstance = pMessage->GetUINT32();
209 NPP instance = m_aInstances[ nInstance ]->instance;
210 char* pUrl = pMessage->GetString();
211 char* pTarget = pMessage->GetString();
212 sal_uInt32 nLen = pMessage->GetUINT32();
213 char* pBuf = static_cast<char*>(pMessage->GetBytes());
214 NPBool* pFile = static_cast<NPBool*>(pMessage->GetBytes());
215 void** pNData = static_cast<void**>(pMessage->GetBytes());
216 NPError aRet =
217 NPN_PostURLNotify( instance, pUrl, pTarget, nLen, pBuf, *pFile, *pNData );
218 Respond( pMessage->m_nID, reinterpret_cast<char*>(&aRet), sizeof( aRet ), NULL );
219 delete [] pUrl;
220 delete [] pTarget;
221 delete [] pBuf;
222 delete [] pFile;
223 delete [] pNData;
225 break;
226 case eNPN_PostURL:
228 sal_uInt32 nInstance = pMessage->GetUINT32();
229 NPP instance = m_aInstances[ nInstance ]->instance;
230 char* pUrl = pMessage->GetString();
231 char* pWindow = pMessage->GetString();
232 sal_uInt32 nLen = pMessage->GetUINT32();
233 char* pBuf = static_cast<char*>(pMessage->GetBytes());
234 NPBool* pFile = static_cast<NPBool*>(pMessage->GetBytes());
235 NPError aRet =
236 NPN_PostURL( instance, pUrl, pWindow, nLen, pBuf, *pFile );
237 Respond( pMessage->m_nID, reinterpret_cast<char*>(&aRet), sizeof( aRet ), NULL );
238 delete [] pUrl;
239 delete [] pWindow;
240 delete [] pBuf;
241 delete [] pFile;
243 break;
244 case eNPN_RequestRead:
246 sal_uInt32 nFileID = pMessage->GetUINT32();
247 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
248 sal_uInt32 nRanges = pMessage->GetUINT32();
249 sal_uInt32* pArray = static_cast<sal_uInt32*>(pMessage->GetBytes());
250 // build ranges table
251 NPByteRange* pFirst = new NPByteRange;
252 NPByteRange* pRun = pFirst;
253 for( sal_uInt32 n = 0; n < nRanges; n++ )
255 pRun->offset = pArray[ 2*n ];
256 pRun->length = pArray[ 2*n+1 ];
257 pRun->next = n < nRanges-1 ? new NPByteRange : NULL;
258 pRun = pRun->next;
260 NPError aRet = NPN_RequestRead( pStream, pFirst );
261 Respond( pMessage->m_nID, reinterpret_cast<char*>(&aRet), sizeof( aRet ), NULL );
262 while( pFirst )
264 pRun = pFirst->next;
265 delete pFirst;
266 pFirst = pRun;
268 delete [] pArray;
270 break;
271 case eNPN_Status:
273 sal_uInt32 nInstance = pMessage->GetUINT32();
274 NPP instance = m_aInstances[ nInstance ]->instance;
275 char* pString = pMessage->GetString();
276 NPN_Status( instance, pString );
277 delete [] pString;
279 break;
280 case eNPN_Version:
282 int major, minor, net_major, net_minor;
283 NPN_Version( &major, &minor, &net_major, &net_minor );
284 Respond( pMessage->m_nID,
285 reinterpret_cast<char*>(&major), sizeof( int ),
286 &minor, sizeof( int ),
287 &net_major, sizeof( int ),
288 &net_minor, sizeof( int ),
289 NULL );
291 break;
292 case eNPN_Write:
294 sal_uInt32 nInstance = pMessage->GetUINT32();
295 NPP instance = m_aInstances[ nInstance ]->instance;
296 sal_uInt32 nFileID = pMessage->GetUINT32();
297 NPStream* pStream = m_aNPWrapStreams[ nFileID ];
298 sal_Int32 nLen = pMessage->GetUINT32();
299 void* pBuffer = pMessage->GetBytes();
300 sal_Int32 nRet = NPN_Write( instance, pStream, nLen, pBuffer );
301 Respond( pMessage->m_nID,
302 reinterpret_cast<char*>(&nRet), sizeof( nRet ),
303 NULL );
304 delete [] static_cast<char*>(pBuffer);
305 delete instance;
307 break;
308 case eNPN_UserAgent:
310 sal_uInt32 nInstance = pMessage->GetUINT32();
311 NPP instance = m_aInstances[ nInstance ]->instance;
312 const char* pAnswer = NPN_UserAgent( instance );
313 Respond( pMessage->m_nID,
314 const_cast<char*>(pAnswer), strlen( pAnswer ),
315 NULL );
317 break;
318 default:
319 SAL_WARN(
320 "extensions.plugin",
321 "caught unknown NPN request " << +nCommand);
324 delete pMessage;
326 return 0;
329 #define GET_INSTANCE() \
330 sal_uInt32 nInstance; \
331 nInstance = GetNPPID( instance );
333 #define GET_INSTANCE_RET( err ) \
334 GET_INSTANCE() \
335 if( nInstance == PluginConnector::UnknownNPPID ) \
336 return err
339 #define POST_INSTANCE() reinterpret_cast<char*>(&nInstance), sizeof( nInstance )
341 NPError UnxPluginComm::NPP_Destroy( NPP instance, NPSavedData** save )
343 NPError aRet = NPERR_GENERIC_ERROR;
344 GET_INSTANCE_RET( aRet );
345 MediatorMessage* pMes =
346 Transact( eNPP_Destroy,
347 POST_INSTANCE(),
348 NULL );
349 if( ! pMes )
350 return NPERR_GENERIC_ERROR;
351 delete pMes;
353 pMes = Transact( eNPP_DestroyPhase2,
354 POST_INSTANCE(),
355 NULL );
356 if( ! pMes )
357 return NPERR_GENERIC_ERROR;
359 aRet = GetNPError( pMes );
360 sal_uLong nSaveBytes;
361 void* pSaveData = pMes->GetBytes( nSaveBytes );
362 if( nSaveBytes == 4 && *static_cast<sal_uInt32*>(pSaveData) == 0 )
363 *save = NULL;
364 else
366 *save = new NPSavedData;
367 (*save)->len = nSaveBytes;
368 (*save)->buf = pSaveData;
370 delete pMes;
372 return aRet;
375 NPError UnxPluginComm::NPP_DestroyStream( NPP instance, NPStream* stream, NPError reason )
377 NPError aRet = NPERR_GENERIC_ERROR;
378 GET_INSTANCE_RET( aRet );
379 sal_uInt32 nFileID = GetStreamID( stream );
380 if( nFileID == PluginConnector::UnknownStreamID )
381 return NPERR_GENERIC_ERROR;
383 MediatorMessage* pMes =
384 Transact( eNPP_DestroyStream,
385 POST_INSTANCE(),
386 &nFileID, sizeof( nFileID ),
387 &reason, sizeof( reason ),
388 NULL );
389 m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
390 if( ! pMes )
391 return NPERR_GENERIC_ERROR;
393 aRet = GetNPError( pMes );
394 delete pMes;
395 return aRet;
398 void* UnxPluginComm::NPP_GetJavaClass()
400 return NULL;
403 NPError UnxPluginComm::NPP_Initialize()
405 MediatorMessage* pMes =
406 Transact( eNPP_Initialize,
407 NULL );
408 if( ! pMes )
409 return NPERR_GENERIC_ERROR;
411 NPError aRet = GetNPError( pMes );
412 delete pMes;
413 return aRet;
416 NPError UnxPluginComm::NPP_New( NPMIMEType pluginType, NPP instance, uint16_t mode, int16_t argc,
417 char* argn[], char* argv[], NPSavedData *saved )
419 m_aInstances.push_back(
420 new ConnectorInstance( instance, pluginType, 0,
421 NULL, 0, NULL, 0,
422 saved ? static_cast<char*>(saved->buf) : NULL,
423 saved ? saved->len : 0 ) );
425 char *pArgnBuf, *pArgvBuf;
426 size_t nArgnLen = 0, nArgvLen = 0;
427 int i;
428 for( i = 0; i < argc; i++ )
430 nArgnLen += strlen( argn[i] ) +1;
431 nArgvLen += strlen( argv[i] ) +1;
433 pArgnBuf = new char[ nArgnLen ];
434 pArgvBuf = new char[ nArgvLen ];
435 char* pRunArgn = pArgnBuf;
436 char* pRunArgv = pArgvBuf;
437 for( i = 0; i < argc; i++ )
439 strcpy( pRunArgn, argn[i] );
440 strcpy( pRunArgv, argv[i] );
441 pRunArgn += strlen( argn[i] ) +1;
442 pRunArgv += strlen( argv[i] ) +1;
445 MediatorMessage* pMes;
446 if( saved )
447 pMes =
448 Transact( eNPP_New,
449 pluginType, strlen( pluginType ),
450 &mode, sizeof( mode ),
451 &argc, sizeof( argc ),
452 pArgnBuf, nArgnLen,
453 pArgvBuf, nArgvLen,
454 saved->buf, static_cast<size_t>(saved->len),
455 NULL );
456 else
457 pMes =
458 Transact( eNPP_New,
459 pluginType, strlen( pluginType ),
460 &mode, sizeof( mode ),
461 &argc, sizeof( argc ),
462 pArgnBuf, nArgnLen,
463 pArgvBuf, nArgvLen,
464 "0000", size_t(4),
465 NULL );
466 delete [] pArgnBuf;
467 delete [] pArgvBuf;
468 if( ! pMes )
469 return NPERR_GENERIC_ERROR;
471 NPError aRet = GetNPError( pMes );
472 delete pMes;
474 return aRet;
477 NPError UnxPluginComm::NPP_NewStream( NPP instance, NPMIMEType type, NPStream* stream,
478 NPBool seekable, uint16_t* stype )
480 NPError aRet = NPERR_GENERIC_ERROR;
481 GET_INSTANCE_RET( aRet );
483 m_aNPWrapStreams.push_back( stream );
484 MediatorMessage* pMes =
485 Transact( eNPP_NewStream,
486 POST_INSTANCE(),
487 type, strlen( type ),
488 stream->url, strlen( stream->url ),
489 &stream->end, sizeof( stream->end ),
490 &stream->lastmodified, sizeof( stream->lastmodified ),
491 &seekable, sizeof( seekable ),
492 NULL );
494 if( ! pMes )
495 return NPERR_GENERIC_ERROR;
497 aRet = GetNPError( pMes );
498 uint16_t* pSType = static_cast<uint16_t*>(pMes->GetBytes());
499 *stype = *pSType;
501 delete [] pSType;
502 delete pMes;
503 return aRet;
506 void UnxPluginComm::NPP_Print( NPP /*instance*/, NPPrint* /*platformPrint*/ )
510 NPError UnxPluginComm::NPP_SetWindow( NPP instance, NPWindow* window )
512 NPError aRet = NPERR_GENERIC_ERROR;
513 GET_INSTANCE_RET( aRet );
515 MediatorMessage* pMes =
516 Transact( eNPP_SetWindow,
517 POST_INSTANCE(),
518 window, sizeof( NPWindow ),
519 NULL );
520 if( ! pMes )
521 return NPERR_GENERIC_ERROR;
523 aRet = GetNPError( pMes );
524 delete pMes;
525 return aRet;
528 void UnxPluginComm::NPP_Shutdown()
530 Send( eNPP_Shutdown, NULL );
533 void UnxPluginComm::NPP_StreamAsFile( NPP instance, NPStream* stream, const char* fname )
535 GET_INSTANCE();
536 sal_uInt32 nFileID = GetStreamID( stream );
537 if( nFileID == PluginConnector::UnknownStreamID )
538 return;
540 Send( eNPP_StreamAsFile,
541 POST_INSTANCE(),
542 &nFileID, sizeof( nFileID ),
543 fname, strlen( fname ),
544 NULL );
547 void UnxPluginComm::NPP_URLNotify( NPP instance, const char* url, NPReason reason, void* notifyData )
549 GET_INSTANCE();
551 Send( eNPP_URLNotify,
552 POST_INSTANCE(),
553 url, strlen( url ),
554 &reason, sizeof( reason ),
555 &notifyData, sizeof( void* ),
556 NULL );
559 int32_t UnxPluginComm::NPP_Write( NPP instance, NPStream* stream, int32_t offset, int32_t len, void* buffer )
561 GET_INSTANCE_RET( -1 );
562 sal_uInt32 nFileID = GetStreamID( stream );
563 if( nFileID == PluginConnector::UnknownStreamID )
564 return -1;
566 MediatorMessage* pMes =
567 Transact( eNPP_Write,
568 POST_INSTANCE(),
569 &nFileID, sizeof( nFileID ),
570 &offset, sizeof( offset ),
571 buffer, static_cast<size_t>(len),
572 NULL );
573 if( ! pMes )
574 return 0;
576 int32_t aRet = pMes->GetUINT32();
577 delete pMes;
579 return aRet;
582 int32_t UnxPluginComm::NPP_WriteReady( NPP instance, NPStream* stream )
584 GET_INSTANCE_RET( -1 );
585 sal_uInt32 nFileID = GetStreamID( stream );
586 if( nFileID == PluginConnector::UnknownStreamID )
587 return -1;
589 MediatorMessage* pMes =
590 Transact( eNPP_WriteReady,
591 POST_INSTANCE(),
592 &nFileID, sizeof( nFileID ),
593 NULL );
595 if( ! pMes )
596 return 0;
598 int32_t aRet = pMes->GetUINT32();
599 delete pMes;
601 return aRet;
604 NPError UnxPluginComm::NPP_GetValue( NPP /*instance*/, NPPVariable /*variable*/, void* /*value*/ )
606 return 0;
609 NPError UnxPluginComm::NPP_SetValue( NPP /*instance*/, NPNVariable /*variable*/, void* /*value*/ )
611 return 0;
614 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */