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 #define _LINUX_SOURCE_COMPAT
31 #include <sys/timer.h>
32 #undef _LINUX_SOURCE_COMPAT
40 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
41 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
42 #include <com/sun/star/loader/XImplementationLoader.hpp>
43 #include <com/sun/star/plugin/PluginManager.hpp>
45 #include <cppuhelper/queryinterface.hxx>
46 #include <comphelper/processfactory.hxx>
47 #include <plugin/impl.hxx>
48 #include <sal/log.hxx>
49 #include <ucbhelper/content.hxx>
50 #include <tools/urlobj.hxx>
51 #include <vcl/svapp.hxx>
52 #include <salhelper/timer.hxx>
53 #include <osl/file.hxx>
56 #include <sys/types.h>
57 #include <sys/socket.h>
60 #if OSL_DEBUG_LEVEL > 1
64 #include <boost/scoped_array.hpp>
66 using namespace com::sun::star
;
67 using namespace com::sun::star::io
;
68 using namespace com::sun::star::beans
;
69 using namespace com::sun::star::plugin
;
72 class PluginDisposer
: public salhelper::Timer
75 XPlugin_Impl
* m_pPlugin
;
77 virtual void SAL_CALL
onShot() SAL_OVERRIDE
;
79 PluginDisposer( XPlugin_Impl
* pPlugin
) :
80 salhelper::Timer( salhelper::TTimeValue( 2, 0 ),
81 salhelper::TTimeValue( 2, 0 ) ),
84 virtual ~PluginDisposer() {}
87 void PluginDisposer::onShot()
91 if( m_pPlugin
->isDisposable() )
93 Application::PostUserEvent( LINK( m_pPlugin
, XPlugin_Impl
, secondLevelDispose
), (void*)m_pPlugin
);
100 Any
XPlugin_Impl::queryInterface( const Type
& type
) throw( RuntimeException
, std::exception
)
102 return OWeakAggObject::queryInterface( type
);
105 Any
XPlugin_Impl::queryAggregation( const Type
& type
) throw( RuntimeException
, std::exception
)
107 Any
aRet( cppu::queryInterface( type
, static_cast< XPlugin
* >(this) ) );
108 if( ! aRet
.hasValue() )
109 aRet
= PluginControl_Impl::queryAggregation( type
);
114 XPlugin_Impl::XPlugin_Impl( const uno::Reference
< com::sun::star::lang::XMultiServiceFactory
> & rSMgr
) :
115 PluginControl_Impl(),
117 m_pPluginComm( NULL
),
118 m_pSysPlugData( CreateSysPlugData() ),
119 m_aEncoding( osl_getThreadTextEncoding() ),
123 m_aPluginMode( NP_FULL
),
124 m_nProvidingState( PROVIDING_NONE
),
125 m_nCalledFromPlugin( 0 ),
127 m_bIsDisposed( false )
129 memset( &m_aInstance
, 0, sizeof( m_aInstance
) );
130 memset( &m_aNPWindow
, 0, sizeof( m_aNPWindow
) );
132 m_xModel
= new PluginModel();
133 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
134 xPS
->addPropertyChangeListener( OUString(), this );
136 Guard
< Mutex
> aGuard( ::PluginManager::get().getPluginMutex() );
137 ::PluginManager::get().getPlugins().push_back( this );
140 void XPlugin_Impl::destroyInstance()
142 Guard
< Mutex
> aGuard( m_aMutex
);
144 NPSavedData
* pSavedData
= NULL
;
147 if( getPluginComm() )
149 getPluginComm()->NPP_Destroy( this, &pSavedData
);
150 getPluginComm()->decRef();
151 m_pPluginComm
= NULL
;
156 while( m_aPEventListeners
.size() )
158 delete *m_aPEventListeners
.begin();
159 m_aPEventListeners
.pop_front();
163 XPlugin_Impl::~XPlugin_Impl()
168 void XPlugin_Impl::checkListeners( const char* normalizedURL
)
170 if( ! normalizedURL
)
173 Guard
< Mutex
> aGuard( m_aMutex
);
175 std::list
<PluginEventListener
*>::iterator iter
;
176 for( iter
= m_aPEventListeners
.begin();
177 iter
!= m_aPEventListeners
.end();
180 if( ! strcmp( normalizedURL
, (*iter
)->getURL() ) ||
181 ! strcmp( normalizedURL
, (*iter
)->getNormalizedURL() ) )
183 (*iter
)->disposing( com::sun::star::lang::EventObject() );
185 m_aPEventListeners
.remove( *iter
);
191 IMPL_LINK( XPlugin_Impl
, secondLevelDispose
, XPlugin_Impl
*, /*pThis*/ )
193 Guard
< Mutex
> aGuard( m_aMutex
);
195 // may have become undisposable between PostUserEvent and here
196 // or may have disposed and receive a second UserEvent
197 std::list
<XPlugin_Impl
*>& rList
= ::PluginManager::get().getPlugins();
198 std::list
<XPlugin_Impl
*>::iterator iter
;
201 Guard
< Mutex
> aPluginGuard( ::PluginManager::get().getPluginMutex() );
202 for( iter
= rList
.begin(); iter
!= rList
.end(); ++iter
)
207 if( iter
== rList
.end() || ! isDisposable() )
213 m_pDisposer
->release();
217 uno::Reference
< XPlugin
> xProtection( this );
218 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
219 xPS
->removePropertyChangeListener( OUString(), this );
221 Guard
< Mutex
> aPluginGuard( ::PluginManager::get().getPluginMutex() );
222 rList
.remove( this );
224 m_aNPWindow
.window
= NULL
;
226 // acrobat does an unconditional XtParent on the windows widget
227 getPluginComm()->NPP_SetWindow( this );
230 PluginControl_Impl::dispose();
234 void XPlugin_Impl::dispose() throw(std::exception
)
236 Guard
< Mutex
> aGuard( m_aMutex
);
238 if (m_bIsDisposed
|| !getPluginComm())
240 m_bIsDisposed
= true;
243 secondLevelDispose( this );
246 m_pDisposer
= new PluginDisposer( this );
247 m_pDisposer
->acquire();
251 void XPlugin_Impl::initArgs( const Sequence
< OUString
>& argn
,
252 const Sequence
< OUString
>& argv
,
255 m_aPluginMode
= mode
;
257 m_nArgs
= argn
.getLength();
258 m_pArgn
= new const char*[m_nArgs
];
259 m_pArgv
= new const char*[m_nArgs
];
260 const OUString
* pUArgn
= argn
.getConstArray();
261 const OUString
* pUArgv
= argv
.getConstArray();
262 for( int i
= 0; i
< m_nArgs
; i
++ )
265 OUStringToOString( pUArgn
[i
], m_aEncoding
).getStr()
268 OUStringToOString( pUArgv
[i
], m_aEncoding
).getStr()
273 void XPlugin_Impl::freeArgs()
279 free( (void*)m_pArgn
[m_nArgs
] );
280 free( (void*)m_pArgv
[m_nArgs
] );
287 void XPlugin_Impl::prependArg( const char* pName
, const char* pValue
)
289 const char** pNewNames
= new const char*[m_nArgs
+1];
290 const char** pNewValues
= new const char*[m_nArgs
+1];
292 pNewNames
[0] = strdup( pName
);
293 pNewValues
[0] = strdup( pValue
);
294 for( int nIndex
= 0; nIndex
< m_nArgs
; ++nIndex
)
296 pNewNames
[nIndex
+1] = m_pArgn
[nIndex
];
297 pNewValues
[nIndex
+1]= m_pArgv
[nIndex
];
304 m_pArgv
= pNewValues
;
305 // set new number of arguments
307 #if OSL_DEBUG_LEVEL > 1
308 fprintf( stderr
, "inserted %s=%s\n", pNewNames
[0], pNewValues
[0] );
312 void XPlugin_Impl::handleSpecialArgs()
314 // special handling for real audio which needs a lot of parameters
315 // or won't function at all
316 if( m_aDescription
.Mimetype
== "audio/x-pn-realaudio-plugin" && m_nArgs
< 1 )
323 uno::Reference
< XPropertySet
> xProp( m_xModel
, UNO_QUERY
);
324 Any aProp
= xProp
->getPropertyValue("URL");
327 catch(const UnknownPropertyException
&)
332 if( !aURL
.isEmpty() )
334 // set new args, old args need not be freed as there were none set
336 m_pArgn
= new const char*[m_nArgs
];
337 m_pArgv
= new const char*[m_nArgs
];
340 m_pArgn
[0] = strdup( "SRC" );
341 m_pArgv
[0] = strdup( OUStringToOString( aURL
, m_aEncoding
).getStr() );
343 m_pArgn
[1] = strdup( "WIDTH" );
344 m_pArgv
[1] = strdup( "200" );
346 m_pArgn
[2] = strdup( "HEIGHT" );
347 m_pArgv
[2] = strdup( "200" );
349 m_pArgn
[3] = strdup( "CONTROLS" );
350 m_pArgv
[3] = strdup( "PlayButton,StopButton,ImageWindow" );
352 m_pArgn
[4] = strdup( "AUTOSTART" );
353 m_pArgv
[4] = strdup( "TRUE" );
355 m_pArgn
[5] = strdup( "NOJAVA" );
356 m_pArgv
[5] = strdup( "TRUE" );
359 // #69333# special for pdf
360 else if( m_aDescription
.Mimetype
== "application/pdf" )
361 m_aPluginMode
= PluginMode::FULL
;
363 // see if we have a TYPE tag
365 for( nIndex
= 0; nIndex
< m_nArgs
; ++nIndex
)
366 if( m_pArgn
[nIndex
][0] == 'T' &&
367 m_pArgn
[nIndex
][1] == 'Y' &&
368 m_pArgn
[nIndex
][2] == 'P' &&
369 m_pArgn
[nIndex
][3] == 'E' &&
370 m_pArgn
[nIndex
][4] == 0 )
372 if( nIndex
>= m_nArgs
)
375 prependArg( "TYPE", OUStringToOString( m_aDescription
.Mimetype
, m_aEncoding
).getStr() );
378 // see if we have a SRC tag
379 for( nIndex
= 0; nIndex
< m_nArgs
; ++nIndex
)
380 if( m_pArgn
[nIndex
][0] == 'S' &&
381 m_pArgn
[nIndex
][1] == 'R' &&
382 m_pArgn
[nIndex
][2] == 'C' &&
383 m_pArgn
[nIndex
][3] == 0 )
385 if( nIndex
>= m_nArgs
)
387 // need a SRC parameter (as all browser set one on the plugin
393 uno::Reference
< XPropertySet
> xProp( m_xModel
, UNO_QUERY
);
394 Any aProp
= xProp
->getPropertyValue("URL");
397 catch(const UnknownPropertyException
&)
402 if( !aURL
.isEmpty() )
405 prependArg( "SRC", OUStringToOString( aURL
, m_aEncoding
).getStr() );
410 void XPlugin_Impl::initInstance( const PluginDescription
& rDescription
,
411 const Sequence
< OUString
>& argn
,
412 const Sequence
< OUString
>& argv
,
415 Guard
< Mutex
> aGuard( m_aMutex
);
417 m_aDescription
= rDescription
;
418 initArgs( argn
, argv
, mode
);
422 void XPlugin_Impl::initInstance( const OUString
& rURL
,
423 const Sequence
< OUString
>& argn
,
424 const Sequence
< OUString
>& argv
,
427 Guard
< Mutex
> aGuard( m_aMutex
);
429 initArgs( argn
, argv
, mode
);
430 m_aDescription
= fitDescription( rURL
);
432 m_xModel
= new PluginModel( rURL
, m_aDescription
.Mimetype
);
436 void XPlugin_Impl::modelChanged()
438 Guard
< Mutex
> aGuard( m_aMutex
);
440 m_nProvidingState
= PROVIDING_MODEL_UPDATE
;
442 m_aDescription
= fitDescription( getCreationURL() );
444 if( m_aDescription
.Mimetype
.isEmpty() )
446 m_nProvidingState
= PROVIDING_NONE
;
450 OUString aURL
= getCreationURL();
451 provideNewStream( m_aDescription
.Mimetype
,
452 uno::Reference
< XActiveDataSource
>(),
454 0, 0, aURL
.startsWith("file:") );
455 m_nProvidingState
= PROVIDING_NONE
;
458 OUString
XPlugin_Impl::getCreationURL()
460 Guard
< Mutex
> aGuard( m_aMutex
);
463 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
466 Any aValue
= xPS
->getPropertyValue("URL");
473 sal_Bool
XPlugin_Impl::setModel( const uno::Reference
< com::sun::star::awt::XControlModel
> & Model
)
474 throw( RuntimeException
, std::exception
)
476 Guard
< Mutex
> aGuard( m_aMutex
);
478 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( Model
, UNO_QUERY
);
482 if( !getCreationURL().isEmpty() )
486 xPS
->addPropertyChangeListener( OUString(), this );
492 void XPlugin_Impl::createPeer( const uno::Reference
< com::sun::star::awt::XToolkit
> & xToolkit
, const uno::Reference
< com::sun::star::awt::XWindowPeer
> & Parent
)
493 throw( RuntimeException
, std::exception
)
495 Guard
< Mutex
> aGuard( m_aMutex
);
500 throw RuntimeException();
501 PluginControl_Impl::createPeer( xToolkit
, Parent
);
505 void XPlugin_Impl::loadPlugin()
507 Guard
< Mutex
> aGuard( m_aMutex
);
509 std::list
<PluginComm
*>::iterator iter
;
510 for( iter
= ::PluginManager::get().getPluginComms().begin();
511 iter
!= ::PluginManager::get().getPluginComms().end(); ++iter
)
513 if( OStringToOUString( (*iter
)->getLibName(), m_aEncoding
) == m_aDescription
.PluginName
)
515 setPluginComm( *iter
);
519 const SystemEnvData
* pEnvData
= getSysChildSysData();
520 #if defined( UNX ) && !(defined(MACOSX))
521 if (pEnvData
->pDisplay
) // headless?
523 XSync( static_cast<Display
*>(pEnvData
->pDisplay
), False
);
526 if( ! getPluginComm() )
528 if( !m_aDescription
.PluginName
.isEmpty() )
531 PluginComm
* pComm
= new MacPluginComm( m_aDescription
.Mimetype
,
532 m_aDescription
.PluginName
,
533 pEnvData
->mpNSView
);
535 // need a new PluginComm
536 PluginComm
* pComm
= NULL
;
538 if( !socketpair( AF_UNIX
, SOCK_STREAM
, 0, sv
) )
539 pComm
= new UnxPluginComm( m_aDescription
.Mimetype
,
540 m_aDescription
.PluginName
,
541 (Window
)pEnvData
->aWindow
,
546 SAL_WARN_IF( !pComm
, "extensions.plugin", "no PluginComm");
551 PluginComm
* pComm
= new PluginComm_Impl( m_aDescription
.Mimetype
,
552 m_aDescription
.PluginName
,
553 (HWND
)pEnvData
->hWnd
);
556 setPluginComm( pComm
);
563 NPP_New( const_cast<char*>(OUStringToOString( m_aDescription
.Mimetype
,
564 m_aEncoding
).getStr()),
566 m_aPluginMode
== PluginMode::FULL
? NP_FULL
: NP_EMBED
,
567 ::sal::static_int_cast
< int16_t, int >( m_nArgs
),
568 (char**)(m_nArgs
? m_pArgn
: NULL
),
569 (char**)(m_nArgs
? m_pArgv
: NULL
),
572 // m_aNPWindow is set up in the MacPluginComm from the view
573 SetSysPlugDataParentView(*pEnvData
);
575 if (pEnvData
->pDisplay
) // headless?
577 XSync( static_cast<Display
*>(pEnvData
->pDisplay
), False
);
578 m_aNPWindow
.window
= reinterpret_cast<void*>(pEnvData
->aWindow
);
582 m_aNPWindow
.window
= NULL
;
584 m_aNPWindow
.ws_info
= NULL
;
586 m_aNPWindow
.window
= (void*)pEnvData
->hWnd
;
588 com::sun::star::awt::Rectangle aPosSize
= getPosSize();
590 for( int i
= 0; i
< m_nArgs
; i
++ )
592 OString
aName( m_pArgn
[i
] );
593 if( aName
.equalsIgnoreAsciiCase( "width" ) )
595 OString
aValue( m_pArgv
[i
] );
596 aPosSize
.Width
= aValue
.toInt32();
598 else if( aName
.equalsIgnoreAsciiCase( "height" ) )
600 OString
aValue( m_pArgv
[i
] );
601 aPosSize
.Height
= aValue
.toInt32();
605 m_aNPWindow
.clipRect
.top
= 0;
606 m_aNPWindow
.clipRect
.left
= 0;
607 m_aNPWindow
.clipRect
.bottom
= ::sal::static_int_cast
< uint16_t, sal_Int32
>( aPosSize
.Height
);
608 m_aNPWindow
.clipRect
.right
= ::sal::static_int_cast
< uint16_t, sal_Int32
>( aPosSize
.Width
);
609 m_aNPWindow
.type
= NPWindowTypeWindow
;
613 m_aNPWindow
.width
= aPosSize
.Width
? aPosSize
.Width
: 600;
614 m_aNPWindow
.height
= aPosSize
.Height
? aPosSize
.Height
: 600;
616 getPluginComm()->NPP_SetWindow( this );
619 void XPlugin_Impl::destroyStreams()
621 Guard
< Mutex
> aGuard( m_aMutex
);
623 // streams remove themselves from this list when deleted
624 while( m_aOutputStreams
.size() )
625 delete *m_aOutputStreams
.begin();
627 // input streams are XOutputStreams, they cannot be simply deleted
628 std::list
<PluginInputStream
*> aLocalList( m_aInputStreams
);
629 for( std::list
<PluginInputStream
*>::iterator it
= aLocalList
.begin();
630 it
!= aLocalList
.end(); ++it
)
631 (*it
)->setMode( -1 );
634 PluginStream
* XPlugin_Impl::getStreamFromNPStream( NPStream
* stream
)
636 Guard
< Mutex
> aGuard( m_aMutex
);
638 std::list
<PluginInputStream
*>::iterator iter
;
639 for( iter
= m_aInputStreams
.begin(); iter
!= m_aInputStreams
.end(); ++iter
)
640 if( &(*iter
)->getStream() == stream
)
643 std::list
<PluginOutputStream
*>::iterator iter2
;
644 for( iter2
= m_aOutputStreams
.begin(); iter2
!= m_aOutputStreams
.end(); ++iter2
)
645 if( &(*iter2
)->getStream() == stream
)
651 sal_Bool
XPlugin_Impl::provideNewStream(const OUString
& mimetype
,
652 const uno::Reference
< com::sun::star::io::XActiveDataSource
> & stream
,
653 const OUString
& url
, sal_Int32 length
,
654 sal_Int32 lastmodified
, sal_Bool isfile
) throw(std::exception
)
657 Guard
< Mutex
> aGuard( m_aMutex
);
660 if( m_nProvidingState
!= PROVIDING_NONE
)
662 m_nProvidingState
= PROVIDING_NOW
;
665 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
670 xPS
->setPropertyValue("URL", aAny
);
672 xPS
->setPropertyValue("TYPE", aAny
);
679 m_nProvidingState
= PROVIDING_NOW
;
682 if( !mimetype
.isEmpty() )
683 aMIME
= OUStringToOString( mimetype
, m_aEncoding
);
685 aMIME
= OUStringToOString( m_aDescription
.Mimetype
, m_aEncoding
);
687 OString aURL
= OUStringToOString( url
, m_aEncoding
);
689 // check whether there is a notifylistener for this stream
690 // this means that the strema is created from the plugin
691 // via NPN_GetURLNotify or NPN_PostURLNotify
692 std::list
<PluginEventListener
*>::iterator iter
;
693 for( iter
= m_aPEventListeners
.begin();
694 iter
!= m_aPEventListeners
.end();
697 if( (*iter
)->getNormalizedURL() == aURL
)
699 aURL
= (*iter
)->getURL();
704 if( ! m_pPluginComm
)
707 if( !m_aLastGetUrl
.isEmpty() && m_aLastGetUrl
== aURL
)
709 // plugin is pulling data, don't push the same stream;
710 // this complicated method could have been avoided if
711 // all plugins respected the SRC parameter; but e.g.
712 // acrobat reader plugin does not
713 m_nProvidingState
= PROVIDING_NONE
;
717 if( ! m_pPluginComm
)
721 // this is valid if the plugin is supposed to
722 // pull data (via e.g. NPN_GetURL)
725 // set mimetype on model
727 uno::Reference
< com::sun::star::beans::XPropertySet
> xPS( m_xModel
, UNO_QUERY
);
733 aAny
<<= m_aDescription
.Mimetype
;
734 xPS
->setPropertyValue("TYPE", aAny
);
742 // there may be plugins that can use the file length information,
743 // but currently none are known. Since this file opening/seeking/closing
744 // is rather costly, it is not implemented. If there are plugins known to
745 // make use of the file length, simply put it in
747 PluginInputStream
* pStream
= new PluginInputStream( this, aURL
.getStr(),
748 length
, lastmodified
);
749 uno::Reference
< com::sun::star::io::XOutputStream
> xNewStream( pStream
);
751 if( iter
!= m_aPEventListeners
.end() )
752 pStream
->getStream().notifyData
= (*iter
)->getNotifyData();
756 // special handling acrobat reader
757 // presenting a seekable stream to it does not seem to work correctly
758 if( aMIME
.equals( "application/pdf" ) )
761 #if OSL_DEBUG_LEVEL > 1
763 "new stream \"%s\" of MIMEType \"%s\"\n"
764 "for plugin \"%s\"\n"
765 "seekable = %s, length = %" SAL_PRIdINT32
"\n",
766 aURL
.getStr(), aMIME
.getStr(), getPluginComm()->getLibName().getStr(),
767 isfile
? "true" : "false", length
);
770 if( ! m_pPluginComm
->NPP_NewStream( &m_aInstance
,
771 const_cast<char*>(aMIME
.getStr()),
772 &pStream
->getStream(), isfile
,
775 #if OSL_DEBUG_LEVEL > 1
779 case NP_NORMAL
: pType
= "NP_NORMAL";break;
780 case NP_SEEK
: pType
= "NP_SEEK";break;
781 case NP_ASFILE
: pType
= "NP_ASFILE";break;
782 case NP_ASFILEONLY
: pType
= "NP_ASFILEONLY";break;
783 default: pType
= "unknown!!!";
785 fprintf( stderr
, "Plugin wants it in Mode %s\n", pType
);
787 if( isfile
&& stype
== NP_ASFILEONLY
)
790 if( url
.startsWith("file:") )
793 osl_getSystemPathFromFileURL( url
.pData
, &aSysName
.pData
);
794 aFileName
= OUStringToOString( aSysName
, m_aEncoding
);
797 aFileName
= OUStringToOString( url
, m_aEncoding
);
799 NPP_StreamAsFile( &m_aInstance
,
800 &pStream
->getStream(),
801 aFileName
.getStr() );
805 pStream
->setMode( stype
);
809 // stream has to be loaded by PluginStream itself via UCB
814 uno::Reference
< com::sun::star::io::XConnectable
> xConnectable( stream
, UNO_QUERY
);
815 pStream
->setPredecessor( xConnectable
);
816 if( xConnectable
.is() )
818 xConnectable
->setSuccessor( static_cast< com::sun::star::io::XConnectable
* >(pStream
) );
819 while( xConnectable
->getPredecessor().is() )
820 xConnectable
= xConnectable
->getPredecessor();
822 stream
->setOutputStream( xNewStream
);
823 pStream
->setSource( stream
);
824 uno::Reference
< com::sun::star::io::XActiveDataControl
> xController
;
825 if( xConnectable
.is() )
826 xController
= uno::Reference
< com::sun::star::io::XActiveDataControl
>( xConnectable
, UNO_QUERY
);
828 xController
= uno::Reference
< com::sun::star::io::XActiveDataControl
>( stream
, UNO_QUERY
);
830 if( xController
.is() )
831 xController
->start();
837 m_nProvidingState
= PROVIDING_NONE
;
842 void XPlugin_Impl::disposing( const com::sun::star::lang::EventObject
& /*rSource*/ ) throw(std::exception
)
846 void XPlugin_Impl::propertyChange(const com::sun::star::beans::PropertyChangeEvent
& rEvent
)
847 throw (css::uno::RuntimeException
, std::exception
)
849 Guard
< Mutex
> aGuard( m_aMutex
);
851 if( rEvent
.PropertyName
== "URL" )
854 rEvent
.NewValue
>>= aStr
;
855 if( m_nProvidingState
== PROVIDING_NONE
)
866 void XPlugin_Impl::setPluginContext( const uno::Reference
< XPluginContext
> & rContext
)
868 m_rBrowserContext
= rContext
;
871 void XPlugin_Impl::setPosSize( sal_Int32 nX_
, sal_Int32 nY_
, sal_Int32 nWidth_
, sal_Int32 nHeight_
, sal_Int16 nFlags
)
872 throw( RuntimeException
, std::exception
)
874 Guard
< Mutex
> aGuard( m_aMutex
);
876 #if OSL_DEBUG_LEVEL > 1
877 fprintf( stderr
, "XPlugin_Impl::setPosSize( %" SAL_PRIdINT32
", %" SAL_PRIdINT32
", %" SAL_PRIdINT32
", %" SAL_PRIdINT32
", %d )\n",
878 nX_
, nY_
, nWidth_
, nHeight_
, nFlags
);
881 PluginControl_Impl::setPosSize(nX_
, nY_
, nWidth_
, nHeight_
, nFlags
);
885 m_aNPWindow
.width
= nWidth_
;
886 m_aNPWindow
.height
= nHeight_
;
887 m_aNPWindow
.clipRect
.top
= 0;
888 m_aNPWindow
.clipRect
.left
= 0;
889 m_aNPWindow
.clipRect
.right
= ::sal::static_int_cast
< uint16_t, sal_Int32
>( nWidth_
);
890 m_aNPWindow
.clipRect
.bottom
= ::sal::static_int_cast
< uint16_t, sal_Int32
>( nHeight_
);
892 if( getPluginComm() )
893 getPluginComm()->NPP_SetWindow( this );
896 PluginDescription
XPlugin_Impl::fitDescription( const OUString
& rURL
)
898 uno::Reference
< XPluginManager
> xPMgr( plugin::PluginManager::create(comphelper::getComponentContext(m_xSMgr
)) );
900 Sequence
< PluginDescription
> aDescrs
= xPMgr
->getPluginDescriptions();
901 const PluginDescription
* pDescrs
= aDescrs
.getConstArray();
903 for( int nArg
= 0; nArg
< m_nArgs
; nArg
++ )
905 if( strncmp( m_pArgn
[nArg
], "TYPE", 4 ) == 0 &&
906 m_pArgn
[nArg
][4] == 0 )
908 for( int i
= 0; i
< aDescrs
.getLength(); i
++ )
910 if( pDescrs
[i
].Mimetype
.equalsAscii( m_pArgv
[nArg
] ) )
916 int nPos
= rURL
.lastIndexOf( (sal_Unicode
)'.' );
919 OUString
const aExt
= rURL
.copy( nPos
).toAsciiLowerCase();
920 for( int i
= 0; i
< aDescrs
.getLength(); i
++ )
922 OUString aThisExt
= pDescrs
[ i
].Extension
.toAsciiLowerCase();
923 if( aThisExt
.indexOf( aExt
) != -1 )
929 return PluginDescription();
933 PluginStream::PluginStream( XPlugin_Impl
* pPlugin
,
934 const char* url
, sal_uInt32 len
, sal_uInt32 lastmod
)
935 : m_wPlugin(static_cast< ::cppu::OWeakObject
* >(pPlugin
))
939 memset( &m_aNPStream
, 0, sizeof( m_aNPStream
) );
940 m_aNPStream
.url
= strdup( url
);
941 m_aNPStream
.end
= len
;
942 m_aNPStream
.lastmodified
= lastmod
;
945 PluginStream::~PluginStream()
947 uno::Reference
<uno::XInterface
> const xPlugin(m_wPlugin
);
948 XPlugin_Impl
*const pPlugin(m_pPlugin
);
949 if (xPlugin
.is() && pPlugin
)
951 Guard
< Mutex
> aGuard( pPlugin
->getMutex() );
953 if( m_pPlugin
&& m_pPlugin
->getPluginComm() )
955 m_pPlugin
->getPluginComm()->NPP_DestroyStream( &m_pPlugin
->getNPPInstance(),
956 &m_aNPStream
, NPRES_DONE
);
957 m_pPlugin
->checkListeners( m_aNPStream
.url
);
958 m_pPlugin
->getPluginComm()->NPP_SetWindow( m_pPlugin
);
961 ::free( (void*)m_aNPStream
.url
);
964 PluginInputStream::PluginInputStream( XPlugin_Impl
* pPlugin
,
967 sal_uInt32 lastmod
) :
968 PluginStream( pPlugin
, url
, len
, lastmod
),
970 m_nMode( NP_NORMAL
),
974 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
976 m_pPlugin
->getInputStreams().push_back( this );
978 osl::FileBase::createTempFile( 0, 0, &aTmpFile
);
980 // set correct extension, some plugins need that
981 OUString
aName( m_aNPStream
.url
, strlen( m_aNPStream
.url
), m_pPlugin
->getTextEncoding() );
983 sal_Int32 nSepInd
= aName
.lastIndexOf('.');
986 aExtension
= aName
.copy( nSepInd
+ 1, aName
.getLength() - nSepInd
- 1 );
988 if( !aExtension
.isEmpty() )
990 aTmpFile
+= aExtension
;
992 m_aFileStream
.Open( aTmpFile
, StreamMode::READ
| StreamMode::WRITE
);
993 if( ! m_aFileStream
.IsOpen() )
995 // might be that the extension scrambled the whole filename
996 osl::FileBase::createTempFile( 0, 0, &aTmpFile
);
997 m_aFileStream
.Open( aTmpFile
, StreamMode::READ
| StreamMode::WRITE
);
1001 PluginInputStream::~PluginInputStream()
1003 OUString
aFile( m_aFileStream
.GetFileName() );
1005 m_aFileStream
.Close();
1007 uno::Reference
<uno::XInterface
> const xPlugin(m_wPlugin
);
1008 XPlugin_Impl
*const pPlugin(m_pPlugin
);
1009 if (xPlugin
.is() && pPlugin
)
1011 Guard
< Mutex
> aGuard( pPlugin
->getMutex() );
1013 pPlugin
->getInputStreams().remove( this );
1017 OString
aFileName(OUStringToOString(aFile
, m_pPlugin
->getTextEncoding()));
1018 if( m_pPlugin
->getPluginComm() && m_nMode
!= -1 )
1019 // mode -1 means either an error occurred,
1020 // or the plugin is already disposing
1022 m_pPlugin
->getPluginComm()->addFileToDelete( aFile
);
1023 if( m_nMode
== NP_ASFILE
)
1025 m_pPlugin
->getPluginComm()->
1026 NPP_StreamAsFile( &m_pPlugin
->getNPPInstance(),
1028 aFileName
.getStr() );
1030 m_pPlugin
->getPluginComm()->NPP_SetWindow( m_pPlugin
);
1031 m_pPlugin
->getInputStreams().remove( this );
1034 osl::File::remove( aFile
);
1037 osl::File::remove( aFile
);
1040 osl::File::remove( aFile
);
1045 PluginStreamType
PluginInputStream::getStreamType()
1050 void PluginInputStream::load()
1052 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
1055 aUrl
.SetSmartProtocol( INetProtocol::File
);
1057 OUString( getStream().url
,
1058 strlen( getStream().url
),
1059 RTL_TEXTENCODING_MS_1252
1064 new ::ucbhelper::Content(
1065 aUrl
.GetMainURL(INetURLObject::DECODE_TO_IURI
),
1066 uno::Reference
< com::sun::star::ucb::XCommandEnvironment
>(),
1067 comphelper::getProcessComponentContext()
1069 m_pContent
->openStream( static_cast< XOutputStream
* >( this ) );
1071 catch(const com::sun::star::uno::Exception
&)
1076 void PluginInputStream::setMode( sal_Int32 nMode
)
1078 assert(m_pPlugin
); // this is currently only called from two places...
1079 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
1083 // invalidation by plugin
1086 m_pPlugin
->getInputStreams().remove( this );
1092 void PluginInputStream::writeBytes( const Sequence
<sal_Int8
>& Buffer
) throw(std::exception
)
1094 uno::Reference
<uno::XInterface
> const xPlugin(m_wPlugin
);
1095 XPlugin_Impl
*const pPlugin(m_pPlugin
);
1096 if (!xPlugin
.is() || !pPlugin
)
1099 Guard
< Mutex
> aGuard( pPlugin
->getMutex() );
1101 m_aFileStream
.Seek( STREAM_SEEK_TO_END
);
1102 m_aFileStream
.Write( Buffer
.getConstArray(), Buffer
.getLength() );
1104 if( m_nMode
== NP_SEEK
)
1105 // hold reference, streem gets destroyed in NPN_DestroyStream
1108 if( m_nMode
== -1 || !m_pPlugin
->getPluginComm() )
1111 sal_Size nPos
= m_aFileStream
.Tell();
1112 sal_Size nBytes
= 0;
1113 while( m_nMode
!= NP_ASFILEONLY
&&
1114 m_nWritePos
< nPos
&&
1115 (nBytes
= m_pPlugin
->getPluginComm()-> NPP_WriteReady(
1116 &m_pPlugin
->getNPPInstance(), &m_aNPStream
)) > 0 )
1118 nBytes
= (nBytes
> nPos
- m_nWritePos
) ? nPos
- m_nWritePos
: nBytes
;
1120 boost::scoped_array
<char> pBuffer(new char[ nBytes
]);
1121 m_aFileStream
.Seek( m_nWritePos
);
1122 nBytes
= m_aFileStream
.Read( pBuffer
.get(), nBytes
);
1124 int32_t nBytesRead
= 0;
1127 nBytesRead
= m_pPlugin
->getPluginComm()->NPP_Write(
1128 &m_pPlugin
->getNPPInstance(), &m_aNPStream
, m_nWritePos
, nBytes
, pBuffer
.get() );
1135 if( nBytesRead
< 0 )
1141 m_nWritePos
+= nBytesRead
;
1145 void PluginInputStream::closeOutput() throw(std::exception
)
1147 uno::Reference
<uno::XInterface
> const xPlugin(m_wPlugin
);
1148 XPlugin_Impl
*const pPlugin(m_pPlugin
);
1149 if (!xPlugin
.is() || !pPlugin
)
1152 Guard
< Mutex
> aGuard( pPlugin
->getMutex() );
1155 m_xSource
= uno::Reference
< com::sun::star::io::XActiveDataSource
>();
1158 sal_uInt32
PluginInputStream::read( sal_uInt32 offset
, sal_Int8
* buffer
, sal_uInt32 size
)
1160 uno::Reference
<uno::XInterface
> const xPlugin(m_wPlugin
);
1161 XPlugin_Impl
*const pPlugin(m_pPlugin
);
1162 if (!xPlugin
.is() || !pPlugin
)
1165 Guard
< Mutex
> aGuard( pPlugin
->getMutex() );
1167 if( m_nMode
!= NP_SEEK
)
1170 m_aFileStream
.Seek( offset
);
1171 return m_aFileStream
.Read( buffer
, size
);
1174 void PluginInputStream::flush() throw(std::exception
)
1178 PluginOutputStream::PluginOutputStream( XPlugin_Impl
* pPlugin
,
1181 sal_uInt32 lastmod
) :
1182 PluginStream( pPlugin
, url
, len
, lastmod
),
1183 m_xStream( pPlugin
->getServiceManager()->createInstance("com.sun.star.io.DataOutputStream"), UNO_QUERY
)
1185 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
1187 m_pPlugin
->getOutputStreams().push_back( this );
1190 PluginOutputStream::~PluginOutputStream()
1192 Guard
< Mutex
> aGuard( m_pPlugin
->getMutex() );
1194 m_pPlugin
->getOutputStreams().remove( this );
1197 PluginStreamType
PluginOutputStream::getStreamType()
1199 return OutputStream
;
1202 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */