Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*************************************************************************
3 : *
4 : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : *
6 : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : *
8 : * OpenOffice.org - a multi-platform office productivity suite
9 : *
10 : * This file is part of OpenOffice.org.
11 : *
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.
15 : *
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).
21 : *
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.
26 : *
27 : ************************************************************************/
28 :
29 :
30 : #ifdef AIX
31 : #define _LINUX_SOURCE_COMPAT
32 : #include <sys/timer.h>
33 : #undef _LINUX_SOURCE_COMPAT
34 : #endif
35 :
36 : #include <plugin/unx/plugcon.hxx>
37 :
38 : #include <unistd.h>
39 : #include <dlfcn.h>
40 :
41 : #include <osl/module.h>
42 : #include <sal/log.hxx>
43 :
44 : #include <config_vclplug.h>
45 :
46 : #include <npwrap.hxx>
47 :
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;
56 :
57 : // begin Netscape plugin api calls
58 : extern "C" {
59 :
60 0 : static void* l_NPN_MemAlloc( uint32_t nBytes )
61 : {
62 0 : void* pMem = new char[nBytes];
63 0 : return pMem;
64 : }
65 :
66 0 : static void l_NPN_MemFree( void* pMem )
67 : {
68 0 : delete [] static_cast<char*>(pMem);
69 0 : }
70 :
71 0 : static uint32_t l_NPN_MemFlush( uint32_t /*nSize*/ )
72 : {
73 0 : return 0;
74 : }
75 :
76 0 : static NPError l_NPN_DestroyStream( NPP instance, NPStream* stream, NPError reason )
77 : {
78 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
79 0 : if( nInstance == PluginConnector::UnknownNPPID )
80 0 : return NPERR_GENERIC_ERROR;
81 :
82 0 : sal_uInt32 nFileID = pConnector->GetStreamID( stream );
83 : MediatorMessage* pMes=
84 : pConnector->
85 : Transact( eNPN_DestroyStream,
86 : &nInstance, sizeof( nInstance ),
87 : &nFileID, sizeof( nFileID ),
88 0 : POST_STRING( stream->url ),
89 : &reason, sizeof( reason ),
90 0 : NULL );
91 :
92 0 : if( ! pMes )
93 0 : return NPERR_GENERIC_ERROR;
94 :
95 0 : for( std::vector< NPStream* >::iterator it = pConnector->getStreamList().begin();
96 0 : it != pConnector->getStreamList().end(); ++it )
97 : {
98 0 : if( *it == stream )
99 : {
100 0 : pConnector->getStreamList().erase( it );
101 0 : break;
102 : }
103 : }
104 0 : delete [] stream->url;
105 0 : delete stream;
106 : // returns NPError
107 0 : NPError aRet = PluginConnector::GetNPError( pMes );
108 0 : delete pMes;
109 0 : return aRet;
110 : }
111 :
112 : #ifdef OJI
113 : static JRIEnv* l_NPN_GetJavaEnv()
114 : {
115 : // no java in this program
116 : SAL_INFO("extensions.plugin", "SNI: NPN_GetJavaEnv");
117 : return NULL;
118 : }
119 :
120 : static jref l_NPN_GetJavaPeer( NPP /*instance*/ )
121 : {
122 : SAL_INFO("extensions.plugin", "SNI: NPN_GetJavaPeer");
123 : return NULL;
124 : }
125 : #endif
126 :
127 0 : static NPError l_NPN_GetURL( NPP instance, const char* url, const char* window )
128 : {
129 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
130 0 : if( nInstance == PluginConnector::UnknownNPPID )
131 0 : return NPERR_GENERIC_ERROR;
132 :
133 : MediatorMessage* pMes=
134 : pConnector->
135 : Transact( eNPN_GetURL,
136 : &nInstance, sizeof( nInstance ),
137 : POST_STRING(url),
138 : POST_STRING(window),
139 0 : NULL );
140 : SAL_WARN_IF(!pMes, "extensions.plugin", "geturl: message unanswered");
141 0 : if( ! pMes )
142 0 : return NPERR_GENERIC_ERROR;
143 :
144 : // returns NPError
145 0 : NPError aRet = PluginConnector::GetNPError( pMes );
146 : SAL_WARN_IF(aRet, "extensions.plugin", "geturl returns " << aRet);
147 0 : delete pMes;
148 0 : return aRet;
149 : }
150 :
151 0 : static NPError l_NPN_GetURLNotify( NPP instance, const char* url, const char* target,
152 : void* notifyData )
153 : {
154 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
155 0 : if( nInstance == PluginConnector::UnknownNPPID )
156 0 : return NPERR_GENERIC_ERROR;
157 :
158 : MediatorMessage* pMes=
159 : pConnector->
160 : Transact( eNPN_GetURLNotify,
161 : &nInstance, sizeof( nInstance ),
162 : POST_STRING(url),
163 : POST_STRING(target),
164 : ¬ifyData, 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 0 : NULL );
168 0 : if( ! pMes )
169 0 : return NPERR_GENERIC_ERROR;
170 :
171 : // returns NPError
172 0 : NPError aRet = PluginConnector::GetNPError( pMes );
173 0 : delete pMes;
174 0 : return aRet;
175 : }
176 :
177 0 : static NPError l_NPN_NewStream( NPP instance, NPMIMEType type, const char* target,
178 : NPStream** stream )
179 : // stream is a return value
180 : {
181 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
182 0 : if( nInstance == PluginConnector::UnknownNPPID )
183 0 : return NPERR_GENERIC_ERROR;
184 :
185 : MediatorMessage* pMes=
186 : pConnector->
187 : Transact( eNPN_NewStream,
188 : &nInstance, sizeof( nInstance ),
189 : POST_STRING(type),
190 : POST_STRING(target),
191 0 : NULL );
192 0 : if( ! pMes )
193 0 : return NPERR_GENERIC_ERROR;
194 :
195 : // returns a new NPStream and an error
196 0 : NPError aRet = PluginConnector::GetNPError( pMes );
197 0 : if( ! aRet )
198 : {
199 0 : NPStream* pStream = new NPStream;
200 0 : pStream->url = pMes->GetString();
201 0 : pStream->end = pMes->GetUINT32();
202 0 : pStream->lastmodified = pMes->GetUINT32();
203 0 : pStream->ndata = pStream->pdata = pStream->notifyData = NULL;
204 :
205 0 : pConnector->getStreamList().push_back( pStream );
206 0 : *stream = pStream;
207 : }
208 :
209 0 : delete pMes;
210 0 : return aRet;
211 : }
212 :
213 0 : static NPError l_NPN_PostURLNotify( NPP instance, const char* url, const char* target, uint32_t len, const char* buf, NPBool file, void* notifyData )
214 : {
215 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
216 0 : if( nInstance == PluginConnector::UnknownNPPID )
217 0 : return NPERR_GENERIC_ERROR;
218 :
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 : ¬ifyData, sizeof( void* ), // send the real pointer
228 0 : NULL );
229 :
230 0 : if( ! pMes )
231 0 : return NPERR_GENERIC_ERROR;
232 :
233 0 : NPError aRet = PluginConnector::GetNPError( pMes );
234 0 : delete pMes;
235 0 : return aRet;
236 : }
237 :
238 0 : static NPError l_NPN_PostURL( NPP instance, const char* url, const char* window, uint32_t len, const char* buf, NPBool file )
239 : {
240 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
241 0 : if( nInstance == PluginConnector::UnknownNPPID )
242 0 : return NPERR_GENERIC_ERROR;
243 :
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 0 : NULL );
253 0 : if( ! pMes )
254 0 : return NPERR_GENERIC_ERROR;
255 :
256 0 : NPError aRet = PluginConnector::GetNPError( pMes );
257 0 : delete pMes;
258 0 : return aRet;
259 : }
260 :
261 0 : static NPError l_NPN_RequestRead( NPStream* stream, NPByteRange* rangeList )
262 : {
263 : SAL_INFO("extensions.plugin", "pluginapp: NPN_RequestRead");
264 :
265 0 : NPByteRange* pRange = rangeList;
266 0 : sal_uInt32 nRanges = 0;
267 0 : while( pRange )
268 : {
269 0 : nRanges++;
270 0 : pRange = pRange->next;
271 : }
272 :
273 0 : sal_uInt32* pArray = new sal_uInt32[ 2 * nRanges ];
274 0 : pRange = rangeList;
275 0 : sal_uInt32 n = 0;
276 0 : while( pRange )
277 : {
278 0 : pArray[ 2*n ] = (sal_uInt32)pRange->offset;
279 0 : pArray[ 2*n + 1] = (sal_uInt32)pRange->length;
280 0 : n++;
281 0 : pRange = pRange->next;
282 : }
283 0 : 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 0 : NULL );
290 :
291 0 : if( ! pMes )
292 : {
293 0 : delete[] pArray;
294 0 : return NPERR_GENERIC_ERROR;
295 : }
296 :
297 0 : NPError aRet = PluginConnector::GetNPError( pMes );
298 0 : delete [] pArray;
299 0 : delete pMes;
300 0 : return aRet;
301 : }
302 :
303 0 : static void l_NPN_Status( NPP instance, const char* message )
304 : {
305 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
306 0 : if( nInstance == PluginConnector::UnknownNPPID )
307 0 : return;
308 :
309 : pConnector->Send( eNPN_Status,
310 : &nInstance, sizeof( nInstance ),
311 : POST_STRING( message ),
312 0 : NULL );
313 : }
314 :
315 0 : static const char* l_NPN_UserAgent( NPP instance )
316 : {
317 : static char* pAgent = NULL;
318 :
319 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
320 0 : if( nInstance == PluginConnector::UnknownNPPID )
321 : {
322 0 : if( instance )
323 0 : return "Mozilla 3.0";
324 : else // e.g. flashplayer calls NPN_UserAgent with NULL
325 0 : nInstance = 0;
326 : }
327 :
328 : MediatorMessage* pMes = pConnector->
329 : Transact( eNPN_UserAgent,
330 : &nInstance, sizeof( nInstance ),
331 0 : NULL );
332 :
333 0 : if( ! pMes )
334 0 : return pAgent;
335 :
336 0 : if( pAgent )
337 0 : delete [] pAgent;
338 0 : pAgent = pMes->GetString();
339 :
340 0 : delete pMes;
341 :
342 : SAL_INFO("extensions.plugin", "NPN_UserAgent returns " << pAgent);
343 :
344 0 : return pAgent;
345 : }
346 :
347 0 : static int32_t l_NPN_Write( NPP instance, NPStream* stream, int32_t len, void* buffer )
348 : {
349 0 : sal_uInt32 nFileID = pConnector->GetStreamID( stream );
350 0 : if( nFileID == PluginConnector::UnknownStreamID )
351 0 : return NPERR_GENERIC_ERROR;
352 0 : sal_uInt32 nInstance = pConnector->GetNPPID( instance );
353 0 : if( nInstance == PluginConnector::UnknownNPPID )
354 0 : return NPERR_GENERIC_ERROR;
355 :
356 : MediatorMessage* pMes = pConnector->
357 : Transact( eNPN_Write,
358 : &nInstance, sizeof( nInstance ),
359 : &nFileID, sizeof( nFileID ),
360 : &len, sizeof( len ),
361 : buffer, len,
362 0 : NULL );
363 :
364 0 : if( ! pMes )
365 0 : return 0;
366 :
367 0 : sal_Int32 nRet = pMes->GetUINT32();
368 0 : return nRet;
369 : }
370 :
371 0 : static void l_NPN_ReloadPlugins( NPBool /*reloadPages*/ )
372 : {
373 : SAL_INFO("extensions.plugin", "NPN_ReloadPlugins: SNI");
374 0 : }
375 :
376 0 : static NPError l_NPN_GetValue( NPP, NPNVariable variable, void* value )
377 : {
378 : /*
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
382 : */
383 0 : switch( (int)variable )
384 : {
385 : case NPNVxDisplay:
386 0 : *static_cast<Display**>(value) = pXtAppDisplay;
387 : SAL_INFO("extensions.plugin", "Display requested");
388 0 : break;
389 : case NPNVxtAppContext:
390 0 : *static_cast<XtAppContext*>(value) = app_context;
391 : SAL_INFO("extensions.plugin", "AppContext requested");
392 0 : break;
393 : case NPNVjavascriptEnabledBool:
394 : // no javascript
395 0 : *static_cast<NPBool*>(value) = false;
396 : SAL_INFO("extensions.plugin", "javascript enabled requested");
397 0 : break;
398 : case NPNVasdEnabledBool:
399 : // no SmartUpdate
400 0 : *static_cast<NPBool*>(value) = false;
401 : SAL_INFO("extensions.plugin", "smart update enabled requested");
402 0 : break;
403 : case NPNVisOfflineBool:
404 : // no offline browsing
405 0 : *static_cast<NPBool*>(value) = false;
406 : SAL_INFO("extensions.plugin", "offline browsing requested");
407 0 : break;
408 : case NPNVSupportsXEmbedBool:
409 : // asking xembed
410 0 : *static_cast<int*>(value) = int(true);
411 : SAL_INFO("extensions.plugin", "xembed requested");
412 0 : break;
413 : case NPNVToolkit:
414 : # if ENABLE_GTK
415 0 : *static_cast<int*>(value) = NPNVGtk2;
416 : # else
417 : *(int*)value = 0;
418 : # endif
419 : SAL_INFO("extensions.plugin", "toolkit requested");
420 0 : break;
421 : default:
422 : SAL_WARN(
423 : "extensions.plugin",
424 : "unknown NPNVariable " << +variable << " requested");
425 0 : return NPERR_INVALID_PARAM;
426 : }
427 0 : return NPERR_NO_ERROR;
428 : }
429 :
430 0 : static NPError l_NPN_SetValue(NPP /*instance*/, NPPVariable variable, void *value)
431 : {
432 : SAL_INFO("extensions.plugin", "NPN_SetValue " << +variable << "=" << value);
433 0 : return 0;
434 : }
435 :
436 0 : static void l_NPN_InvalidateRect(NPP /*instance*/, NPRect* /*invalidRect*/)
437 : {
438 : SAL_INFO("extensions.plugin", "NPN_InvalidateRect");
439 0 : }
440 :
441 0 : static void l_NPN_InvalidateRegion(NPP /*instance*/, NPRegion /*invalidRegion*/)
442 : {
443 : SAL_INFO("extensions.plugin", "NPN_InvalidateRegion");
444 0 : }
445 :
446 0 : static void l_NPN_ForceRedraw(NPP /*instance*/)
447 : {
448 : SAL_INFO("extensions.plugin", "NPN_ForceRedraw");
449 0 : }
450 :
451 : }
452 :
453 : static NPNetscapeFuncs aNetscapeFuncs =
454 : {
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
483 : };
484 :
485 : static NPPluginFuncs aPluginFuncs =
486 : {
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
503 : };
504 :
505 :
506 : oslModule pPluginLib = NULL;
507 : char*(*pNPP_GetMIMEDescription)() = NULL;
508 : NPError (*pNP_Initialize)(NPNetscapeFuncs*,NPPluginFuncs*) = NULL;
509 : NPError (*pNP_Shutdown)() = NULL;
510 :
511 0 : std::vector< PluginConnector* > PluginConnector::allConnectors;
512 :
513 0 : PluginConnector::PluginConnector( int nSocket ) :
514 0 : Mediator( nSocket )
515 : {
516 0 : SetNewMessageHdl( LINK( this, PluginConnector, NewMessageHdl ) );
517 0 : }
518 :
519 0 : PluginConnector::~PluginConnector()
520 : {
521 0 : }
522 :
523 0 : IMPL_LINK( PluginConnector, WorkOnNewMessageHdl, Mediator*, /*pMediator*/ )
524 : {
525 : MediatorMessage* pMessage;
526 : CommandAtoms nCommand;
527 0 : while( (pMessage = GetNextMessage( false )) )
528 : {
529 0 : nCommand = (CommandAtoms)pMessage->GetUINT32();
530 : SAL_INFO(
531 : "extensions.plugin", "pluginapp: " << GetCommandName(nCommand));
532 0 : switch( nCommand )
533 : {
534 : case eNPP_DestroyStream:
535 : {
536 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
537 0 : NPP instance = m_aInstances[ nInstance ]->instance;
538 0 : sal_uInt32 nFileID = pMessage->GetUINT32();
539 0 : NPStream* pStream = m_aNPWrapStreams[ nFileID ];
540 0 : NPError aReason = GetNPError( pMessage );
541 0 : m_aNPWrapStreams.erase( m_aNPWrapStreams.begin() + nFileID );
542 :
543 0 : aReason = aPluginFuncs.destroystream( instance, pStream, aReason );
544 : Respond( pMessage->m_nID,
545 : reinterpret_cast<char*>(&aReason), sizeof( aReason ),
546 0 : NULL );
547 :
548 0 : delete [] pStream->url;
549 0 : delete pStream;
550 : }
551 0 : break;
552 : case eNPP_Destroy:
553 : {
554 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
555 0 : ConnectorInstance* pInst= m_aInstances[ nInstance ];
556 :
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 0 : if( pInst->pShell )
561 0 : XtDestroyWidget( static_cast<Widget>(pInst->pShell) );
562 :
563 0 : pInst->pWidget = pInst->pShell = NULL;
564 :
565 : // the other side will call eNPP_DestroyPhase2 after this
566 0 : NPError aReason = NPERR_NO_ERROR;
567 0 : Respond( pMessage->m_nID, reinterpret_cast<char*>(&aReason), sizeof( aReason ), NULL );
568 : }
569 0 : break;
570 : case eNPP_DestroyPhase2:
571 : {
572 : // now really destroy the instance
573 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
574 0 : ConnectorInstance* pInst= m_aInstances[ nInstance ];
575 0 : NPP instance = pInst->instance;
576 0 : NPSavedData* pSave = NULL;
577 :
578 0 : NPError aRet = aPluginFuncs.destroy( instance, &pSave );
579 0 : if( pSave )
580 : {
581 : Respond( pMessage->m_nID,
582 : reinterpret_cast<char*>(&aRet), sizeof( aRet ),
583 : pSave->buf, pSave->len,
584 0 : NULL );
585 0 : delete [] static_cast<char*>(pSave->buf);
586 : }
587 : else
588 : Respond( pMessage->m_nID,
589 : reinterpret_cast<char*>(&aRet), sizeof( aRet ),
590 : "0000", 4,
591 0 : NULL );
592 :
593 : #if ENABLE_GTK
594 0 : if( pInst->pGtkWindow )
595 0 : g_object_unref( G_OBJECT(pInst->pGtkWindow) );
596 0 : if( pInst->pGtkWidget )
597 0 : g_object_unref( G_OBJECT(pInst->pGtkWidget) );
598 : #endif
599 :
600 0 : m_aInstances.erase( m_aInstances.begin() + nInstance );
601 0 : delete pInst;
602 0 : delete instance;
603 : SAL_INFO(
604 : "extensions.plugin",
605 : "destroyed instance (returning " << aRet << ")");
606 : }
607 0 : break;
608 : case eNPP_NewStream:
609 : {
610 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
611 0 : NPP instance = m_aInstances[ nInstance ]->instance;
612 0 : char* pType = pMessage->GetString();
613 0 : NPStream* pStream = new NPStream;
614 0 : pStream->url = pMessage->GetString();
615 0 : pStream->end = pMessage->GetUINT32();
616 0 : pStream->lastmodified = pMessage->GetUINT32();
617 0 : pStream->pdata = pStream->ndata = pStream->notifyData = NULL;
618 0 : NPBool* pSeekable = static_cast<NPBool*>(pMessage->GetBytes());
619 0 : m_aNPWrapStreams.push_back( pStream );
620 0 : uint16_t nStype = NP_ASFILE;
621 : NPError aRet = aPluginFuncs.newstream( instance, pType, pStream,
622 0 : *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 0 : NULL );
638 0 : delete [] pType;
639 0 : delete [] pSeekable;
640 : }
641 0 : break;
642 : case eNPP_New:
643 : {
644 0 : char* pType = pMessage->GetString();
645 0 : uint16_t* pMode = static_cast<uint16_t*>(pMessage->GetBytes());
646 0 : int16_t* pArgc = static_cast<int16_t*>(pMessage->GetBytes());
647 0 : NPP instance = new NPP_t;
648 0 : instance->pdata = instance->ndata = NULL;
649 : sal_uLong nArgnBytes, nArgvBytes;
650 0 : char* pArgn = static_cast<char*>(pMessage->GetBytes( nArgnBytes ));
651 0 : char* pArgv = static_cast<char*>(pMessage->GetBytes( nArgvBytes ));
652 : sal_uLong nSaveBytes;
653 0 : 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 0 : pSavedData, nSaveBytes );
660 0 : 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 0 : ( nSaveBytes == 4 && *reinterpret_cast<sal_uInt32*>(pSavedData) == 0 ) ?
666 0 : &(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 0 : for( int i = 0; i < pInst->nArg; i++ )
674 : SAL_INFO(
675 : "extensions.plugin",
676 : " \"" << pInst->argn[i] << "\"=\"" << pInst->argv[i]
677 : << "\"");
678 :
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 0 : if( aPluginFuncs.getvalue )
685 : {
686 0 : int bNeedsXEmbed = 0;
687 0 : NPError error = aPluginFuncs.getvalue( instance, NPPVpluginNeedsXEmbed, static_cast<void *>(&bNeedsXEmbed) );
688 0 : if( error == NPERR_NO_ERROR )
689 0 : pInst->bShouldUseXEmbed = (bNeedsXEmbed != 0);
690 : SAL_INFO(
691 : "extensions.plugin",
692 : "should use xembed = "
693 : << (pInst->bShouldUseXEmbed ? "true" : "false"));
694 : }
695 : #endif
696 :
697 : Respond( pMessage->m_nID,
698 : reinterpret_cast<char*>(&aRet), sizeof( aRet ),
699 0 : NULL );
700 0 : delete [] pMode;
701 0 : delete [] pArgc;
702 0 : delete [] pType;
703 : }
704 0 : break;
705 : case eNPP_SetWindow:
706 : {
707 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
708 0 : ConnectorInstance* pInst= m_aInstances[ nInstance ];
709 0 : NPWindow* pWindow = static_cast<NPWindow*>(pMessage->GetBytes());
710 :
711 0 : if( pWindow->width < 1 )
712 0 : pWindow->width = 1;
713 0 : if( pWindow->height < 1 )
714 0 : pWindow->height = 1;
715 :
716 : #if ENABLE_GTK
717 0 : if( pInst->bShouldUseXEmbed )
718 : {
719 0 : if( ! pInst->pGtkWidget )
720 : {
721 : SAL_INFO(
722 : "extensions.plugin",
723 : "creating gtk plug and socket");
724 :
725 0 : pInst->pGtkWindow = gtk_plug_new((GdkNativeWindow)reinterpret_cast<sal_uIntPtr>(pWindow->window));
726 0 : gtk_widget_show( pInst->pGtkWindow );
727 0 : pInst->pGtkWidget = gtk_socket_new();
728 0 : gtk_widget_show( pInst->pGtkWidget );
729 0 : gtk_container_add( GTK_CONTAINER(pInst->pGtkWindow), pInst->pGtkWidget );
730 0 : gtk_widget_show_all( pInst->pGtkWindow );
731 0 : pInst->window.window = reinterpret_cast<void *>(gtk_socket_get_id( GTK_SOCKET(pInst->pGtkWidget ) ));
732 :
733 0 : XSync( pAppDisplay, False );
734 :
735 0 : XMapWindow( pAppDisplay, GDK_WINDOW_XWINDOW(pInst->pGtkWindow->window) );
736 :
737 0 : XSync( pAppDisplay, False );
738 : }
739 :
740 : // update widget size; alas out parent is not yet really XEMBED conformant
741 0 : gtk_widget_set_size_request( pInst->pGtkWidget, pWindow->width, pWindow->height );
742 0 : gtk_window_resize( GTK_WINDOW(pInst->pGtkWindow), pWindow->width, pWindow->height );
743 :
744 0 : GdkScreen* pGdkScreen = gtk_widget_get_screen( pInst->pGtkWidget );
745 0 : Screen* pScreen = ScreenOfDisplay( pAppDisplay, gdk_screen_get_number( pGdkScreen ) );
746 :
747 0 : pInst->window.x = 0;
748 0 : pInst->window.y = 0;
749 0 : pInst->window.width = pWindow->width;
750 0 : pInst->window.height = pWindow->height;
751 0 : pInst->window.clipRect.left = 0;
752 0 : pInst->window.clipRect.top = 0;
753 0 : pInst->window.clipRect.right = pWindow->width;
754 0 : pInst->window.clipRect.bottom = pWindow->height;
755 0 : pInst->window.ws_info = &pInst->ws_info;
756 0 : pInst->window.type = NPWindowTypeWindow;
757 0 : pInst->ws_info.type = NP_SETWINDOW;
758 0 : pInst->ws_info.display = pAppDisplay;
759 0 : pInst->ws_info.visual = DefaultVisualOfScreen( pScreen );
760 0 : pInst->ws_info.colormap = DefaultColormapOfScreen( pScreen );
761 0 : pInst->ws_info.depth = DefaultDepthOfScreen( pScreen );
762 : }
763 : else
764 : #endif
765 : {
766 0 : if( ! pInst->pWidget )
767 : {
768 0 : pInst->pWidget = CreateNewShell( &(pInst->pShell), reinterpret_cast<Window>(pWindow->window) );
769 : }
770 :
771 : // fill in NPWindow and NPCallbackStruct
772 0 : pInst->window.window = reinterpret_cast<void*>(XtWindow( static_cast<Widget>(pInst->pWidget) ));
773 0 : pInst->window.x = 0;
774 0 : pInst->window.y = 0;
775 0 : pInst->window.width = pWindow->width;
776 0 : pInst->window.height = pWindow->height;
777 0 : pInst->window.clipRect.left = 0;
778 0 : pInst->window.clipRect.top = 0;
779 0 : pInst->window.clipRect.right = pWindow->width;
780 0 : pInst->window.clipRect.bottom = pWindow->height;
781 0 : pInst->window.ws_info = &pInst->ws_info;
782 0 : pInst->window.type = NPWindowTypeWindow;
783 0 : pInst->ws_info.type = NP_SETWINDOW;
784 0 : pInst->ws_info.display = XtDisplay( static_cast<Widget>(pInst->pWidget) );
785 0 : pInst->ws_info.visual = DefaultVisualOfScreen( XtScreen( static_cast<Widget>(pInst->pWidget) ) );
786 0 : pInst->ws_info.colormap = DefaultColormapOfScreen( XtScreen( static_cast<Widget>(pInst->pWidget) ) );
787 0 : pInst->ws_info.depth = DefaultDepthOfScreen( XtScreen( static_cast<Widget>(pInst->pWidget) ) );
788 :
789 : XtResizeWidget( static_cast<Widget>(pInst->pShell),
790 : pInst->window.width,
791 : pInst->window.height,
792 0 : 0 );
793 : XtResizeWidget( static_cast<Widget>(pInst->pWidget),
794 : pInst->window.width,
795 : pInst->window.height,
796 0 : 0 );
797 : }
798 :
799 0 : 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 0 : NULL );
806 0 : delete [] reinterpret_cast<char*>(pWindow);
807 : }
808 0 : break;
809 : case eNPP_StreamAsFile:
810 : {
811 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
812 0 : NPP instance = m_aInstances[ nInstance ]->instance;
813 0 : sal_uInt32 nFileID = pMessage->GetUINT32();
814 0 : NPStream* pStream = m_aNPWrapStreams[ nFileID ];
815 0 : char* fname = pMessage->GetString();
816 : SAL_INFO(
817 : "extensions.plugin",
818 : "pluginapp: NPP_StreamAsFile " << fname);
819 0 : aPluginFuncs.asfile( instance, pStream, fname );
820 0 : delete [] fname;
821 : }
822 0 : break;
823 : case eNPP_URLNotify:
824 : {
825 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
826 0 : NPP instance = m_aInstances[ nInstance ]->instance;
827 0 : char* url = pMessage->GetString();
828 0 : NPReason* pReason = static_cast<NPReason*>(pMessage->GetBytes());
829 0 : void** notifyData = static_cast<void**>(pMessage->GetBytes());
830 0 : aPluginFuncs.urlnotify( instance, url, *pReason, *notifyData );
831 0 : delete [] url;
832 0 : delete [] pReason;
833 0 : delete [] notifyData;
834 : }
835 0 : break;
836 : case eNPP_WriteReady:
837 : {
838 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
839 0 : NPP instance = m_aInstances[ nInstance ]->instance;
840 0 : sal_uInt32 nFileID = pMessage->GetUINT32();
841 0 : NPStream* pStream = m_aNPWrapStreams[ nFileID ];
842 0 : int32_t nRet = aPluginFuncs.writeready( instance, pStream );
843 :
844 : SAL_INFO(
845 : "extensions.plugin",
846 : "pluginapp: NPP_WriteReady(" << instance << ", " << pStream
847 : << ") (stream id = " << nFileID << ") returns "
848 : << nRet);
849 :
850 : Respond( pMessage->m_nID,
851 : reinterpret_cast<char*>(&nRet), sizeof( nRet ),
852 0 : NULL );
853 : }
854 0 : break;
855 : case eNPP_Write:
856 : {
857 0 : sal_uInt32 nInstance = pMessage->GetUINT32();
858 0 : NPP instance = m_aInstances[ nInstance ]->instance;
859 0 : sal_uInt32 nFileID = pMessage->GetUINT32();
860 0 : NPStream* pStream = m_aNPWrapStreams[ nFileID ];
861 0 : int32_t offset = pMessage->GetUINT32();
862 : sal_uLong len;
863 0 : char* buffer = static_cast<char*>(pMessage->GetBytes( len ));
864 0 : int32_t nRet = aPluginFuncs.write( instance, pStream, offset, len, buffer );
865 :
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 << " }");
876 :
877 : Respond( pMessage->m_nID,
878 : reinterpret_cast<char*>(&nRet), sizeof( nRet ),
879 0 : NULL );
880 0 : delete [] buffer;
881 : }
882 0 : break;
883 : case eNPP_GetMIMEDescription:
884 : {
885 0 : if( ! pNPP_GetMIMEDescription )
886 : pNPP_GetMIMEDescription = reinterpret_cast<char*(*)()>(
887 0 : osl_getAsciiFunctionSymbol( pPluginLib, "NPP_GetMIMEDescription" ));
888 0 : char* pMIME = pNPP_GetMIMEDescription();
889 : Respond( pMessage->m_nID,
890 : POST_NONCONST_STRING( pMIME ),
891 0 : NULL );
892 : }
893 0 : break;
894 : case eNPP_Initialize:
895 : {
896 :
897 : pNP_Initialize =
898 : reinterpret_cast<NPError(*)(NPNetscapeFuncs*, NPPluginFuncs*)>(
899 0 : 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 0 : osl_getAsciiFunctionSymbol( pPluginLib, "NP_Shutdown" ));
905 : SAL_WARN_IF(
906 : !pNP_Initialize, "extensions.plugin",
907 : "no NP_Shutdown, " << dlerror());
908 :
909 : SAL_INFO("extensions.plugin", "entering NP_Initialize");
910 0 : NPError aRet = pNP_Initialize( &aNetscapeFuncs, &aPluginFuncs );
911 : SAL_INFO(
912 : "extensions.plugin",
913 : "pluginapp: NP_Initialize returns " << aRet);
914 0 : Respond( pMessage->m_nID, reinterpret_cast<char*>(&aRet), sizeof( aRet ), NULL );
915 : }
916 0 : break;
917 : case eNPP_Shutdown:
918 : {
919 0 : bool bSuccess = (4 == write(wakeup_fd[1], "xxxx", 4));
920 : SAL_WARN_IF(!bSuccess, "extensions.plugin", "short write");
921 : }
922 0 : break;
923 : default:
924 : SAL_WARN(
925 : "extensions.plugin",
926 : "caught unknown NPP request " << +nCommand);
927 0 : break;
928 : }
929 0 : delete pMessage;
930 : }
931 0 : return 0;
932 : }
933 :
934 0 : void LoadAdditionalLibs( const char* _pPluginLib )
935 : {
936 : SAL_INFO("extensions.plugin", "LoadAdditionalLibs " << _pPluginLib);
937 :
938 0 : if( ! strncmp( _pPluginLib, "libflashplayer.so", 17 ) )
939 : {
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.
945 : */
946 0 : aNetscapeFuncs.version = 11;
947 0 : aPluginFuncs.version = 11;
948 : }
949 0 : }
950 :
951 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|