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