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