summaryrefslogtreecommitdiff
path: root/extensions/source/plugin/base/xplugin.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'extensions/source/plugin/base/xplugin.cxx')
-rw-r--r--extensions/source/plugin/base/xplugin.cxx1155
1 files changed, 1155 insertions, 0 deletions
diff --git a/extensions/source/plugin/base/xplugin.cxx b/extensions/source/plugin/base/xplugin.cxx
new file mode 100644
index 000000000000..b031df45e2af
--- /dev/null
+++ b/extensions/source/plugin/base/xplugin.cxx
@@ -0,0 +1,1155 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_extensions.hxx"
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/lang/XSingleServiceFactory.hpp>
+#include <com/sun/star/loader/XImplementationLoader.hpp>
+#include <com/sun/star/loader/CannotActivateFactoryException.hpp>
+
+#include <plugin/impl.hxx>
+#include <tools/fsys.hxx>
+#include <ucbhelper/content.hxx>
+#include <tools/urlobj.hxx>
+#include <tools/string.hxx>
+#include <vcl/svapp.hxx>
+#include <vos/timer.hxx>
+#include <osl/file.hxx>
+
+#ifdef UNX
+#include <sys/types.h>
+#include <sys/socket.h>
+#endif
+
+#if OSL_DEBUG_LEVEL > 1
+#include <stdio.h>
+#endif
+
+using namespace com::sun::star;
+using namespace com::sun::star::io;
+using namespace com::sun::star::beans;
+using namespace com::sun::star::plugin;
+using namespace rtl;
+using namespace osl;
+
+class PluginDisposer : public vos::OTimer
+{
+private:
+ XPlugin_Impl* m_pPlugin;
+
+ virtual void SAL_CALL onShot();
+public:
+ PluginDisposer( XPlugin_Impl* pPlugin ) :
+ OTimer( vos::TTimeValue( 2, 0 ),
+ vos::TTimeValue( 2, 0 ) ),
+ m_pPlugin( pPlugin )
+ { start(); }
+ ~PluginDisposer() {}
+};
+
+void PluginDisposer::onShot()
+{
+ if( m_pPlugin )
+ {
+ if( m_pPlugin->isDisposable() )
+ {
+ sal_uLong nEvent;
+ Application::PostUserEvent( nEvent, LINK( m_pPlugin, XPlugin_Impl, secondLevelDispose ), (void*)m_pPlugin );
+ }
+ }
+ else
+ release();
+}
+
+//==================================================================================================
+
+Any XPlugin_Impl::queryInterface( const Type& type ) throw( RuntimeException )
+{
+ return OWeakAggObject::queryInterface( type );
+}
+
+Any XPlugin_Impl::queryAggregation( const Type& type ) throw( RuntimeException )
+{
+ Any aRet( cppu::queryInterface( type, static_cast< XPlugin* >(this) ) );
+ if( ! aRet.hasValue() )
+ aRet = PluginControl_Impl::queryAggregation( type );
+ return aRet;
+}
+
+
+XPlugin_Impl::XPlugin_Impl( const uno::Reference< com::sun::star::lang::XMultiServiceFactory > & rSMgr) :
+ PluginControl_Impl(),
+ m_xSMgr( rSMgr ),
+ m_pPluginComm( NULL ),
+ m_aEncoding( gsl_getSystemTextEncoding() ),
+ m_pArgv( NULL ),
+ m_pArgn( NULL ),
+ m_nArgs( 0 ),
+ m_aPluginMode( NP_FULL ),
+ m_nProvidingState( PROVIDING_NONE ),
+ m_nCalledFromPlugin( 0 ),
+ m_pDisposer( NULL ),
+ m_bIsDisposed( sal_False )
+{
+ memset( &m_aInstance, 0, sizeof( m_aInstance ) );
+ memset( &m_aNPWindow, 0, sizeof( m_aNPWindow ) );
+ memset( &m_aSysPlugData, 0, sizeof( m_aSysPlugData ) );
+
+ m_xModel = new PluginModel();
+ uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
+ xPS->addPropertyChangeListener( OUString(), this );
+
+ Guard< Mutex > aGuard( PluginManager::get().getPluginMutex() );
+ PluginManager::get().getPlugins().push_back( this );
+}
+
+void XPlugin_Impl::destroyInstance()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ NPSavedData* pSavedData = NULL;
+
+ destroyStreams();
+ if( getPluginComm() )
+ {
+ getPluginComm()->NPP_Destroy( this, &pSavedData );
+ getPluginComm()->decRef();
+ m_pPluginComm = NULL;
+ }
+
+ freeArgs();
+
+ while( m_aPEventListeners.size() )
+ {
+ delete *m_aPEventListeners.begin();
+ m_aPEventListeners.pop_front();
+ }
+}
+
+XPlugin_Impl::~XPlugin_Impl()
+{
+ destroyInstance();
+}
+
+void XPlugin_Impl::checkListeners( const char* normalizedURL )
+{
+ if( ! normalizedURL )
+ return;
+
+ Guard< Mutex > aGuard( m_aMutex );
+
+ std::list<PluginEventListener*>::iterator iter;
+ for( iter = m_aPEventListeners.begin();
+ iter != m_aPEventListeners.end();
+ ++iter )
+ {
+ if( ! strcmp( normalizedURL, (*iter)->getURL() ) ||
+ ! strcmp( normalizedURL, (*iter)->getNormalizedURL() ) )
+ {
+ (*iter)->disposing( com::sun::star::lang::EventObject() );
+ delete *iter;
+ m_aPEventListeners.remove( *iter );
+ return;
+ }
+ }
+}
+
+IMPL_LINK( XPlugin_Impl, secondLevelDispose, XPlugin_Impl*, /*pThis*/ )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ // may have become undisposable between PostUserEvent and here
+ // or may have disposed and receive a second UserEvent
+ std::list<XPlugin_Impl*>& rList = PluginManager::get().getPlugins();
+ std::list<XPlugin_Impl*>::iterator iter;
+
+ {
+ Guard< Mutex > aPluginGuard( PluginManager::get().getPluginMutex() );
+ for( iter = rList.begin(); iter != rList.end(); ++iter )
+ {
+ if( *iter == this )
+ break;
+ }
+ if( iter == rList.end() || ! isDisposable() )
+ return 0;
+ }
+
+ if (m_pDisposer)
+ {
+ m_pDisposer->release();
+ m_pDisposer = NULL;
+ }
+
+ uno::Reference< XPlugin > xProtection( this );
+ uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
+ xPS->removePropertyChangeListener( OUString(), this );
+ {
+ Guard< Mutex > aPluginGuard( PluginManager::get().getPluginMutex() );
+ rList.remove( this );
+ }
+ m_aNPWindow.window = NULL;
+#ifndef UNX
+ // acrobat does an unconditional XtParent on the windows widget
+ getPluginComm()->NPP_SetWindow( this );
+#endif
+ destroyInstance();
+ PluginControl_Impl::dispose();
+ return 0;
+}
+
+void XPlugin_Impl::dispose() throw()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ if (m_bIsDisposed || !getPluginComm())
+ return;
+ m_bIsDisposed = sal_True;
+
+ if( isDisposable() )
+ secondLevelDispose( this );
+ else
+ {
+ m_pDisposer = new PluginDisposer( this );
+ m_pDisposer->acquire();
+ }
+}
+
+void XPlugin_Impl::initArgs( const Sequence< OUString >& argn,
+ const Sequence< OUString >& argv,
+ sal_Int16 mode )
+{
+ m_aPluginMode = mode;
+
+ m_nArgs = argn.getLength();
+ m_pArgn = new const char*[m_nArgs];
+ m_pArgv = new const char*[m_nArgs];
+ const OUString* pUArgn = argn.getConstArray();
+ const OUString* pUArgv = argv.getConstArray();
+ for( int i = 0; i < m_nArgs; i++ )
+ {
+ m_pArgn[i] = strdup(
+ OUStringToOString( pUArgn[i], m_aEncoding ).getStr()
+ );
+ m_pArgv[i] = strdup(
+ OUStringToOString( pUArgv[i], m_aEncoding ).getStr()
+ );
+ }
+}
+
+void XPlugin_Impl::freeArgs()
+{
+ if( m_nArgs > 0 )
+ {
+ for( ; m_nArgs--; )
+ {
+ free( (void*)m_pArgn[m_nArgs] );
+ free( (void*)m_pArgv[m_nArgs] );
+ }
+ delete [] m_pArgn;
+ delete [] m_pArgv;
+ }
+}
+
+void XPlugin_Impl::prependArg( const char* pName, const char* pValue )
+{
+ const char** pNewNames = new const char*[m_nArgs+1];
+ const char** pNewValues = new const char*[m_nArgs+1];
+
+ pNewNames[0] = strdup( pName );
+ pNewValues[0] = strdup( pValue );
+ for( int nIndex = 0; nIndex < m_nArgs; ++nIndex )
+ {
+ pNewNames[nIndex+1] = m_pArgn[nIndex];
+ pNewValues[nIndex+1]= m_pArgv[nIndex];
+ }
+ // free old arrays
+ delete [] m_pArgn;
+ delete [] m_pArgv;
+ // set new arrays
+ m_pArgn = pNewNames;
+ m_pArgv = pNewValues;
+ // set new number of arguments
+ m_nArgs++;
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "inserted %s=%s\n", pNewNames[0], pNewValues[0] );
+#endif
+}
+
+void XPlugin_Impl::handleSpecialArgs()
+{
+ // special handling for real audio which needs a lot of parameters
+ // or won't function at all
+ if( ! m_aDescription.Mimetype.compareToAscii( "audio/x-pn-realaudio-plugin" ) && m_nArgs < 1 )
+ {
+ OUString aURL;
+ if( m_xModel.is() )
+ {
+ try
+ {
+ uno::Reference< XPropertySet > xProp( m_xModel, UNO_QUERY );
+ Any aProp = xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) );
+ aProp >>= aURL;
+ }
+ catch( UnknownPropertyException )
+ {
+ }
+ }
+
+ if( aURL.getLength() )
+ {
+ // set new args, old args need not be freed as there were none set
+ m_nArgs = 6;
+ m_pArgn = new const char*[m_nArgs];
+ m_pArgv = new const char*[m_nArgs];
+
+ // SRC
+ m_pArgn[0] = strdup( "SRC" );
+ m_pArgv[0] = strdup( OUStringToOString( aURL, m_aEncoding ).getStr() );
+ // WIDTH
+ m_pArgn[1] = strdup( "WIDTH" );
+ m_pArgv[1] = strdup( "200" );
+ // HEIGHT
+ m_pArgn[2] = strdup( "HEIGHT" );
+ m_pArgv[2] = strdup( "200" );
+ // CONTROLS
+ m_pArgn[3] = strdup( "CONTROLS" );
+ m_pArgv[3] = strdup( "PlayButton,StopButton,ImageWindow" );
+ // AUTOSTART
+ m_pArgn[4] = strdup( "AUTOSTART" );
+ m_pArgv[4] = strdup( "TRUE" );
+ // NOJAVA
+ m_pArgn[5] = strdup( "NOJAVA" );
+ m_pArgv[5] = strdup( "TRUE" );
+ }
+ }
+ // #69333# special for pdf
+ else if( ! m_aDescription.Mimetype.compareToAscii( "application/pdf" ) )
+ m_aPluginMode = PluginMode::FULL;
+
+ // see if we have a TYPE tag
+ int nIndex;
+ for( nIndex = 0; nIndex < m_nArgs; ++nIndex )
+ if( m_pArgn[nIndex][0] == 'T' &&
+ m_pArgn[nIndex][1] == 'Y' &&
+ m_pArgn[nIndex][2] == 'P' &&
+ m_pArgn[nIndex][3] == 'E' &&
+ m_pArgn[nIndex][4] == 0 )
+ break;
+ if( nIndex >= m_nArgs )
+ {
+ // TYPE
+ prependArg( "TYPE", OUStringToOString( m_aDescription.Mimetype, m_aEncoding ).getStr() );
+ }
+
+ // see if we have a SRC tag
+ for( nIndex = 0; nIndex < m_nArgs; ++nIndex )
+ if( m_pArgn[nIndex][0] == 'S' &&
+ m_pArgn[nIndex][1] == 'R' &&
+ m_pArgn[nIndex][2] == 'C' &&
+ m_pArgn[nIndex][3] == 0 )
+ break;
+ if( nIndex >= m_nArgs )
+ {
+ // need a SRC parameter (as all browser set one on the plugin
+ OUString aURL;
+ if( m_xModel.is() )
+ {
+ try
+ {
+ uno::Reference< XPropertySet > xProp( m_xModel, UNO_QUERY );
+ Any aProp = xProp->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) );
+ aProp >>= aURL;
+ }
+ catch( UnknownPropertyException )
+ {
+ }
+ }
+
+ if( aURL.getLength() )
+ {
+ // SRC
+ prependArg( "SRC", OUStringToOString( aURL, m_aEncoding ).getStr() );
+ }
+ }
+}
+
+void XPlugin_Impl::initInstance( const PluginDescription& rDescription,
+ const Sequence< OUString >& argn,
+ const Sequence< OUString >& argv,
+ sal_Int16 mode )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ m_aDescription = rDescription;
+ initArgs( argn, argv, mode );
+ handleSpecialArgs();
+}
+
+void XPlugin_Impl::initInstance( const OUString& rURL,
+ const Sequence< OUString >& argn,
+ const Sequence< OUString >& argv,
+ sal_Int16 mode )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ initArgs( argn, argv, mode );
+ m_aDescription = fitDescription( rURL );
+
+ m_xModel = new PluginModel( rURL, m_aDescription.Mimetype );
+ handleSpecialArgs();
+}
+
+void XPlugin_Impl::modelChanged()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ m_nProvidingState = PROVIDING_MODEL_UPDATE;
+
+ destroyInstance();
+
+ m_aDescription = fitDescription( getCreationURL() );
+ if( !m_aDescription.Mimetype.getLength() )
+ {
+ m_nProvidingState = PROVIDING_NONE;
+ return;
+ }
+
+ OUString aURL = getCreationURL();
+ provideNewStream( m_aDescription.Mimetype,
+ uno::Reference< XActiveDataSource >(),
+ aURL,
+ 0, 0, (sal_Bool)(aURL.compareToAscii( "file:", 5 ) == 0) );
+ m_nProvidingState = PROVIDING_NONE;
+}
+
+OUString XPlugin_Impl::getCreationURL()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ OUString aRet;
+ uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
+ if( xPS.is() )
+ {
+ Any aValue = xPS->getPropertyValue( OUString::createFromAscii( "URL" ) );
+ aValue >>= aRet;
+ }
+ return aRet;
+}
+
+
+sal_Bool XPlugin_Impl::setModel( const uno::Reference< com::sun::star::awt::XControlModel > & Model )
+ throw( RuntimeException )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ uno::Reference< com::sun::star::beans::XPropertySet > xPS( Model, UNO_QUERY );
+ if( ! xPS.is() )
+ return sal_False;
+
+ if( getCreationURL().getLength() )
+ {
+ m_xModel = Model;
+ modelChanged();
+ xPS->addPropertyChangeListener( OUString(), this );
+ return sal_True;
+ }
+ return sal_False;
+}
+
+void XPlugin_Impl::createPeer( const uno::Reference< com::sun::star::awt::XToolkit > & xToolkit, const uno::Reference< com::sun::star::awt::XWindowPeer > & Parent )
+ throw( RuntimeException )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ if( ! _xPeer.is() )
+ {
+ if( ! Parent.is() )
+ throw RuntimeException();
+ PluginControl_Impl::createPeer( xToolkit, Parent );
+ }
+}
+
+void XPlugin_Impl::loadPlugin()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ std::list<PluginComm*>::iterator iter;
+ for( iter = PluginManager::get().getPluginComms().begin();
+ iter != PluginManager::get().getPluginComms().end(); ++iter )
+ {
+ if( OStringToOUString( (*iter)->getLibName(), m_aEncoding ) == m_aDescription.PluginName )
+ {
+ setPluginComm( *iter );
+ break;
+ }
+ }
+ const SystemEnvData* pEnvData = getSysChildSysData();
+#if defined( UNX ) && !(defined(QUARTZ))
+ XSync( (Display*)pEnvData->pDisplay, False );
+#endif
+ if( ! getPluginComm() )
+ {
+ if( m_aDescription.PluginName.getLength() )
+ {
+#if defined QUARTZ
+ PluginComm* pComm = new MacPluginComm( m_aDescription.Mimetype,
+ m_aDescription.PluginName,
+ pEnvData->pView );
+#elif defined UNX
+ // need a new PluginComm
+ PluginComm* pComm = NULL;
+ int sv[2];
+ if( !socketpair( AF_UNIX, SOCK_STREAM, 0, sv ) )
+ pComm = new UnxPluginComm( m_aDescription.Mimetype,
+ m_aDescription.PluginName,
+ (XLIB_Window)pEnvData->aWindow,
+ sv[0],
+ sv[1]
+ );
+#elif (defined WNT || defined OS2)
+ PluginComm* pComm = new PluginComm_Impl( m_aDescription.Mimetype,
+ m_aDescription.PluginName,
+ (HWND)pEnvData->hWnd );
+#endif
+ setPluginComm( pComm );
+ }
+ else
+ return;
+ }
+
+ NPError aError = getPluginComm()->
+ NPP_New( (char*)OUStringToOString( m_aDescription.Mimetype,
+ m_aEncoding).getStr(),
+ getNPPInstance(),
+ m_aPluginMode == PluginMode::FULL ? NP_FULL : NP_EMBED,
+ ::sal::static_int_cast< int16, int >( m_nArgs ),
+ (char**)(m_nArgs ? m_pArgn : NULL),
+ (char**)(m_nArgs ? m_pArgv : NULL),
+ NULL );
+#ifdef QUARTZ
+ // m_aNPWindow is set up in the MacPluginComm from the view
+ m_aSysPlugData.m_pParentView = pEnvData->pView;
+#elif defined( UNX )
+ XSync( (Display*)pEnvData->pDisplay, False );
+ m_aNPWindow.window = (void*)pEnvData->aWindow;
+ m_aNPWindow.ws_info = NULL;
+#else
+ m_aNPWindow.window = (void*)pEnvData->hWnd;
+#endif
+ com::sun::star::awt::Rectangle aPosSize = getPosSize();
+
+ for( int i = 0; i < m_nArgs; i++ )
+ {
+ OString aName( m_pArgn[i] );
+ if( aName.equalsIgnoreAsciiCase( "width" ) )
+ {
+ OString aValue( m_pArgv[i] );
+ aPosSize.Width = aValue.toInt32();
+ }
+ else if( aName.equalsIgnoreAsciiCase( "height" ) )
+ {
+ OString aValue( m_pArgv[i] );
+ aPosSize.Height = aValue.toInt32();
+ }
+ }
+
+ m_aNPWindow.clipRect.top = 0;
+ m_aNPWindow.clipRect.left = 0;
+ m_aNPWindow.clipRect.bottom = ::sal::static_int_cast< uint16, sal_Int32 >( aPosSize.Height );
+ m_aNPWindow.clipRect.right = ::sal::static_int_cast< uint16, sal_Int32 >( aPosSize.Width );
+ m_aNPWindow.type = NPWindowTypeWindow;
+
+ m_aNPWindow.x = 0;
+ m_aNPWindow.y = 0;
+ m_aNPWindow.width = aPosSize.Width ? aPosSize.Width : 600;
+ m_aNPWindow.height = aPosSize.Height ? aPosSize.Height : 600;
+
+ aError = getPluginComm()->NPP_SetWindow( this );
+}
+
+void XPlugin_Impl::destroyStreams()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ // streams remove themselves from this list when deleted
+ while( m_aOutputStreams.size() )
+ delete *m_aOutputStreams.begin();
+
+ // input streams are XOutputStreams, they cannot be simply deleted
+ std::list<PluginInputStream*> aLocalList( m_aInputStreams );
+ for( std::list<PluginInputStream*>::iterator it = aLocalList.begin();
+ it != aLocalList.end(); ++it )
+ (*it)->setMode( -1 );
+}
+
+PluginStream* XPlugin_Impl::getStreamFromNPStream( NPStream* stream )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ std::list<PluginInputStream*>::iterator iter;
+ for( iter = m_aInputStreams.begin(); iter != m_aInputStreams.end(); ++iter )
+ if( (*iter)->getStream() == stream )
+ return *iter;
+
+ std::list<PluginOutputStream*>::iterator iter2;
+ for( iter2 = m_aOutputStreams.begin(); iter2 != m_aOutputStreams.end(); ++iter2 )
+ if( (*iter2)->getStream() == stream )
+ return *iter2;
+
+ return NULL;
+}
+
+sal_Bool XPlugin_Impl::provideNewStream(const OUString& mimetype,
+ const uno::Reference< com::sun::star::io::XActiveDataSource > & stream,
+ const OUString& url, sal_Int32 length,
+ sal_Int32 lastmodified, sal_Bool isfile) throw()
+
+{
+ Guard< Mutex > aGuard( m_aMutex );
+ sal_Bool bRet = sal_False;
+
+ if( m_nProvidingState != PROVIDING_NONE )
+ {
+ m_nProvidingState = PROVIDING_NOW;
+ Any aAny;
+ aAny <<= url;
+ uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
+ if( xPS.is() )
+ {
+ try
+ {
+ xPS->setPropertyValue( OUString::createFromAscii( "URL" ), aAny );
+ aAny <<= mimetype;
+ xPS->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny );
+ }
+ catch(...)
+ {
+ }
+ }
+ }
+ m_nProvidingState = PROVIDING_NOW;
+
+ OString aMIME;
+ if( mimetype.getLength() )
+ aMIME = OUStringToOString( mimetype, m_aEncoding );
+ else
+ aMIME = OUStringToOString( m_aDescription.Mimetype, m_aEncoding );
+
+ OString aURL = OUStringToOString( url, m_aEncoding );
+
+ // check wether there is a notifylistener for this stream
+ // this means that the strema is created from the plugin
+ // via NPN_GetURLNotify or NPN_PostURLNotify
+ std::list<PluginEventListener*>::iterator iter;
+ for( iter = m_aPEventListeners.begin();
+ iter != m_aPEventListeners.end();
+ ++iter )
+ {
+ if( (*iter)->getNormalizedURL() == aURL )
+ {
+ aURL = (*iter)->getURL();
+ break;
+ }
+ }
+
+ if( ! m_pPluginComm )
+ {
+ loadPlugin();
+ if( m_aLastGetUrl.getLength() && m_aLastGetUrl == aURL )
+ {
+ // plugin is pulling data, don't push the same stream;
+ // this complicated method could have been avoided if
+ // all plugins respected the SRC parameter; but e.g.
+ // acrobat reader plugin does not
+ m_nProvidingState = PROVIDING_NONE;
+ return sal_True;
+ }
+ }
+ if( ! m_pPluginComm )
+ return sal_False;
+
+ if( ! url.getLength() )
+ // this is valid if the plugin is supposed to
+ // pull data (via e.g. NPN_GetURL)
+ return sal_True;
+
+ // set mimetype on model
+ {
+ uno::Reference< com::sun::star::beans::XPropertySet > xPS( m_xModel, UNO_QUERY );
+ if( xPS.is() )
+ {
+ try
+ {
+ Any aAny;
+ aAny <<= m_aDescription.Mimetype;
+ xPS->setPropertyValue( OUString::createFromAscii( "TYPE" ), aAny );
+ }
+ catch(...)
+ {
+ }
+ }
+ }
+
+ // there may be plugins that can use the file length information,
+ // but currently none are known. Since this file opening/seeking/closing
+ // is rather costly, it is #if'ed out. If there are plugins known to
+ // make use of the file length, simply put it in
+#if 0
+ if( isfile && ! length )
+ {
+ osl::File aFile( url );
+ if( aFile.open( OpenFlag_Read ) == FileBase::E_None )
+ {
+ aFile.setPos( Pos_End, 0 );
+ sal_uInt64 nPos = 0;
+ if( aFile.getPos( nPos ) == FileBase::E_None )
+ length = nPos;
+ aFile.close();
+ }
+ }
+#endif
+
+ PluginInputStream* pStream = new PluginInputStream( this, aURL.getStr(),
+ length, lastmodified );
+ uno::Reference< com::sun::star::io::XOutputStream > xNewStream( pStream );
+
+ if( iter != m_aPEventListeners.end() )
+ pStream->getStream()->notifyData = (*iter)->getNotifyData();
+
+ uint16 stype = 0;
+
+ // special handling acrobat reader
+ // presenting a seekable stream to it does not seem to work correctly
+ if( aMIME.equals( "application/pdf" ) )
+ isfile = sal_False;
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr,
+ "new stream \"%s\" of MIMEType \"%s\"\n"
+ "for plugin \"%s\"\n"
+ "seekable = %s, length = %"SAL_PRIdINT32"\n",
+ aURL.getStr(), aMIME.getStr(), getPluginComm()->getLibName().getStr(),
+ isfile ? "true" : "false", length );
+
+#endif
+ if( ! m_pPluginComm->NPP_NewStream( &m_aInstance,
+ (char*)aMIME.getStr(),
+ pStream->getStream(), isfile,
+ &stype ) )
+ {
+#if OSL_DEBUG_LEVEL > 1
+ const char* pType;
+ switch( stype )
+ {
+ case NP_NORMAL: pType = "NP_NORMAL";break;
+ case NP_SEEK: pType = "NP_SEEK";break;
+ case NP_ASFILE: pType = "NP_ASFILE";break;
+ case NP_ASFILEONLY: pType = "NP_ASFILEONLY";break;
+ default: pType = "unknown!!!";
+ }
+ fprintf( stderr, "Plugin wants it in Mode %s\n", pType );
+#endif
+ if( isfile && stype == NP_ASFILEONLY )
+ {
+ OString aFileName;
+ if( url.compareToAscii( "file:", 5 ) == 0 )
+ {
+ OUString aSysName;
+ osl_getSystemPathFromFileURL( url.pData, &aSysName.pData );
+ aFileName = OUStringToOString( aSysName, m_aEncoding );
+ }
+ else
+ aFileName = OUStringToOString( url, m_aEncoding );
+ m_pPluginComm->
+ NPP_StreamAsFile( &m_aInstance,
+ pStream->getStream(),
+ aFileName.getStr() );
+ }
+ else
+ {
+ pStream->setMode( stype );
+
+ if( ! stream.is() )
+ {
+ // stream has to be loaded by PluginStream itself via UCB
+ pStream->load();
+ }
+ else
+ {
+ uno::Reference< com::sun::star::io::XConnectable > xConnectable( stream, UNO_QUERY );
+ pStream->setPredecessor( xConnectable );
+ if( xConnectable.is() )
+ {
+ xConnectable->setSuccessor( static_cast< com::sun::star::io::XConnectable* >(pStream) );
+ while( xConnectable->getPredecessor().is() )
+ xConnectable = xConnectable->getPredecessor();
+ }
+ stream->setOutputStream( xNewStream );
+ pStream->setSource( stream );
+ uno::Reference< com::sun::star::io::XActiveDataControl > xController;
+ if( xConnectable.is() )
+ xController = uno::Reference< com::sun::star::io::XActiveDataControl >( xConnectable, UNO_QUERY );
+ else
+ xController = uno::Reference< com::sun::star::io::XActiveDataControl >( stream, UNO_QUERY );
+
+ if( xController.is() )
+ xController->start();
+ }
+ }
+ bRet = sal_True;
+ }
+
+ m_nProvidingState = PROVIDING_NONE;
+
+ return bRet;
+}
+
+void XPlugin_Impl::disposing( const com::sun::star::lang::EventObject& /*rSource*/ ) throw()
+{
+}
+
+void XPlugin_Impl::propertyChange( const com::sun::star::beans::PropertyChangeEvent& rEvent ) throw()
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+ if( ! rEvent.PropertyName.compareToAscii( "URL" ) )
+ {
+ OUString aStr;
+ rEvent.NewValue >>= aStr;
+ if( m_nProvidingState == PROVIDING_NONE )
+ {
+ if( aStr != m_aURL )
+ {
+ m_aURL = aStr;
+ modelChanged();
+ }
+ }
+ }
+}
+
+void XPlugin_Impl::setPluginContext( const uno::Reference< XPluginContext > & rContext )
+{
+ m_rBrowserContext = rContext;
+}
+
+void XPlugin_Impl::setPosSize( sal_Int32 nX_, sal_Int32 nY_, sal_Int32 nWidth_, sal_Int32 nHeight_, sal_Int16 nFlags )
+ throw( RuntimeException )
+{
+ Guard< Mutex > aGuard( m_aMutex );
+
+#if OSL_DEBUG_LEVEL > 1
+ fprintf( stderr, "XPlugin_Impl::setPosSize( %"SAL_PRIdINT32", %"SAL_PRIdINT32", %"SAL_PRIdINT32", %"SAL_PRIdINT32", %d )\n",
+ nX_, nY_, nWidth_, nHeight_, nFlags );
+#endif
+
+ PluginControl_Impl::setPosSize(nX_, nY_, nWidth_, nHeight_, nFlags);
+
+ m_aNPWindow.x = 0;
+ m_aNPWindow.y = 0;
+ m_aNPWindow.width = nWidth_;
+ m_aNPWindow.height = nHeight_;
+ m_aNPWindow.clipRect.top = 0;
+ m_aNPWindow.clipRect.left = 0;
+ m_aNPWindow.clipRect.right = ::sal::static_int_cast< uint16, sal_Int32 >( nWidth_ );
+ m_aNPWindow.clipRect.bottom = ::sal::static_int_cast< uint16, sal_Int32 >( nHeight_ );
+
+ if( getPluginComm() )
+ getPluginComm()->NPP_SetWindow( this );
+}
+
+PluginDescription XPlugin_Impl::fitDescription( const OUString& rURL )
+{
+ uno::Reference< XPluginManager > xPMgr( m_xSMgr->createInstance( OUString::createFromAscii( "com.sun.star.plugin.PluginManager" ) ), UNO_QUERY );
+ if( !xPMgr.is() )
+ {
+ m_nProvidingState = PROVIDING_NONE;
+ return PluginDescription();
+ }
+
+ Sequence< PluginDescription > aDescrs = xPMgr->getPluginDescriptions();
+ const PluginDescription* pDescrs = aDescrs.getConstArray();
+
+ for( int nArg = 0; nArg < m_nArgs; nArg++ )
+ {
+ if( strncmp( m_pArgn[nArg], "TYPE", 4 ) == 0 &&
+ m_pArgn[nArg][4] == 0 )
+ {
+ for( int i = 0; i < aDescrs.getLength(); i++ )
+ {
+ if( pDescrs[i].Mimetype.compareToAscii( m_pArgv[nArg] ) == 0 )
+ return pDescrs[i];
+ }
+ }
+ }
+
+ int nPos = rURL.lastIndexOf( (sal_Unicode)'.' );
+ OUString aExt = rURL.copy( nPos ).toAsciiLowerCase();
+ if( nPos != -1 )
+ {
+ for( int i = 0; i < aDescrs.getLength(); i++ )
+ {
+ OUString aThisExt = pDescrs[ i ].Extension.toAsciiLowerCase();
+ if( aThisExt.indexOf( aExt ) != -1 )
+ {
+ return pDescrs[i];
+ }
+ }
+ }
+ return PluginDescription();
+}
+
+
+PluginStream::PluginStream( XPlugin_Impl* pPlugin,
+ const char* url, sal_uInt32 len, sal_uInt32 lastmod ) :
+ m_pPlugin( pPlugin )
+{
+ memset( &m_aNPStream, 0, sizeof( m_aNPStream ) );
+ m_aNPStream.url = strdup( url );
+ m_aNPStream.end = len;
+ m_aNPStream.lastmodified = lastmod;
+}
+
+PluginStream::~PluginStream()
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ if( m_pPlugin && m_pPlugin->getPluginComm() )
+ {
+ m_pPlugin->getPluginComm()->NPP_DestroyStream( m_pPlugin->getNPPInstance(),
+ &m_aNPStream, NPRES_DONE );
+ m_pPlugin->checkListeners( m_aNPStream.url );
+ m_pPlugin->getPluginComm()->NPP_SetWindow( m_pPlugin );
+ }
+ ::free( (void*)m_aNPStream.url );
+}
+
+PluginInputStream::PluginInputStream( XPlugin_Impl* pPlugin,
+ const char* url,
+ sal_uInt32 len,
+ sal_uInt32 lastmod ) :
+ PluginStream( pPlugin, url, len, lastmod ),
+ m_pContent( NULL ),
+ m_nMode( NP_NORMAL ),
+ m_nWritePos( 0 )
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ m_pPlugin->getInputStreams().push_back( this );
+ DirEntry aEntry;
+ aEntry = aEntry.TempName();
+
+ // set correct extension, some plugins need that
+ DirEntry aName( String( m_aNPStream.url, m_pPlugin->getTextEncoding() ) );
+ String aExtension = aName.GetExtension();
+ if( aExtension.Len() )
+ aEntry.SetExtension( aExtension );
+ m_aFileStream.Open( aEntry.GetFull(), STREAM_READ | STREAM_WRITE );
+ if( ! m_aFileStream.IsOpen() )
+ {
+ // #74808# might be that the extension scrambled the whole filename
+ aEntry = aEntry.TempName();
+ m_aFileStream.Open( aEntry.GetFull(), STREAM_READ | STREAM_WRITE );
+ }
+}
+
+PluginInputStream::~PluginInputStream()
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ m_pPlugin->getInputStreams().remove( this );
+
+ String aFile( m_aFileStream.GetFileName() );
+
+ m_aFileStream.Close();
+ if( m_pPlugin )
+ {
+ ByteString aFileName( aFile, m_pPlugin->getTextEncoding() );
+ if( m_pPlugin->getPluginComm() && m_nMode != -1 )
+ // mode -1 means either an error occured,
+ // or the plugin is already disposing
+ {
+ m_pPlugin->getPluginComm()->addFileToDelete( aFile );
+ if( m_nMode == NP_ASFILE )
+ {
+ m_pPlugin->getPluginComm()->
+ NPP_StreamAsFile( m_pPlugin->getNPPInstance(),
+ &m_aNPStream,
+ aFileName.GetBuffer() );
+ }
+ m_pPlugin->getPluginComm()->NPP_SetWindow( m_pPlugin );
+ m_pPlugin->getInputStreams().remove( this );
+ }
+ else
+ DirEntry( m_aFileStream.GetFileName() ).Kill();
+ }
+ else
+ DirEntry( m_aFileStream.GetFileName() ).Kill();
+ if( m_pContent )
+ delete m_pContent;
+}
+
+PluginStreamType PluginInputStream::getStreamType()
+{
+ return InputStream;
+}
+
+void PluginInputStream::load()
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ INetURLObject aUrl;
+ aUrl.SetSmartProtocol( INET_PROT_FILE );
+ aUrl.SetSmartURL(
+ String( getStream()->url,
+ ::sal::static_int_cast< sal_uInt16, size_t >( strlen( getStream()->url ) ),
+ RTL_TEXTENCODING_MS_1252
+ ) );
+ try
+ {
+ m_pContent =
+ new ::ucbhelper::Content(
+ aUrl.GetMainURL(INetURLObject::DECODE_TO_IURI),
+ uno::Reference< com::sun::star::ucb::XCommandEnvironment >()
+ );
+ m_pContent->openStream( static_cast< XOutputStream* >( this ) );
+ }
+ catch( com::sun::star::uno::Exception )
+ {
+ }
+}
+
+void PluginInputStream::setMode( sal_Int32 nMode )
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ m_nMode = nMode;
+
+ // invalidation by plugin
+ if( m_nMode == -1 && m_pPlugin )
+ {
+ m_pPlugin->getInputStreams().remove( this );
+ m_pPlugin = NULL;
+ }
+}
+
+void PluginInputStream::writeBytes( const Sequence<sal_Int8>& Buffer ) throw()
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ m_aFileStream.Seek( STREAM_SEEK_TO_END );
+ m_aFileStream.Write( Buffer.getConstArray(), Buffer.getLength() );
+
+ if( m_nMode == NP_SEEK )
+ // hold reference, streem gets destroyed in NPN_DestroyStream
+ m_xSelf = this;
+
+ if( m_nMode == -1 || !m_pPlugin->getPluginComm() )
+ return;
+
+ sal_uInt32 nPos = m_aFileStream.Tell();
+ sal_uInt32 nBytes = 0;
+ while( m_nMode != NP_ASFILEONLY &&
+ m_nWritePos < nPos &&
+ (nBytes = m_pPlugin->getPluginComm()-> NPP_WriteReady(
+ m_pPlugin->getNPPInstance(), &m_aNPStream )) > 0 )
+ {
+ nBytes = (nBytes > nPos - m_nWritePos) ? nPos - m_nWritePos : nBytes;
+
+ char* pBuffer = new char[ nBytes ];
+ m_aFileStream.Seek( m_nWritePos );
+ nBytes = m_aFileStream.Read( pBuffer, nBytes );
+
+ int32 nBytesRead = 0;
+ try
+ {
+ nBytesRead = m_pPlugin->getPluginComm()->NPP_Write(
+ m_pPlugin->getNPPInstance(), &m_aNPStream, m_nWritePos, nBytes, pBuffer );
+ }
+ catch( ... )
+ {
+ nBytesRead = 0;
+ }
+ delete [] pBuffer;
+
+ if( nBytesRead < 0 )
+ {
+ m_nMode = -1;
+ return;
+ }
+
+ m_nWritePos += nBytesRead;
+ }
+}
+
+void PluginInputStream::closeOutput() throw()
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ flush();
+ m_xSource = uno::Reference< com::sun::star::io::XActiveDataSource >();
+}
+
+sal_uInt32 PluginInputStream::read( sal_uInt32 offset, sal_Int8* buffer, sal_uInt32 size )
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ if( m_nMode != NP_SEEK )
+ return 0;
+
+ m_aFileStream.Seek( offset );
+ return m_aFileStream.Read( buffer, size );
+}
+
+void PluginInputStream::flush(void) throw()
+{
+}
+
+PluginOutputStream::PluginOutputStream( XPlugin_Impl* pPlugin,
+ const char* url,
+ sal_uInt32 len,
+ sal_uInt32 lastmod ) :
+ PluginStream( pPlugin, url, len, lastmod ),
+ m_xStream( pPlugin->getServiceManager()->createInstance( OUString::createFromAscii( "com.sun.star.io.DataOutputStream" ) ), UNO_QUERY )
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ m_pPlugin->getOutputStreams().push_back( this );
+}
+
+PluginOutputStream::~PluginOutputStream()
+{
+ Guard< Mutex > aGuard( m_pPlugin->getMutex() );
+
+ m_pPlugin->getOutputStreams().remove( this );
+}
+
+PluginStreamType PluginOutputStream::getStreamType()
+{
+ return OutputStream;
+}
+