merge the formfield patch from ooo-build
[ooovba.git] / extensions / source / plugin / base / xplugin.cxx
blob0a684a076b7026b9c89e14050fcdd33a36bb9313
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xplugin.cxx,v $
10 * $Revision: 1.25 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_extensions.hxx"
33 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
34 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
35 #include <com/sun/star/loader/XImplementationLoader.hpp>
36 #include <com/sun/star/loader/CannotActivateFactoryException.hpp>
38 #include <plugin/impl.hxx>
39 #include <tools/fsys.hxx>
40 #include <ucbhelper/content.hxx>
41 #include <tools/urlobj.hxx>
42 #include <tools/string.hxx>
43 #include <vcl/svapp.hxx>
44 #include <vos/timer.hxx>
45 #include <osl/file.hxx>
47 #ifdef UNX
48 #include <sys/types.h>
49 #include <sys/socket.h>
50 #endif
52 #if OSL_DEBUG_LEVEL > 1
53 #include <stdio.h>
54 #endif
56 using namespace com::sun::star;
57 using namespace com::sun::star::io;
58 using namespace com::sun::star::beans;
59 using namespace com::sun::star::plugin;
60 using namespace rtl;
61 using namespace osl;
63 class PluginDisposer : public vos::OTimer
65 private:
66 XPlugin_Impl* m_pPlugin;
68 virtual void SAL_CALL onShot();
69 public:
70 PluginDisposer( XPlugin_Impl* pPlugin ) :
71 OTimer( vos::TTimeValue( 2, 0 ),
72 vos::TTimeValue( 2, 0 ) ),
73 m_pPlugin( pPlugin )
74 { start(); }
75 ~PluginDisposer() {}
78 void PluginDisposer::onShot()
80 if( m_pPlugin )
82 if( m_pPlugin->isDisposable() )
84 ULONG nEvent;
85 Application::PostUserEvent( nEvent, LINK( m_pPlugin, XPlugin_Impl, secondLevelDispose ), (void*)m_pPlugin );
88 else
89 release();
92 //==================================================================================================
94 Any XPlugin_Impl::queryInterface( const Type& type ) throw( RuntimeException )
96 return OWeakAggObject::queryInterface( type );
99 Any XPlugin_Impl::queryAggregation( const Type& type ) throw( RuntimeException )
101 Any aRet( cppu::queryInterface( type, static_cast< XPlugin* >(this) ) );
102 if( ! aRet.hasValue() )
103 aRet = PluginControl_Impl::queryAggregation( type );
104 return aRet;
108 XPlugin_Impl::XPlugin_Impl( const uno::Reference< com::sun::star::lang::XMultiServiceFactory > & rSMgr) :
109 PluginControl_Impl(),
110 m_xSMgr( rSMgr ),
111 m_pPluginComm( NULL ),
112 m_aEncoding( gsl_getSystemTextEncoding() ),
113 m_pArgv( NULL ),
114 m_pArgn( NULL ),
115 m_nArgs( 0 ),
116 m_aPluginMode( NP_FULL ),
117 m_nProvidingState( PROVIDING_NONE ),
118 m_nCalledFromPlugin( 0 ),
119 m_pDisposer( NULL ),
120 m_bIsDisposed( sal_False )
122 memset( &m_aInstance, 0, sizeof( m_aInstance ) );
123 memset( &m_aNPWindow, 0, sizeof( m_aNPWindow ) );
124 memset( &m_aSysPlugData, 0, sizeof( m_aSysPlugData ) );
126 m_xModel = new PluginModel();
127 uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
128 xPS->addPropertyChangeListener( OUString(), this );
130 Guard< Mutex > aGuard( PluginManager::get().getPluginMutex() );
131 PluginManager::get().getPlugins().push_back( this );
134 void XPlugin_Impl::destroyInstance()
136 Guard< Mutex > aGuard( m_aMutex );
138 NPSavedData* pSavedData = NULL;
140 destroyStreams();
141 if( getPluginComm() )
143 getPluginComm()->NPP_Destroy( this, &pSavedData );
144 getPluginComm()->decRef();
145 m_pPluginComm = NULL;
148 freeArgs();
150 while( m_aPEventListeners.size() )
152 delete *m_aPEventListeners.begin();
153 m_aPEventListeners.pop_front();
157 XPlugin_Impl::~XPlugin_Impl()
159 destroyInstance();
162 void XPlugin_Impl::checkListeners( const char* normalizedURL )
164 if( ! normalizedURL )
165 return;
167 Guard< Mutex > aGuard( m_aMutex );
169 std::list<PluginEventListener*>::iterator iter;
170 for( iter = m_aPEventListeners.begin();
171 iter != m_aPEventListeners.end();
172 ++iter )
174 if( ! strcmp( normalizedURL, (*iter)->getURL() ) ||
175 ! strcmp( normalizedURL, (*iter)->getNormalizedURL() ) )
177 (*iter)->disposing( com::sun::star::lang::EventObject() );
178 delete *iter;
179 m_aPEventListeners.remove( *iter );
180 return;
185 IMPL_LINK( XPlugin_Impl, secondLevelDispose, XPlugin_Impl*, /*pThis*/ )
187 Guard< Mutex > aGuard( m_aMutex );
189 // may have become undisposable between PostUserEvent and here
190 // or may have disposed and receive a second UserEvent
191 std::list<XPlugin_Impl*>& rList = PluginManager::get().getPlugins();
192 std::list<XPlugin_Impl*>::iterator iter;
195 Guard< Mutex > aPluginGuard( PluginManager::get().getPluginMutex() );
196 for( iter = rList.begin(); iter != rList.end(); ++iter )
198 if( *iter == this )
199 break;
201 if( iter == rList.end() || ! isDisposable() )
202 return 0;
205 if (m_pDisposer)
207 m_pDisposer->release();
208 m_pDisposer = NULL;
211 uno::Reference< XPlugin > xProtection( this );
212 uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
213 xPS->removePropertyChangeListener( OUString(), this );
215 Guard< Mutex > aPluginGuard( PluginManager::get().getPluginMutex() );
216 rList.remove( this );
218 m_aNPWindow.window = NULL;
219 #ifndef UNX
220 // acrobat does an unconditional XtParent on the windows widget
221 getPluginComm()->NPP_SetWindow( this );
222 #endif
223 destroyInstance();
224 PluginControl_Impl::dispose();
225 return 0;
228 void XPlugin_Impl::dispose() throw()
230 Guard< Mutex > aGuard( m_aMutex );
232 if (m_bIsDisposed || !getPluginComm())
233 return;
234 m_bIsDisposed = sal_True;
236 if( isDisposable() )
237 secondLevelDispose( this );
238 else
240 m_pDisposer = new PluginDisposer( this );
241 m_pDisposer->acquire();
245 void XPlugin_Impl::initArgs( const Sequence< OUString >& argn,
246 const Sequence< OUString >& argv,
247 sal_Int16 mode )
249 m_aPluginMode = mode;
251 m_nArgs = argn.getLength();
252 m_pArgn = new const char*[m_nArgs];
253 m_pArgv = new const char*[m_nArgs];
254 const OUString* pUArgn = argn.getConstArray();
255 const OUString* pUArgv = argv.getConstArray();
256 for( int i = 0; i < m_nArgs; i++ )
258 m_pArgn[i] = strdup(
259 OUStringToOString( pUArgn[i], m_aEncoding ).getStr()
261 m_pArgv[i] = strdup(
262 OUStringToOString( pUArgv[i], m_aEncoding ).getStr()
267 void XPlugin_Impl::freeArgs()
269 if( m_nArgs > 0 )
271 for( ; m_nArgs--; )
273 free( (void*)m_pArgn[m_nArgs] );
274 free( (void*)m_pArgv[m_nArgs] );
276 delete [] m_pArgn;
277 delete [] m_pArgv;
281 void XPlugin_Impl::prependArg( const char* pName, const char* pValue )
283 const char** pNewNames = new const char*[m_nArgs+1];
284 const char** pNewValues = new const char*[m_nArgs+1];
286 pNewNames[0] = strdup( pName );
287 pNewValues[0] = strdup( pValue );
288 for( int nIndex = 0; nIndex < m_nArgs; ++nIndex )
290 pNewNames[nIndex+1] = m_pArgn[nIndex];
291 pNewValues[nIndex+1]= m_pArgv[nIndex];
293 // free old arrays
294 delete [] m_pArgn;
295 delete [] m_pArgv;
296 // set new arrays
297 m_pArgn = pNewNames;
298 m_pArgv = pNewValues;
299 // set new number of arguments
300 m_nArgs++;
301 #if OSL_DEBUG_LEVEL > 1
302 fprintf( stderr, "inserted %s=%s\n", pNewNames[0], pNewValues[0] );
303 #endif
306 void XPlugin_Impl::handleSpecialArgs()
308 // special handling for real audio which needs a lot of parameters
309 // or won't function at all
310 if( ! m_aDescription.Mimetype.compareToAscii( "audio/x-pn-realaudio-plugin" ) && m_nArgs < 1 )
312 OUString aURL;
313 if( m_xModel.is() )
317 uno::Reference< XPropertySet > xProp( m_xModel, UNO_QUERY );
318 Any aProp = xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) );
319 aProp >>= aURL;
321 catch( UnknownPropertyException )
326 if( aURL.getLength() )
328 // set new args, old args need not be freed as there were none set
329 m_nArgs = 6;
330 m_pArgn = new const char*[m_nArgs];
331 m_pArgv = new const char*[m_nArgs];
333 // SRC
334 m_pArgn[0] = strdup( "SRC" );
335 m_pArgv[0] = strdup( OUStringToOString( aURL, m_aEncoding ).getStr() );
336 // WIDTH
337 m_pArgn[1] = strdup( "WIDTH" );
338 m_pArgv[1] = strdup( "200" );
339 // HEIGHT
340 m_pArgn[2] = strdup( "HEIGHT" );
341 m_pArgv[2] = strdup( "200" );
342 // CONTROLS
343 m_pArgn[3] = strdup( "CONTROLS" );
344 m_pArgv[3] = strdup( "PlayButton,StopButton,ImageWindow" );
345 // AUTOSTART
346 m_pArgn[4] = strdup( "AUTOSTART" );
347 m_pArgv[4] = strdup( "TRUE" );
348 // NOJAVA
349 m_pArgn[5] = strdup( "NOJAVA" );
350 m_pArgv[5] = strdup( "TRUE" );
353 // #69333# special for pdf
354 else if( ! m_aDescription.Mimetype.compareToAscii( "application/pdf" ) )
355 m_aPluginMode = PluginMode::FULL;
357 // see if we have a TYPE tag
358 int nIndex;
359 for( nIndex = 0; nIndex < m_nArgs; ++nIndex )
360 if( m_pArgn[nIndex][0] == 'T' &&
361 m_pArgn[nIndex][1] == 'Y' &&
362 m_pArgn[nIndex][2] == 'P' &&
363 m_pArgn[nIndex][3] == 'E' &&
364 m_pArgn[nIndex][4] == 0 )
365 break;
366 if( nIndex >= m_nArgs )
368 // TYPE
369 prependArg( "TYPE", OUStringToOString( m_aDescription.Mimetype, m_aEncoding ).getStr() );
372 // see if we have a SRC tag
373 for( nIndex = 0; nIndex < m_nArgs; ++nIndex )
374 if( m_pArgn[nIndex][0] == 'S' &&
375 m_pArgn[nIndex][1] == 'R' &&
376 m_pArgn[nIndex][2] == 'C' &&
377 m_pArgn[nIndex][3] == 0 )
378 break;
379 if( nIndex >= m_nArgs )
381 // need a SRC parameter (as all browser set one on the plugin
382 OUString aURL;
383 if( m_xModel.is() )
387 uno::Reference< XPropertySet > xProp( m_xModel, UNO_QUERY );
388 Any aProp = xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) );
389 aProp >>= aURL;
391 catch( UnknownPropertyException )
396 if( aURL.getLength() )
398 // SRC
399 prependArg( "SRC", OUStringToOString( aURL, m_aEncoding ).getStr() );
404 void XPlugin_Impl::initInstance( const PluginDescription& rDescription,
405 const Sequence< OUString >& argn,
406 const Sequence< OUString >& argv,
407 sal_Int16 mode )
409 Guard< Mutex > aGuard( m_aMutex );
411 m_aDescription = rDescription;
412 initArgs( argn, argv, mode );
413 handleSpecialArgs();
416 void XPlugin_Impl::initInstance( const OUString& rURL,
417 const Sequence< OUString >& argn,
418 const Sequence< OUString >& argv,
419 sal_Int16 mode )
421 Guard< Mutex > aGuard( m_aMutex );
423 initArgs( argn, argv, mode );
424 m_aDescription = fitDescription( rURL );
426 m_xModel = new PluginModel( rURL, m_aDescription.Mimetype );
427 handleSpecialArgs();
430 void XPlugin_Impl::modelChanged()
432 Guard< Mutex > aGuard( m_aMutex );
434 m_nProvidingState = PROVIDING_MODEL_UPDATE;
436 destroyInstance();
438 m_aDescription = fitDescription( getCreationURL() );
439 if( !m_aDescription.Mimetype.getLength() )
441 m_nProvidingState = PROVIDING_NONE;
442 return;
445 OUString aURL = getCreationURL();
446 provideNewStream( m_aDescription.Mimetype,
447 uno::Reference< XActiveDataSource >(),
448 aURL,
449 0, 0, (sal_Bool)(aURL.compareToAscii( "file:", 5 ) == 0) );
450 m_nProvidingState = PROVIDING_NONE;
453 OUString XPlugin_Impl::getCreationURL()
455 Guard< Mutex > aGuard( m_aMutex );
457 OUString aRet;
458 uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
459 if( xPS.is() )
461 Any aValue = xPS->getPropertyValue( OUString::createFromAscii( "URL" ) );
462 aValue >>= aRet;
464 return aRet;
468 sal_Bool XPlugin_Impl::setModel( const uno::Reference< com::sun::star::awt::XControlModel > & Model )
469 throw( RuntimeException )
471 Guard< Mutex > aGuard( m_aMutex );
473 uno::Reference< com::sun::star::beans::XPropertySet > xPS( Model, UNO_QUERY );
474 if( ! xPS.is() )
475 return sal_False;
477 if( getCreationURL().getLength() )
479 m_xModel = Model;
480 modelChanged();
481 xPS->addPropertyChangeListener( OUString(), this );
482 return sal_True;
484 return sal_False;
487 void XPlugin_Impl::createPeer( const uno::Reference< com::sun::star::awt::XToolkit > & xToolkit, const uno::Reference< com::sun::star::awt::XWindowPeer > & Parent )
488 throw( RuntimeException )
490 Guard< Mutex > aGuard( m_aMutex );
492 if( ! _xPeer.is() )
494 if( ! Parent.is() )
495 throw RuntimeException();
496 PluginControl_Impl::createPeer( xToolkit, Parent );
500 void XPlugin_Impl::loadPlugin()
502 Guard< Mutex > aGuard( m_aMutex );
504 std::list<PluginComm*>::iterator iter;
505 for( iter = PluginManager::get().getPluginComms().begin();
506 iter != PluginManager::get().getPluginComms().end(); ++iter )
508 if( OStringToOUString( (*iter)->getLibName(), m_aEncoding ) == m_aDescription.PluginName )
510 setPluginComm( *iter );
511 break;
514 const SystemEnvData* pEnvData = getSysChildSysData();
515 #if defined( UNX ) && !(defined(QUARTZ))
516 XSync( (Display*)pEnvData->pDisplay, False );
517 #endif
518 if( ! getPluginComm() )
520 if( m_aDescription.PluginName.getLength() )
522 #if defined QUARTZ
523 PluginComm* pComm = new MacPluginComm( m_aDescription.Mimetype,
524 m_aDescription.PluginName,
525 pEnvData->pView );
526 #elif defined UNX
527 // need a new PluginComm
528 PluginComm* pComm = NULL;
529 int sv[2];
530 if( !socketpair( AF_UNIX, SOCK_STREAM, 0, sv ) )
531 pComm = new UnxPluginComm( m_aDescription.Mimetype,
532 m_aDescription.PluginName,
533 (XLIB_Window)pEnvData->aWindow,
534 sv[0],
535 sv[1]
537 #elif (defined WNT || defined OS2)
538 PluginComm* pComm = new PluginComm_Impl( m_aDescription.Mimetype,
539 m_aDescription.PluginName,
540 (HWND)pEnvData->hWnd );
541 #endif
542 setPluginComm( pComm );
544 else
545 return;
548 NPError aError = getPluginComm()->
549 NPP_New( (char*)OUStringToOString( m_aDescription.Mimetype,
550 m_aEncoding).getStr(),
551 getNPPInstance(),
552 m_aPluginMode == PluginMode::FULL ? NP_FULL : NP_EMBED,
553 ::sal::static_int_cast< int16, int >( m_nArgs ),
554 (char**)(m_nArgs ? m_pArgn : NULL),
555 (char**)(m_nArgs ? m_pArgv : NULL),
556 NULL );
557 #ifdef QUARTZ
558 // m_aNPWindow is set up in the MacPluginComm from the view
559 m_aSysPlugData.m_pParentView = pEnvData->pView;
560 #elif defined( UNX )
561 XSync( (Display*)pEnvData->pDisplay, False );
562 m_aNPWindow.window = (void*)pEnvData->aWindow;
563 m_aNPWindow.ws_info = NULL;
564 #else
565 m_aNPWindow.window = (void*)pEnvData->hWnd;
566 #endif
567 com::sun::star::awt::Rectangle aPosSize = getPosSize();
569 for( int i = 0; i < m_nArgs; i++ )
571 OString aName( m_pArgn[i] );
572 if( aName.equalsIgnoreAsciiCase( "width" ) )
574 OString aValue( m_pArgv[i] );
575 aPosSize.Width = aValue.toInt32();
577 else if( aName.equalsIgnoreAsciiCase( "height" ) )
579 OString aValue( m_pArgv[i] );
580 aPosSize.Height = aValue.toInt32();
584 m_aNPWindow.clipRect.top = 0;
585 m_aNPWindow.clipRect.left = 0;
586 m_aNPWindow.clipRect.bottom = ::sal::static_int_cast< uint16, sal_Int32 >( aPosSize.Height );
587 m_aNPWindow.clipRect.right = ::sal::static_int_cast< uint16, sal_Int32 >( aPosSize.Width );
588 m_aNPWindow.type = NPWindowTypeWindow;
590 m_aNPWindow.x = 0;
591 m_aNPWindow.y = 0;
592 m_aNPWindow.width = aPosSize.Width ? aPosSize.Width : 600;
593 m_aNPWindow.height = aPosSize.Height ? aPosSize.Height : 600;
595 aError = getPluginComm()->NPP_SetWindow( this );
598 void XPlugin_Impl::destroyStreams()
600 Guard< Mutex > aGuard( m_aMutex );
602 // streams remove themselves from this list when deleted
603 while( m_aOutputStreams.size() )
604 delete *m_aOutputStreams.begin();
606 // input streams are XOutputStreams, they cannot be simply deleted
607 std::list<PluginInputStream*> aLocalList( m_aInputStreams );
608 for( std::list<PluginInputStream*>::iterator it = aLocalList.begin();
609 it != aLocalList.end(); ++it )
610 (*it)->setMode( -1 );
613 PluginStream* XPlugin_Impl::getStreamFromNPStream( NPStream* stream )
615 Guard< Mutex > aGuard( m_aMutex );
617 std::list<PluginInputStream*>::iterator iter;
618 for( iter = m_aInputStreams.begin(); iter != m_aInputStreams.end(); ++iter )
619 if( (*iter)->getStream() == stream )
620 return *iter;
622 std::list<PluginOutputStream*>::iterator iter2;
623 for( iter2 = m_aOutputStreams.begin(); iter2 != m_aOutputStreams.end(); ++iter2 )
624 if( (*iter2)->getStream() == stream )
625 return *iter2;
627 return NULL;
630 sal_Bool XPlugin_Impl::provideNewStream(const OUString& mimetype,
631 const uno::Reference< com::sun::star::io::XActiveDataSource > & stream,
632 const OUString& url, sal_Int32 length,
633 sal_Int32 lastmodified, sal_Bool isfile) throw()
636 Guard< Mutex > aGuard( m_aMutex );
637 sal_Bool bRet = sal_False;
639 if( m_nProvidingState != PROVIDING_NONE )
641 m_nProvidingState = PROVIDING_NOW;
642 Any aAny;
643 aAny <<= url;
644 uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
645 if( xPS.is() )
649 xPS->setPropertyValue( OUString::createFromAscii( "URL" ), aAny );
650 aAny <<= mimetype;
651 xPS->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny );
653 catch(...)
658 m_nProvidingState = PROVIDING_NOW;
660 OString aMIME;
661 if( mimetype.getLength() )
662 aMIME = OUStringToOString( mimetype, m_aEncoding );
663 else
664 aMIME = OUStringToOString( m_aDescription.Mimetype, m_aEncoding );
666 OString aURL = OUStringToOString( url, m_aEncoding );
668 // check wether there is a notifylistener for this stream
669 // this means that the strema is created from the plugin
670 // via NPN_GetURLNotify or NPN_PostURLNotify
671 std::list<PluginEventListener*>::iterator iter;
672 for( iter = m_aPEventListeners.begin();
673 iter != m_aPEventListeners.end();
674 ++iter )
676 if( (*iter)->getNormalizedURL() == aURL )
678 aURL = (*iter)->getURL();
679 break;
683 if( ! m_pPluginComm )
685 loadPlugin();
686 if( m_aLastGetUrl.getLength() && m_aLastGetUrl == aURL )
688 // plugin is pulling data, don't push the same stream;
689 // this complicated method could have been avoided if
690 // all plugins respected the SRC parameter; but e.g.
691 // acrobat reader plugin does not
692 m_nProvidingState = PROVIDING_NONE;
693 return sal_True;
696 if( ! m_pPluginComm )
697 return sal_False;
699 if( ! url.getLength() )
700 // this is valid if the plugin is supposed to
701 // pull data (via e.g. NPN_GetURL)
702 return sal_True;
704 // set mimetype on model
706 uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
707 if( xPS.is() )
711 Any aAny;
712 aAny <<= m_aDescription.Mimetype;
713 xPS->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny );
715 catch(...)
721 // there may be plugins that can use the file length information,
722 // but currently none are known. Since this file opening/seeking/closing
723 // is rather costly, it is #if'ed out. If there are plugins known to
724 // make use of the file length, simply put it in
725 #if 0
726 if( isfile && ! length )
728 osl::File aFile( url );
729 if( aFile.open( OpenFlag_Read ) == FileBase::E_None )
731 aFile.setPos( Pos_End, 0 );
732 sal_uInt64 nPos = 0;
733 if( aFile.getPos( nPos ) == FileBase::E_None )
734 length = nPos;
735 aFile.close();
738 #endif
740 PluginInputStream* pStream = new PluginInputStream( this, aURL.getStr(),
741 length, lastmodified );
742 uno::Reference< com::sun::star::io::XOutputStream > xNewStream( pStream );
744 if( iter != m_aPEventListeners.end() )
745 pStream->getStream()->notifyData = (*iter)->getNotifyData();
747 uint16 stype = 0;
749 // special handling acrobat reader
750 // presenting a seekable stream to it does not seem to work correctly
751 if( aMIME.equals( "application/pdf" ) )
752 isfile = sal_False;
754 #if OSL_DEBUG_LEVEL > 1
755 fprintf( stderr,
756 "new stream \"%s\" of MIMEType \"%s\"\n"
757 "for plugin \"%s\"\n"
758 "seekable = %s, length = %"SAL_PRIdINT32"\n",
759 aURL.getStr(), aMIME.getStr(), getPluginComm()->getLibName().getStr(),
760 isfile ? "true" : "false", length );
762 #endif
763 if( ! m_pPluginComm->NPP_NewStream( &m_aInstance,
764 (char*)aMIME.getStr(),
765 pStream->getStream(), isfile,
766 &stype ) )
768 #if OSL_DEBUG_LEVEL > 1
769 const char* pType;
770 switch( stype )
772 case NP_NORMAL: pType = "NP_NORMAL";break;
773 case NP_SEEK: pType = "NP_SEEK";break;
774 case NP_ASFILE: pType = "NP_ASFILE";break;
775 case NP_ASFILEONLY: pType = "NP_ASFILEONLY";break;
776 default: pType = "unknown!!!";
778 fprintf( stderr, "Plugin wants it in Mode %s\n", pType );
779 #endif
780 if( isfile && stype == NP_ASFILEONLY )
782 OString aFileName;
783 if( url.compareToAscii( "file:", 5 ) == 0 )
785 OUString aSysName;
786 osl_getSystemPathFromFileURL( url.pData, &aSysName.pData );
787 aFileName = OUStringToOString( aSysName, m_aEncoding );
789 else
790 aFileName = OUStringToOString( url, m_aEncoding );
791 m_pPluginComm->
792 NPP_StreamAsFile( &m_aInstance,
793 pStream->getStream(),
794 aFileName.getStr() );
796 else
798 pStream->setMode( stype );
800 if( ! stream.is() )
802 // stream has to be loaded by PluginStream itself via UCB
803 pStream->load();
805 else
807 uno::Reference< com::sun::star::io::XConnectable > xConnectable( stream, UNO_QUERY );
808 pStream->setPredecessor( xConnectable );
809 if( xConnectable.is() )
811 xConnectable->setSuccessor( static_cast< com::sun::star::io::XConnectable* >(pStream) );
812 while( xConnectable->getPredecessor().is() )
813 xConnectable = xConnectable->getPredecessor();
815 stream->setOutputStream( xNewStream );
816 pStream->setSource( stream );
817 uno::Reference< com::sun::star::io::XActiveDataControl > xController;
818 if( xConnectable.is() )
819 xController = uno::Reference< com::sun::star::io::XActiveDataControl >( xConnectable, UNO_QUERY );
820 else
821 xController = uno::Reference< com::sun::star::io::XActiveDataControl >( stream, UNO_QUERY );
823 if( xController.is() )
824 xController->start();
827 bRet = sal_True;
830 m_nProvidingState = PROVIDING_NONE;
832 return bRet;
835 void XPlugin_Impl::disposing( const com::sun::star::lang::EventObject& /*rSource*/ ) throw()
839 void XPlugin_Impl::propertyChange( const com::sun::star::beans::PropertyChangeEvent& rEvent ) throw()
841 Guard< Mutex > aGuard( m_aMutex );
843 if( ! rEvent.PropertyName.compareToAscii( "URL" ) )
845 OUString aStr;
846 rEvent.NewValue >>= aStr;
847 if( m_nProvidingState == PROVIDING_NONE )
849 if( aStr != m_aURL )
851 m_aURL = aStr;
852 modelChanged();
858 void XPlugin_Impl::setPluginContext( const uno::Reference< XPluginContext > & rContext )
860 m_rBrowserContext = rContext;
863 void XPlugin_Impl::setPosSize( sal_Int32 nX_, sal_Int32 nY_, sal_Int32 nWidth_, sal_Int32 nHeight_, sal_Int16 nFlags )
864 throw( RuntimeException )
866 Guard< Mutex > aGuard( m_aMutex );
868 #if OSL_DEBUG_LEVEL > 1
869 fprintf( stderr, "XPlugin_Impl::setPosSize( %"SAL_PRIdINT32", %"SAL_PRIdINT32", %"SAL_PRIdINT32", %"SAL_PRIdINT32", %d )\n",
870 nX_, nY_, nWidth_, nHeight_, nFlags );
871 #endif
873 PluginControl_Impl::setPosSize(nX_, nY_, nWidth_, nHeight_, nFlags);
875 m_aNPWindow.x = 0;
876 m_aNPWindow.y = 0;
877 m_aNPWindow.width = nWidth_;
878 m_aNPWindow.height = nHeight_;
879 m_aNPWindow.clipRect.top = 0;
880 m_aNPWindow.clipRect.left = 0;
881 m_aNPWindow.clipRect.right = ::sal::static_int_cast< uint16, sal_Int32 >( nWidth_ );
882 m_aNPWindow.clipRect.bottom = ::sal::static_int_cast< uint16, sal_Int32 >( nHeight_ );
884 if( getPluginComm() )
885 getPluginComm()->NPP_SetWindow( this );
888 PluginDescription XPlugin_Impl::fitDescription( const OUString& rURL )
890 uno::Reference< XPluginManager > xPMgr( m_xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.plugin.PluginManager" ) ), UNO_QUERY );
891 if( !xPMgr.is() )
893 m_nProvidingState = PROVIDING_NONE;
894 return PluginDescription();
897 Sequence< PluginDescription > aDescrs = xPMgr->getPluginDescriptions();
898 const PluginDescription* pDescrs = aDescrs.getConstArray();
900 for( int nArg = 0; nArg < m_nArgs; nArg++ )
902 if( strncmp( m_pArgn[nArg], "TYPE", 4 ) == 0 &&
903 m_pArgn[nArg][4] == 0 )
905 for( int i = 0; i < aDescrs.getLength(); i++ )
907 if( pDescrs[i].Mimetype.compareToAscii( m_pArgv[nArg] ) == 0 )
908 return pDescrs[i];
913 int nPos = rURL.lastIndexOf( (sal_Unicode)'.' );
914 OUString aExt = rURL.copy( nPos ).toAsciiLowerCase();
915 if( nPos != -1 )
917 for( int i = 0; i < aDescrs.getLength(); i++ )
919 OUString aThisExt = pDescrs[ i ].Extension.toAsciiLowerCase();
920 if( aThisExt.indexOf( aExt ) != -1 )
922 return pDescrs[i];
926 return PluginDescription();
930 PluginStream::PluginStream( XPlugin_Impl* pPlugin,
931 const char* url, sal_uInt32 len, sal_uInt32 lastmod ) :
932 m_pPlugin( pPlugin )
934 memset( &m_aNPStream, 0, sizeof( m_aNPStream ) );
935 m_aNPStream.url = strdup( url );
936 m_aNPStream.end = len;
937 m_aNPStream.lastmodified = lastmod;
940 PluginStream::~PluginStream()
942 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
944 if( m_pPlugin && m_pPlugin->getPluginComm() )
946 m_pPlugin->getPluginComm()->NPP_DestroyStream( m_pPlugin->getNPPInstance(),
947 &m_aNPStream, NPRES_DONE );
948 m_pPlugin->checkListeners( m_aNPStream.url );
949 m_pPlugin->getPluginComm()->NPP_SetWindow( m_pPlugin );
951 ::free( (void*)m_aNPStream.url );
954 PluginInputStream::PluginInputStream( XPlugin_Impl* pPlugin,
955 const char* url,
956 sal_uInt32 len,
957 sal_uInt32 lastmod ) :
958 PluginStream( pPlugin, url, len, lastmod ),
959 m_pContent( NULL ),
960 m_nMode( NP_NORMAL ),
961 m_nWritePos( 0 )
963 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
965 m_pPlugin->getInputStreams().push_back( this );
966 DirEntry aEntry;
967 aEntry = aEntry.TempName();
969 // set correct extension, some plugins need that
970 DirEntry aName( String( m_aNPStream.url, m_pPlugin->getTextEncoding() ) );
971 String aExtension = aName.GetExtension();
972 if( aExtension.Len() )
973 aEntry.SetExtension( aExtension );
974 m_aFileStream.Open( aEntry.GetFull(), STREAM_READ | STREAM_WRITE );
975 if( ! m_aFileStream.IsOpen() )
977 // #74808# might be that the extension scrambled the whole filename
978 aEntry = aEntry.TempName();
979 m_aFileStream.Open( aEntry.GetFull(), STREAM_READ | STREAM_WRITE );
983 PluginInputStream::~PluginInputStream()
985 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
987 m_pPlugin->getInputStreams().remove( this );
989 String aFile( m_aFileStream.GetFileName() );
991 m_aFileStream.Close();
992 if( m_pPlugin )
994 ByteString aFileName( aFile, m_pPlugin->getTextEncoding() );
995 if( m_pPlugin->getPluginComm() && m_nMode != -1 )
996 // mode -1 means either an error occured,
997 // or the plugin is already disposing
999 m_pPlugin->getPluginComm()->addFileToDelete( aFile );
1000 if( m_nMode == NP_ASFILE )
1002 m_pPlugin->getPluginComm()->
1003 NPP_StreamAsFile( m_pPlugin->getNPPInstance(),
1004 &m_aNPStream,
1005 aFileName.GetBuffer() );
1007 m_pPlugin->getPluginComm()->NPP_SetWindow( m_pPlugin );
1008 m_pPlugin->getInputStreams().remove( this );
1010 else
1011 DirEntry( m_aFileStream.GetFileName() ).Kill();
1013 else
1014 DirEntry( m_aFileStream.GetFileName() ).Kill();
1015 if( m_pContent )
1016 delete m_pContent;
1019 PluginStreamType PluginInputStream::getStreamType()
1021 return InputStream;
1024 void PluginInputStream::load()
1026 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1028 INetURLObject aUrl;
1029 aUrl.SetSmartProtocol( INET_PROT_FILE );
1030 aUrl.SetSmartURL(
1031 String( getStream()->url,
1032 ::sal::static_int_cast< USHORT, size_t >( strlen( getStream()->url ) ),
1033 RTL_TEXTENCODING_MS_1252
1034 ) );
1037 m_pContent =
1038 new ::ucbhelper::Content(
1039 aUrl.GetMainURL(INetURLObject::DECODE_TO_IURI),
1040 uno::Reference< com::sun::star::ucb::XCommandEnvironment >()
1042 m_pContent->openStream( static_cast< XOutputStream* >( this ) );
1044 catch( com::sun::star::uno::Exception )
1049 void PluginInputStream::setMode( sal_Int32 nMode )
1051 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1053 m_nMode = nMode;
1055 // invalidation by plugin
1056 if( m_nMode == -1 && m_pPlugin )
1058 m_pPlugin->getInputStreams().remove( this );
1059 m_pPlugin = NULL;
1063 void PluginInputStream::writeBytes( const Sequence<sal_Int8>& Buffer ) throw()
1065 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1067 m_aFileStream.Seek( STREAM_SEEK_TO_END );
1068 m_aFileStream.Write( Buffer.getConstArray(), Buffer.getLength() );
1070 if( m_nMode == NP_SEEK )
1071 // hold reference, streem gets destroyed in NPN_DestroyStream
1072 m_xSelf = this;
1074 if( m_nMode == -1 || !m_pPlugin->getPluginComm() )
1075 return;
1077 UINT32 nPos = m_aFileStream.Tell();
1078 UINT32 nBytes = 0;
1079 while( m_nMode != NP_ASFILEONLY &&
1080 m_nWritePos < nPos &&
1081 (nBytes = m_pPlugin->getPluginComm()-> NPP_WriteReady(
1082 m_pPlugin->getNPPInstance(), &m_aNPStream )) > 0 )
1084 nBytes = (nBytes > nPos - m_nWritePos) ? nPos - m_nWritePos : nBytes;
1086 char* pBuffer = new char[ nBytes ];
1087 m_aFileStream.Seek( m_nWritePos );
1088 nBytes = m_aFileStream.Read( pBuffer, nBytes );
1090 int32 nBytesRead = 0;
1093 nBytesRead = m_pPlugin->getPluginComm()->NPP_Write(
1094 m_pPlugin->getNPPInstance(), &m_aNPStream, m_nWritePos, nBytes, pBuffer );
1096 catch( ... )
1098 nBytesRead = 0;
1100 delete [] pBuffer;
1102 if( nBytesRead < 0 )
1104 m_nMode = -1;
1105 return;
1108 m_nWritePos += nBytesRead;
1112 void PluginInputStream::closeOutput() throw()
1114 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1116 flush();
1117 m_xSource = uno::Reference< com::sun::star::io::XActiveDataSource >();
1120 sal_uInt32 PluginInputStream::read( sal_uInt32 offset, sal_Int8* buffer, sal_uInt32 size )
1122 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1124 if( m_nMode != NP_SEEK )
1125 return 0;
1127 m_aFileStream.Seek( offset );
1128 return m_aFileStream.Read( buffer, size );
1131 void PluginInputStream::flush(void) throw()
1135 PluginOutputStream::PluginOutputStream( XPlugin_Impl* pPlugin,
1136 const char* url,
1137 sal_uInt32 len,
1138 sal_uInt32 lastmod ) :
1139 PluginStream( pPlugin, url, len, lastmod ),
1140 m_xStream( pPlugin->getServiceManager()->createInstance( OUString::createFromAscii( "com.sun.star.io.DataOutputStream" ) ), UNO_QUERY )
1142 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1144 m_pPlugin->getOutputStreams().push_back( this );
1147 PluginOutputStream::~PluginOutputStream()
1149 Guard< Mutex > aGuard( m_pPlugin->getMutex() );
1151 m_pPlugin->getOutputStreams().remove( this );
1154 PluginStreamType PluginOutputStream::getStreamType()
1156 return OutputStream;