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_framework.hxx"
26 //_______________________________________________
27 // my own includes
28
29 #ifndef __FRAMEWORK_SERVICES_TYPEDETECTION_HXX_
30 #include <services/sessionlistener.hxx>
31 #endif
32 #include <threadhelp/readguard.hxx>
33 #include <threadhelp/resetableguard.hxx>
34 #include <protocols.h>
35 #include <services.h>
36
37 #include <osl/thread.h>
38
39
40 #include <vcl/svapp.hxx>
41 #include <tools/urlobj.hxx>
42 #include <tools/tempfile.hxx>
43 #include <unotools/tempfile.hxx>
44 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
45 #include <com/sun/star/lang/XComponent.hpp>
46 #include <com/sun/star/container/XNameAccess.hpp>
47 #include <com/sun/star/container/XNameContainer.hpp>
48 #include <com/sun/star/beans/NamedValue.hpp>
49 #include <com/sun/star/beans/PropertyValue.hpp>
50 #include <com/sun/star/beans/PropertyState.hpp>
51 #include <com/sun/star/beans/XPropertySet.hpp>
52 #include <com/sun/star/frame/XFramesSupplier.hpp>
53 #include <com/sun/star/frame/XStorable.hpp>
54 #include <com/sun/star/frame/XComponentLoader.hpp>
55 #include <com/sun/star/frame/XDispatch.hpp>
56 #include <com/sun/star/frame/XDesktop.hpp>
57 #include <com/sun/star/util/XModifiable.hpp>
58 #include <com/sun/star/util/XChangesBatch.hpp>
59 #include <com/sun/star/util/XURLTransformer.hpp>
60 #include <com/sun/star/util/URL.hpp>
61 #include <osl/time.h>
62 #include <comphelper/processfactory.hxx>
63 #include <unotools/pathoptions.hxx>
64 #include <unotools/internaloptions.hxx>
65 #include <stdio.h>
66 //_______________________________________________
67 // interface includes
68 #include <com/sun/star/uno/Any.hxx>
69
70 #include <com/sun/star/uno/Sequence.hxx>
71 //_______________________________________________
72 // includes of other projects
73
74 //_______________________________________________
75 // namespace
76
77 using namespace com::sun::star::uno;
78 using namespace com::sun::star::util;
79 using namespace com::sun::star::frame;
80 using namespace com::sun::star::lang;
81 using namespace com::sun::star::beans;
82 using namespace com::sun::star::container;
83
84 using namespace rtl;
85
86 namespace framework{
87
88 //_______________________________________________
89 // non exported const
90
91 //_______________________________________________
92 // non exported definitions
93
94 //_______________________________________________
95 // declarations
96
97 //***********************************************
98 // XInterface, XTypeProvider, XServiceInfo
99
DEFINE_XINTERFACE_6(SessionListener,OWeakObject,DIRECT_INTERFACE (css::lang::XTypeProvider),DIRECT_INTERFACE (css::lang::XInitialization),DIRECT_INTERFACE (css::frame::XSessionManagerListener),DIRECT_INTERFACE (css::frame::XSessionManagerListener2),DIRECT_INTERFACE (css::frame::XStatusListener),DIRECT_INTERFACE (css::lang::XServiceInfo))100 DEFINE_XINTERFACE_6(
101 SessionListener,
102 OWeakObject,
103 DIRECT_INTERFACE(css::lang::XTypeProvider),
104 DIRECT_INTERFACE(css::lang::XInitialization),
105 DIRECT_INTERFACE(css::frame::XSessionManagerListener),
106 DIRECT_INTERFACE(css::frame::XSessionManagerListener2),
107 DIRECT_INTERFACE(css::frame::XStatusListener),
108 DIRECT_INTERFACE(css::lang::XServiceInfo))
109
110 DEFINE_XTYPEPROVIDER_5(
111 SessionListener,
112 css::lang::XTypeProvider,
113 css::lang::XInitialization,
114 css::frame::XSessionManagerListener2,
115 css::frame::XStatusListener,
116 css::lang::XServiceInfo)
117
118 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(
119 SessionListener,
120 cppu::OWeakObject,
121 SERVICENAME_SESSIONLISTENER,
122 IMPLEMENTATIONNAME_SESSIONLISTENER)
123
124 DEFINE_INIT_SERVICE(SessionListener,
125 {
126 /* Add special code for initialization here, if you have to use your own instance
127 during your ctor is still in progress! */
128 }
129 )
130
131 SessionListener::SessionListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
132 : ThreadHelpBase (&Application::GetSolarMutex())
133 , OWeakObject ( )
134 , m_xSMGR (xSMGR )
135 , m_bRestored( sal_False )
136 , m_bSessionStoreRequested( sal_False )
137 , m_bAllowUserInteractionOnQuit( sal_False )
138 , m_bTerminated( sal_False )
139 {
140 }
141
~SessionListener()142 SessionListener::~SessionListener()
143 {
144 if (m_rSessionManager.is())
145 {
146 css::uno::Reference< XSessionManagerListener> me(this);
147 m_rSessionManager->removeSessionManagerListener(me);
148 }
149 }
150
StoreSession(sal_Bool bAsync)151 void SessionListener::StoreSession( sal_Bool bAsync )
152 {
153 ResetableGuard aGuard(m_aLock);
154 try
155 {
156 // xd create SERVICENAME_AUTORECOVERY -> XDispatch
157 // xd->dispatch("vnd.sun.star.autorecovery:/doSessionSave, async=bAsync
158 // on stop event m_rSessionManager->saveDone(this); in case of asynchronous call
159 // in case of synchronous call the caller should do saveDone() call himself!
160
161 css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
162 css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
163 URL aURL;
164 aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionSave");
165 xURLTransformer->parseStrict(aURL);
166
167 // in case of asynchronous call the notification will trigger saveDone()
168 if ( bAsync )
169 xDispatch->addStatusListener(this, aURL);
170
171 Sequence< PropertyValue > args(1);
172 args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(bAsync),PropertyState_DIRECT_VALUE);
173 xDispatch->dispatch(aURL, args);
174 } catch (com::sun::star::uno::Exception& e) {
175 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
176 OSL_ENSURE(sal_False, aMsg.getStr());
177 // save failed, but tell manager to go on if we haven't yet dispatched the request
178 // in case of synchronous saving the notification is done by the caller
179 if ( bAsync && m_rSessionManager.is() )
180 m_rSessionManager->saveDone(this);
181 }
182 }
183
QuitSessionQuietly()184 void SessionListener::QuitSessionQuietly()
185 {
186 ResetableGuard aGuard(m_aLock);
187 try
188 {
189 // xd create SERVICENAME_AUTORECOVERY -> XDispatch
190 // xd->dispatch("vnd.sun.star.autorecovery:/doSessionQuietQuit, async=false
191 // it is done synchronously to avoid conflict with normal quit process
192
193 css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
194 css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
195 URL aURL;
196 aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionQuietQuit");
197 xURLTransformer->parseStrict(aURL);
198
199 Sequence< PropertyValue > args(1);
200 args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(sal_False),PropertyState_DIRECT_VALUE);
201 xDispatch->dispatch(aURL, args);
202 } catch (com::sun::star::uno::Exception& e) {
203 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
204 OSL_ENSURE(sal_False, aMsg.getStr());
205 }
206 }
207
disposing(const com::sun::star::lang::EventObject &)208 void SAL_CALL SessionListener::disposing(const com::sun::star::lang::EventObject&) throw (RuntimeException)
209 {
210 }
211
initialize(const Sequence<Any> & args)212 void SAL_CALL SessionListener::initialize(const Sequence< Any >& args)
213 throw (RuntimeException)
214 {
215
216 OUString aSMgr = OUString::createFromAscii("com.sun.star.frame.SessionManagerClient");
217 if (args.getLength() > 0)
218 {
219 NamedValue v;
220 for (int i = 0; i < args.getLength(); i++)
221 {
222 if (args[i] >>= v)
223 {
224 if (v.Name.equalsAscii("SessionManagerName"))
225 v.Value >>= aSMgr;
226 else if (v.Name.equalsAscii("SessionManager"))
227 v.Value >>= m_rSessionManager;
228 else if (v.Name.equalsAscii("AllowUserInteractionOnQuit"))
229 v.Value >>= m_bAllowUserInteractionOnQuit;
230 }
231 }
232 }
233 if (!m_rSessionManager.is())
234 m_rSessionManager = css::uno::Reference< XSessionManagerClient >
235 (m_xSMGR->createInstance(aSMgr), UNO_QUERY);
236
237 if (m_rSessionManager.is())
238 {
239 m_rSessionManager->addSessionManagerListener(this);
240 }
241 }
242
statusChanged(const FeatureStateEvent & event)243 void SAL_CALL SessionListener::statusChanged(const FeatureStateEvent& event)
244 throw (css::uno::RuntimeException)
245 {
246 if (event.FeatureURL.Complete.equalsAscii("vnd.sun.star.autorecovery:/doSessionRestore"))
247 {
248 if (event.FeatureDescriptor.compareToAscii("update")==0)
249 m_bRestored = sal_True; // a document was restored
250 // if (event.FeatureDescriptor.compareToAscii("stop")==0)
251
252 }
253 else if (event.FeatureURL.Complete.equalsAscii("vnd.sun.star.autorecovery:/doSessionSave"))
254 {
255 if (event.FeatureDescriptor.compareToAscii("stop")==0)
256 {
257 if (m_rSessionManager.is())
258 m_rSessionManager->saveDone(this); // done with save
259 }
260 }
261 }
262
263
doRestore()264 sal_Bool SAL_CALL SessionListener::doRestore()
265 throw (RuntimeException)
266 {
267 ResetableGuard aGuard(m_aLock);
268 m_bRestored = sal_False;
269 try {
270 css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
271
272 URL aURL;
273 aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionRestore");
274 css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
275 xURLTransformer->parseStrict(aURL);
276 Sequence< PropertyValue > args;
277 xDispatch->addStatusListener(this, aURL);
278 xDispatch->dispatch(aURL, args);
279 m_bRestored = sal_True;
280
281 } catch (com::sun::star::uno::Exception& e) {
282 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
283 OSL_ENSURE(sal_False, aMsg.getStr());
284 }
285
286 return m_bRestored;
287 }
288
289
doSave(sal_Bool bShutdown,sal_Bool)290 void SAL_CALL SessionListener::doSave( sal_Bool bShutdown, sal_Bool /*bCancelable*/ )
291 throw (RuntimeException)
292 {
293 if (bShutdown)
294 {
295 m_bSessionStoreRequested = sal_True; // there is no need to protect it with mutex
296 if ( m_bAllowUserInteractionOnQuit && m_rSessionManager.is() )
297 m_rSessionManager->queryInteraction( static_cast< css::frame::XSessionManagerListener* >( this ) );
298 else
299 StoreSession( sal_True );
300 }
301 // we don't have anything to do so tell the session manager we're done
302 else if( m_rSessionManager.is() )
303 m_rSessionManager->saveDone( this );
304 }
305
approveInteraction(sal_Bool bInteractionGranted)306 void SAL_CALL SessionListener::approveInteraction( sal_Bool bInteractionGranted )
307 throw (RuntimeException)
308 {
309 // do AutoSave as the first step
310 ResetableGuard aGuard(m_aLock);
311
312 if ( bInteractionGranted )
313 {
314 // close the office documents in normal way
315 try
316 {
317 // first of all let the session be stored to be sure that we lose no information
318 StoreSession( sal_False );
319
320 css::uno::Reference< css::frame::XDesktop > xDesktop( m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
321 m_bTerminated = xDesktop->terminate();
322
323 if ( m_rSessionManager.is() )
324 {
325 // false means that the application closing has been canceled
326 if ( !m_bTerminated )
327 m_rSessionManager->cancelShutdown();
328 else
329 m_rSessionManager->interactionDone( this );
330 }
331 }
332 catch( css::uno::Exception& )
333 {
334 StoreSession( sal_True );
335 m_rSessionManager->interactionDone( this );
336 }
337
338 if ( m_rSessionManager.is() )
339 m_rSessionManager->saveDone(this);
340 }
341 else
342 {
343 StoreSession( sal_True );
344 }
345 }
346
shutdownCanceled()347 void SessionListener::shutdownCanceled()
348 throw (RuntimeException)
349 {
350 // set the state back
351 m_bSessionStoreRequested = sal_False; // there is no need to protect it with mutex
352 }
353
doQuit()354 void SessionListener::doQuit()
355 throw (RuntimeException)
356 {
357 if ( m_bSessionStoreRequested && !m_bTerminated )
358 {
359 // let the session be closed quietly in this case
360 QuitSessionQuietly();
361 }
362 }
363
364 }
365