1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xplugin.cxx,v $
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>
48 #include <sys/types.h>
49 #include <sys/socket.h>
52 #if OSL_DEBUG_LEVEL > 1
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
;
63 class PluginDisposer
: public vos::OTimer
66 XPlugin_Impl
* m_pPlugin
;
68 virtual void SAL_CALL
onShot();
70 PluginDisposer( XPlugin_Impl
* pPlugin
) :
71 OTimer( vos::TTimeValue( 2, 0 ),
72 vos::TTimeValue( 2, 0 ) ),
78 void PluginDisposer::onShot()
82 if( m_pPlugin
->isDisposable() )
85 Application::PostUserEvent( nEvent
, LINK( m_pPlugin
, XPlugin_Impl
, secondLevelDispose
), (void*)m_pPlugin
);
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
);
108 XPlugin_Impl::XPlugin_Impl( const uno::Reference
< com::sun::star::lang::XMultiServiceFactory
> & rSMgr
) :
109 PluginControl_Impl(),
111 m_pPluginComm( NULL
),
112 m_aEncoding( gsl_getSystemTextEncoding() ),
116 m_aPluginMode( NP_FULL
),
117 m_nProvidingState( PROVIDING_NONE
),
118 m_nCalledFromPlugin( 0 ),
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
;
141 if( getPluginComm() )
143 getPluginComm()->NPP_Destroy( this, &pSavedData
);
144 getPluginComm()->decRef();
145 m_pPluginComm
= NULL
;
150 while( m_aPEventListeners
.size() )
152 delete *m_aPEventListeners
.begin();
153 m_aPEventListeners
.pop_front();
157 XPlugin_Impl::~XPlugin_Impl()
162 void XPlugin_Impl::checkListeners( const char* normalizedURL
)
164 if( ! normalizedURL
)
167 Guard
< Mutex
> aGuard( m_aMutex
);
169 std::list
<PluginEventListener
*>::iterator iter
;
170 for( iter
= m_aPEventListeners
.begin();
171 iter
!= m_aPEventListeners
.end();
174 if( ! strcmp( normalizedURL
, (*iter
)->getURL() ) ||
175 ! strcmp( normalizedURL
, (*iter
)->getNormalizedURL() ) )
177 (*iter
)->disposing( com::sun::star::lang::EventObject() );
179 m_aPEventListeners
.remove( *iter
);
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
)
201 if( iter
== rList
.end() || ! isDisposable() )
207 m_pDisposer
->release();
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
;
220 // acrobat does an unconditional XtParent on the windows widget
221 getPluginComm()->NPP_SetWindow( this );
224 PluginControl_Impl::dispose();
228 void XPlugin_Impl::dispose() throw()
230 Guard
< Mutex
> aGuard( m_aMutex
);
232 if (m_bIsDisposed
|| !getPluginComm())
234 m_bIsDisposed
= sal_True
;
237 secondLevelDispose( this );
240 m_pDisposer
= new PluginDisposer( this );
241 m_pDisposer
->acquire();
245 void XPlugin_Impl::initArgs( const Sequence
< OUString
>& argn
,
246 const Sequence
< OUString
>& argv
,
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
++ )
259 OUStringToOString( pUArgn
[i
], m_aEncoding
).getStr()
262 OUStringToOString( pUArgv
[i
], m_aEncoding
).getStr()
267 void XPlugin_Impl::freeArgs()
273 free( (void*)m_pArgn
[m_nArgs
] );
274 free( (void*)m_pArgv
[m_nArgs
] );
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
];
298 m_pArgv
= pNewValues
;
299 // set new number of arguments
301 #if OSL_DEBUG_LEVEL > 1
302 fprintf( stderr
, "inserted %s=%s\n", pNewNames
[0], pNewValues
[0] );
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 )
317 uno::Reference
< XPropertySet
> xProp( m_xModel
, UNO_QUERY
);
318 Any aProp
= xProp
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) );
321 catch( UnknownPropertyException
)
326 if( aURL
.getLength() )
328 // set new args, old args need not be freed as there were none set
330 m_pArgn
= new const char*[m_nArgs
];
331 m_pArgv
= new const char*[m_nArgs
];
334 m_pArgn
[0] = strdup( "SRC" );
335 m_pArgv
[0] = strdup( OUStringToOString( aURL
, m_aEncoding
).getStr() );
337 m_pArgn
[1] = strdup( "WIDTH" );
338 m_pArgv
[1] = strdup( "200" );
340 m_pArgn
[2] = strdup( "HEIGHT" );
341 m_pArgv
[2] = strdup( "200" );
343 m_pArgn
[3] = strdup( "CONTROLS" );
344 m_pArgv
[3] = strdup( "PlayButton,StopButton,ImageWindow" );
346 m_pArgn
[4] = strdup( "AUTOSTART" );
347 m_pArgv
[4] = strdup( "TRUE" );
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
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 )
366 if( nIndex
>= m_nArgs
)
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 )
379 if( nIndex
>= m_nArgs
)
381 // need a SRC parameter (as all browser set one on the plugin
387 uno::Reference
< XPropertySet
> xProp( m_xModel
, UNO_QUERY
);
388 Any aProp
= xProp
->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) );
391 catch( UnknownPropertyException
)
396 if( aURL
.getLength() )
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
,
409 Guard
< Mutex
> aGuard( m_aMutex
);
411 m_aDescription
= rDescription
;
412 initArgs( argn
, argv
, mode
);
416 void XPlugin_Impl::initInstance( const OUString
& rURL
,
417 const Sequence
< OUString
>& argn
,
418 const Sequence
< OUString
>& argv
,
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
);
430 void XPlugin_Impl::modelChanged()
432 Guard
< Mutex
> aGuard( m_aMutex
);
434 m_nProvidingState
= PROVIDING_MODEL_UPDATE
;
438 m_aDescription
= fitDescription( getCreationURL() );
439 if( !m_aDescription
.Mimetype
.getLength() )
441 m_nProvidingState
= PROVIDING_NONE
;
445 OUString aURL
= getCreationURL();
446 provideNewStream( m_aDescription
.Mimetype
,
447 uno::Reference
< XActiveDataSource
>(),
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
);
458 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
461 Any aValue
= xPS
->getPropertyValue( OUString::createFromAscii( "URL" ) );
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
);
477 if( getCreationURL().getLength() )
481 xPS
->addPropertyChangeListener( OUString(), this );
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
);
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
);
514 const SystemEnvData
* pEnvData
= getSysChildSysData();
515 #if defined( UNX ) && !(defined(QUARTZ))
516 XSync( (Display
*)pEnvData
->pDisplay
, False
);
518 if( ! getPluginComm() )
520 if( m_aDescription
.PluginName
.getLength() )
523 PluginComm
* pComm
= new MacPluginComm( m_aDescription
.Mimetype
,
524 m_aDescription
.PluginName
,
527 // need a new PluginComm
528 PluginComm
* pComm
= NULL
;
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
,
537 #elif (defined WNT || defined OS2)
538 PluginComm
* pComm
= new PluginComm_Impl( m_aDescription
.Mimetype
,
539 m_aDescription
.PluginName
,
540 (HWND
)pEnvData
->hWnd
);
542 setPluginComm( pComm
);
548 NPError aError
= getPluginComm()->
549 NPP_New( (char*)OUStringToOString( m_aDescription
.Mimetype
,
550 m_aEncoding
).getStr(),
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
),
558 // m_aNPWindow is set up in the MacPluginComm from the view
559 m_aSysPlugData
.m_pParentView
= pEnvData
->pView
;
561 XSync( (Display
*)pEnvData
->pDisplay
, False
);
562 m_aNPWindow
.window
= (void*)pEnvData
->aWindow
;
563 m_aNPWindow
.ws_info
= NULL
;
565 m_aNPWindow
.window
= (void*)pEnvData
->hWnd
;
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
;
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
)
622 std::list
<PluginOutputStream
*>::iterator iter2
;
623 for( iter2
= m_aOutputStreams
.begin(); iter2
!= m_aOutputStreams
.end(); ++iter2
)
624 if( (*iter2
)->getStream() == stream
)
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
;
644 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
649 xPS
->setPropertyValue( OUString::createFromAscii( "URL" ), aAny
);
651 xPS
->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny
);
658 m_nProvidingState
= PROVIDING_NOW
;
661 if( mimetype
.getLength() )
662 aMIME
= OUStringToOString( mimetype
, m_aEncoding
);
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();
676 if( (*iter
)->getNormalizedURL() == aURL
)
678 aURL
= (*iter
)->getURL();
683 if( ! m_pPluginComm
)
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
;
696 if( ! m_pPluginComm
)
699 if( ! url
.getLength() )
700 // this is valid if the plugin is supposed to
701 // pull data (via e.g. NPN_GetURL)
704 // set mimetype on model
706 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
712 aAny
<<= m_aDescription
.Mimetype
;
713 xPS
->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny
);
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
726 if( isfile
&& ! length
)
728 osl::File
aFile( url
);
729 if( aFile
.open( OpenFlag_Read
) == FileBase::E_None
)
731 aFile
.setPos( Pos_End
, 0 );
733 if( aFile
.getPos( nPos
) == FileBase::E_None
)
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();
749 // special handling acrobat reader
750 // presenting a seekable stream to it does not seem to work correctly
751 if( aMIME
.equals( "application/pdf" ) )
754 #if OSL_DEBUG_LEVEL > 1
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
);
763 if( ! m_pPluginComm
->NPP_NewStream( &m_aInstance
,
764 (char*)aMIME
.getStr(),
765 pStream
->getStream(), isfile
,
768 #if OSL_DEBUG_LEVEL > 1
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
);
780 if( isfile
&& stype
== NP_ASFILEONLY
)
783 if( url
.compareToAscii( "file:", 5 ) == 0 )
786 osl_getSystemPathFromFileURL( url
.pData
, &aSysName
.pData
);
787 aFileName
= OUStringToOString( aSysName
, m_aEncoding
);
790 aFileName
= OUStringToOString( url
, m_aEncoding
);
792 NPP_StreamAsFile( &m_aInstance
,
793 pStream
->getStream(),
794 aFileName
.getStr() );
798 pStream
->setMode( stype
);
802 // stream has to be loaded by PluginStream itself via UCB
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
);
821 xController
= uno::Reference
< com::sun::star::io::XActiveDataControl
>( stream
, UNO_QUERY
);
823 if( xController
.is() )
824 xController
->start();
830 m_nProvidingState
= PROVIDING_NONE
;
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" ) )
846 rEvent
.NewValue
>>= aStr
;
847 if( m_nProvidingState
== PROVIDING_NONE
)
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
);
873 PluginControl_Impl::setPosSize(nX_
, nY_
, nWidth_
, nHeight_
, nFlags
);
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
);
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 )
913 int nPos
= rURL
.lastIndexOf( (sal_Unicode
)'.' );
914 OUString aExt
= rURL
.copy( nPos
).toAsciiLowerCase();
917 for( int i
= 0; i
< aDescrs
.getLength(); i
++ )
919 OUString aThisExt
= pDescrs
[ i
].Extension
.toAsciiLowerCase();
920 if( aThisExt
.indexOf( aExt
) != -1 )
926 return PluginDescription();
930 PluginStream::PluginStream( XPlugin_Impl
* pPlugin
,
931 const char* url
, sal_uInt32 len
, sal_uInt32 lastmod
) :
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
,
957 sal_uInt32 lastmod
) :
958 PluginStream( pPlugin
, url
, len
, lastmod
),
960 m_nMode( NP_NORMAL
),
963 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
965 m_pPlugin
->getInputStreams().push_back( this );
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();
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(),
1005 aFileName
.GetBuffer() );
1007 m_pPlugin
->getPluginComm()->NPP_SetWindow( m_pPlugin
);
1008 m_pPlugin
->getInputStreams().remove( this );
1011 DirEntry( m_aFileStream
.GetFileName() ).Kill();
1014 DirEntry( m_aFileStream
.GetFileName() ).Kill();
1019 PluginStreamType
PluginInputStream::getStreamType()
1024 void PluginInputStream::load()
1026 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
1029 aUrl
.SetSmartProtocol( INET_PROT_FILE
);
1031 String( getStream()->url
,
1032 ::sal::static_int_cast
< USHORT
, size_t >( strlen( getStream()->url
) ),
1033 RTL_TEXTENCODING_MS_1252
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() );
1055 // invalidation by plugin
1056 if( m_nMode
== -1 && m_pPlugin
)
1058 m_pPlugin
->getInputStreams().remove( this );
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
1074 if( m_nMode
== -1 || !m_pPlugin
->getPluginComm() )
1077 UINT32 nPos
= m_aFileStream
.Tell();
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
);
1102 if( nBytesRead
< 0 )
1108 m_nWritePos
+= nBytesRead
;
1112 void PluginInputStream::closeOutput() throw()
1114 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
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
)
1127 m_aFileStream
.Seek( offset
);
1128 return m_aFileStream
.Read( buffer
, size
);
1131 void PluginInputStream::flush(void) throw()
1135 PluginOutputStream::PluginOutputStream( XPlugin_Impl
* pPlugin
,
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
;