1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_svtools.hxx" 30 #include <com/sun/star/util/XCloseBroadcaster.hpp> 31 #include <com/sun/star/util/XCloseable.hpp> 32 #include <com/sun/star/lang/DisposedException.hpp> 33 #include <com/sun/star/lang/IllegalArgumentException.hpp> 34 #include <com/sun/star/frame/DoubleInitializationException.hpp> 35 #include <com/sun/star/frame/DoubleInitializationException.hpp> 36 #include <com/sun/star/beans/XPropertySet.hpp> 37 #include <com/sun/star/awt/XVclWindowPeer.hpp> 38 39 #include <vos/mutex.hxx> 40 #include <vcl/svapp.hxx> 41 #include <vcl/dialog.hxx> 42 #include <tools/link.hxx> 43 #include <toolkit/helper/vclunohelper.hxx> 44 45 #include "documentcloser.hxx" 46 47 using namespace ::com::sun::star; 48 49 50 // ==================================================================== 51 // MainThreadFrameCloserRequest 52 // ==================================================================== 53 54 class MainThreadFrameCloserRequest 55 { 56 uno::Reference< frame::XFrame > m_xFrame; 57 58 public: 59 MainThreadFrameCloserRequest( const uno::Reference< frame::XFrame >& xFrame ) 60 : m_xFrame( xFrame ) 61 {} 62 63 DECL_STATIC_LINK( MainThreadFrameCloserRequest, worker, MainThreadFrameCloserRequest* ); 64 65 static void Start( MainThreadFrameCloserRequest* pRequest ); 66 }; 67 68 // -------------------------------------------------------- 69 void MainThreadFrameCloserRequest::Start( MainThreadFrameCloserRequest* pMTRequest ) 70 { 71 if ( pMTRequest ) 72 { 73 if ( Application::GetMainThreadIdentifier() == osl_getThreadIdentifier( NULL ) ) 74 { 75 // this is the main thread 76 worker( NULL, pMTRequest ); 77 } 78 else 79 Application::PostUserEvent( STATIC_LINK( NULL, MainThreadFrameCloserRequest, worker ), pMTRequest ); 80 } 81 } 82 83 // -------------------------------------------------------- 84 IMPL_STATIC_LINK( MainThreadFrameCloserRequest, worker, MainThreadFrameCloserRequest*, pMTRequest ) 85 { 86 (void) pThis; // unused 87 if ( pMTRequest ) 88 { 89 if ( pMTRequest->m_xFrame.is() ) 90 { 91 // this is the main thread, the solar mutex must be locked 92 ::vos::OGuard aGuard( Application::GetSolarMutex() ); 93 94 try 95 { 96 uno::Reference< awt::XWindow > xWindow = pMTRequest->m_xFrame->getContainerWindow(); 97 uno::Reference< awt::XVclWindowPeer > xWinPeer( xWindow, uno::UNO_QUERY_THROW ); 98 99 xWindow->setVisible( sal_False ); 100 101 // reparent the window 102 xWinPeer->setProperty( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PluginParent" ) ), 103 uno::makeAny( (sal_Int64) 0 ) ); 104 105 Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); 106 if ( pWindow ) 107 Dialog::EndAllDialogs( pWindow ); 108 } 109 catch( uno::Exception& ) 110 { 111 // ignore all the errors 112 } 113 114 try 115 { 116 uno::Reference< util::XCloseable > xCloseable( pMTRequest->m_xFrame, uno::UNO_QUERY_THROW ); 117 xCloseable->close( sal_True ); 118 } 119 catch( uno::Exception& ) 120 { 121 // ignore all the errors 122 } 123 } 124 125 delete pMTRequest; 126 } 127 128 return 0; 129 } 130 131 132 // ==================================================================== 133 // ODocumentCloser 134 // ==================================================================== 135 136 // -------------------------------------------------------- 137 ODocumentCloser::ODocumentCloser( const uno::Reference< uno::XComponentContext >& xContext ) 138 : m_xContext( xContext ) 139 , m_pListenersContainer( NULL ) 140 , m_bDisposed( sal_False ) 141 , m_bInitialized( sal_False ) 142 { 143 } 144 145 // -------------------------------------------------------- 146 ODocumentCloser::~ODocumentCloser() 147 { 148 if ( m_pListenersContainer ) 149 { 150 delete m_pListenersContainer; 151 m_pListenersContainer = NULL; 152 } 153 } 154 155 // XComponent 156 // -------------------------------------------------------- 157 void SAL_CALL ODocumentCloser::dispose() 158 throw (uno::RuntimeException) 159 { 160 ::osl::MutexGuard aGuard( m_aMutex ); 161 162 if ( m_bDisposed ) 163 throw lang::DisposedException(); 164 165 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >(this) ); 166 if ( m_pListenersContainer ) 167 m_pListenersContainer->disposeAndClear( aSource ); 168 169 // TODO: trigger a main thread execution to close the frame 170 if ( m_xFrame.is() ) 171 { 172 // the created object will be deleted after thread execution 173 MainThreadFrameCloserRequest* pCloser = new MainThreadFrameCloserRequest( m_xFrame ); 174 MainThreadFrameCloserRequest::Start( pCloser ); 175 } 176 177 m_bDisposed = sal_True; 178 } 179 180 // -------------------------------------------------------- 181 void SAL_CALL ODocumentCloser::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) 182 throw (uno::RuntimeException) 183 { 184 ::osl::MutexGuard aGuard( m_aMutex ); 185 if ( m_bDisposed ) 186 throw lang::DisposedException(); // TODO 187 188 if ( !m_pListenersContainer ) 189 m_pListenersContainer = new ::cppu::OInterfaceContainerHelper( m_aMutex ); 190 191 m_pListenersContainer->addInterface( xListener ); 192 } 193 194 // -------------------------------------------------------- 195 void SAL_CALL ODocumentCloser::removeEventListener( const uno::Reference< lang::XEventListener >& xListener ) 196 throw (uno::RuntimeException) 197 { 198 ::osl::MutexGuard aGuard( m_aMutex ); 199 if ( m_pListenersContainer ) 200 m_pListenersContainer->removeInterface( xListener ); 201 } 202 203 // XInitialization 204 // -------------------------------------------------------- 205 void SAL_CALL ODocumentCloser::initialize( const uno::Sequence< uno::Any >& aArguments ) 206 throw (uno::Exception, uno::RuntimeException) 207 { 208 ::osl::MutexGuard aGuard( m_aMutex ); 209 if ( m_bInitialized ) 210 throw frame::DoubleInitializationException(); 211 212 if ( m_bDisposed ) 213 throw lang::DisposedException(); // TODO 214 215 if ( !m_refCount ) 216 throw uno::RuntimeException(); // the object must be refcounted already! 217 218 sal_Int32 nLen = aArguments.getLength(); 219 if ( nLen != 1 ) 220 throw lang::IllegalArgumentException( 221 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Wrong count of parameters!" ) ), 222 uno::Reference< uno::XInterface >(), 223 0 ); 224 225 if ( !( aArguments[0] >>= m_xFrame ) || !m_xFrame.is() ) 226 throw lang::IllegalArgumentException( 227 ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Nonempty reference is expected as the first argument!" ) ), 228 uno::Reference< uno::XInterface >(), 229 0 ); 230 231 m_bInitialized = sal_True; 232 } 233 234 235 // XServiceInfo 236 // -------------------------------------------------------- 237 ::rtl::OUString SAL_CALL ODocumentCloser::getImplementationName( ) 238 throw (uno::RuntimeException) 239 { 240 return impl_staticGetImplementationName(); 241 } 242 243 // -------------------------------------------------------- 244 ::sal_Bool SAL_CALL ODocumentCloser::supportsService( const ::rtl::OUString& ServiceName ) 245 throw (uno::RuntimeException) 246 { 247 uno::Sequence< ::rtl::OUString > aSeq = impl_staticGetSupportedServiceNames(); 248 249 for ( sal_Int32 nInd = 0; nInd < aSeq.getLength(); nInd++ ) 250 if ( ServiceName.compareTo( aSeq[nInd] ) == 0 ) 251 return sal_True; 252 253 return sal_False; 254 } 255 256 // -------------------------------------------------------- 257 uno::Sequence< ::rtl::OUString > SAL_CALL ODocumentCloser::getSupportedServiceNames() 258 throw (uno::RuntimeException) 259 { 260 return impl_staticGetSupportedServiceNames(); 261 } 262 263 // Static methods 264 // -------------------------------------------------------- 265 uno::Sequence< ::rtl::OUString > SAL_CALL ODocumentCloser::impl_staticGetSupportedServiceNames() 266 { 267 const rtl::OUString aServiceName( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.embed.DocumentCloser" ) ); 268 return uno::Sequence< rtl::OUString >( &aServiceName, 1 ); 269 } 270 271 // -------------------------------------------------------- 272 ::rtl::OUString SAL_CALL ODocumentCloser::impl_staticGetImplementationName() 273 { 274 return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.embed.DocumentCloser" ) ); 275 } 276 277 // -------------------------------------------------------- 278 uno::Reference< uno::XInterface > SAL_CALL ODocumentCloser::impl_staticCreateSelfInstance( 279 const uno::Reference< lang::XMultiServiceFactory >& xServiceManager ) 280 { 281 uno::Reference< uno::XComponentContext > xContext; 282 uno::Reference< beans::XPropertySet > xPropSet( xServiceManager, uno::UNO_QUERY ); 283 if ( xPropSet.is() ) 284 xPropSet->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ) >>= xContext; 285 286 if ( !xContext.is() ) 287 { 288 throw uno::RuntimeException( 289 rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unable to obtain component context from service manager!" ) ), 290 uno::Reference< uno::XInterface >() ); 291 } 292 293 return static_cast< cppu::OWeakObject * >( new ODocumentCloser( xContext ) ); 294 } 295 296