update credits
[LibreOffice.git] / framework / source / services / sessionlistener.cxx
blob98ab2c0e705f21b95cee0279afa8ef6b7c40fe78
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <services/sessionlistener.hxx>
21 #include <services/desktop.hxx>
22 #include <threadhelp/readguard.hxx>
23 #include <threadhelp/resetableguard.hxx>
24 #include <protocols.h>
25 #include <services.h>
27 #include <osl/thread.h>
29 #include <vcl/svapp.hxx>
30 #include <unotools/tempfile.hxx>
31 #include <com/sun/star/lang/XSingleServiceFactory.hpp>
32 #include <com/sun/star/lang/XComponent.hpp>
33 #include <com/sun/star/container/XNameAccess.hpp>
34 #include <com/sun/star/container/XNameContainer.hpp>
35 #include <com/sun/star/beans/NamedValue.hpp>
36 #include <com/sun/star/beans/PropertyValue.hpp>
37 #include <com/sun/star/beans/PropertyState.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/frame/AutoRecovery.hpp>
40 #include <com/sun/star/frame/XFramesSupplier.hpp>
41 #include <com/sun/star/frame/XStorable.hpp>
42 #include <com/sun/star/frame/XComponentLoader.hpp>
43 #include <com/sun/star/frame/XDispatch.hpp>
44 #include <com/sun/star/frame/Desktop.hpp>
45 #include <com/sun/star/util/XModifiable.hpp>
46 #include <com/sun/star/util/XChangesBatch.hpp>
47 #include <com/sun/star/util/URLTransformer.hpp>
48 #include <com/sun/star/util/XURLTransformer.hpp>
49 #include <com/sun/star/util/URL.hpp>
50 #include <osl/time.h>
51 #include <comphelper/processfactory.hxx>
52 #include <unotools/pathoptions.hxx>
53 #include <stdio.h>
55 #include <com/sun/star/uno/Any.hxx>
57 #include <com/sun/star/uno/Sequence.hxx>
59 using namespace com::sun::star::uno;
60 using namespace com::sun::star::util;
61 using namespace com::sun::star::frame;
62 using namespace com::sun::star::lang;
63 using namespace com::sun::star::beans;
64 using namespace com::sun::star::container;
67 namespace framework{
69 //***********************************************
70 // XInterface, XTypeProvider, XServiceInfo
72 DEFINE_XINTERFACE_6(
73 SessionListener,
74 OWeakObject,
75 DIRECT_INTERFACE(css::lang::XTypeProvider),
76 DIRECT_INTERFACE(css::lang::XInitialization),
77 DIRECT_INTERFACE(css::frame::XSessionManagerListener),
78 DIRECT_INTERFACE(css::frame::XSessionManagerListener2),
79 DIRECT_INTERFACE(css::frame::XStatusListener),
80 DIRECT_INTERFACE(css::lang::XServiceInfo))
82 DEFINE_XTYPEPROVIDER_5(
83 SessionListener,
84 css::lang::XTypeProvider,
85 css::lang::XInitialization,
86 css::frame::XSessionManagerListener2,
87 css::frame::XStatusListener,
88 css::lang::XServiceInfo)
90 DEFINE_XSERVICEINFO_ONEINSTANCESERVICE(
91 SessionListener,
92 cppu::OWeakObject,
93 "com.sun.star.frame.SessionListener",
94 IMPLEMENTATIONNAME_SESSIONLISTENER)
96 DEFINE_INIT_SERVICE(SessionListener,
98 /* Add special code for initialization here, if you have to use your own instance
99 during your ctor is still in progress! */
103 SessionListener::SessionListener(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR )
104 : ThreadHelpBase (&Application::GetSolarMutex())
105 , OWeakObject ( )
106 , m_xSMGR (xSMGR )
107 , m_bRestored( sal_False )
108 , m_bSessionStoreRequested( sal_False )
109 , m_bAllowUserInteractionOnQuit( sal_False )
110 , m_bTerminated( sal_False )
112 SAL_INFO("fwk.session", "SessionListener::SessionListener");
115 SessionListener::~SessionListener()
117 SAL_INFO("fwk.session", "SessionListener::~SessionListener");
118 if (m_rSessionManager.is())
120 css::uno::Reference< XSessionManagerListener> me(this);
121 m_rSessionManager->removeSessionManagerListener(me);
125 void SessionListener::StoreSession( sal_Bool bAsync )
127 SAL_INFO("fwk.session", "SessionListener::StoreSession");
128 ResetableGuard aGuard(m_aLock);
131 // xd create SERVICENAME_AUTORECOVERY -> XDispatch
132 // xd->dispatch("vnd.sun.star.autorecovery:/doSessionSave, async=bAsync
133 // on stop event m_rSessionManager->saveDone(this); in case of asynchronous call
134 // in case of synchronous call the caller should do saveDone() call himself!
136 css::uno::Reference< XDispatch > xDispatch = css::frame::AutoRecovery::create( ::comphelper::getComponentContext(m_xSMGR) );
137 css::uno::Reference< XURLTransformer > xURLTransformer = URLTransformer::create( ::comphelper::getComponentContext(m_xSMGR) );
138 URL aURL;
139 aURL.Complete = OUString("vnd.sun.star.autorecovery:/doSessionSave");
140 xURLTransformer->parseStrict(aURL);
142 // in case of asynchronous call the notification will trigger saveDone()
143 if ( bAsync )
144 xDispatch->addStatusListener(this, aURL);
146 Sequence< PropertyValue > args(1);
147 args[0] = PropertyValue(OUString("DispatchAsynchron"),-1,makeAny(bAsync),PropertyState_DIRECT_VALUE);
148 xDispatch->dispatch(aURL, args);
149 } catch (const com::sun::star::uno::Exception& e) {
150 SAL_WARN("fwk.session",e.Message);
151 // save failed, but tell manager to go on if we havent yet dispatched the request
152 // in case of synchronous saving the notification is done by the caller
153 if ( bAsync && m_rSessionManager.is() )
154 m_rSessionManager->saveDone(this);
158 void SessionListener::QuitSessionQuietly()
160 SAL_INFO("fwk.session", "SessionListener::QuitSessionQuietly");
161 ResetableGuard aGuard(m_aLock);
164 // xd create SERVICENAME_AUTORECOVERY -> XDispatch
165 // xd->dispatch("vnd.sun.star.autorecovery:/doSessionQuietQuit, async=false
166 // it is done synchronously to avoid conflict with normal quit process
168 css::uno::Reference< XDispatch > xDispatch = css::frame::AutoRecovery::create( ::comphelper::getComponentContext(m_xSMGR) );
169 css::uno::Reference< XURLTransformer > xURLTransformer = URLTransformer::create( ::comphelper::getComponentContext(m_xSMGR) );
170 URL aURL;
171 aURL.Complete = OUString("vnd.sun.star.autorecovery:/doSessionQuietQuit");
172 xURLTransformer->parseStrict(aURL);
174 Sequence< PropertyValue > args(1);
175 args[0] = PropertyValue(OUString("DispatchAsynchron"),-1,makeAny(sal_False),PropertyState_DIRECT_VALUE);
176 xDispatch->dispatch(aURL, args);
177 } catch (const com::sun::star::uno::Exception& e) {
178 SAL_WARN("fwk.session",e.Message);
182 void SAL_CALL SessionListener::disposing(const com::sun::star::lang::EventObject&) throw (RuntimeException)
184 SAL_INFO("fwk.session", "SessionListener::disposing");
187 void SAL_CALL SessionListener::initialize(const Sequence< Any >& args)
188 throw (RuntimeException)
190 SAL_INFO("fwk.session", "SessionListener::initialize");
192 OUString aSMgr("com.sun.star.frame.SessionManagerClient");
193 if ( (args.getLength() == 1) && (args[0] >>= m_bAllowUserInteractionOnQuit) )
194 ;// do nothing
195 else if (args.getLength() > 0)
197 NamedValue v;
198 for (int i = 0; i < args.getLength(); i++)
200 if (args[i] >>= v)
202 if ( v.Name == "SessionManagerName" )
203 v.Value >>= aSMgr;
204 else if ( v.Name == "SessionManager" )
205 v.Value >>= m_rSessionManager;
206 else if ( v.Name == "AllowUserInteractionOnQuit" )
207 v.Value >>= m_bAllowUserInteractionOnQuit;
211 if (!m_rSessionManager.is())
212 m_rSessionManager = css::uno::Reference< XSessionManagerClient >
213 (m_xSMGR->createInstance(aSMgr), UNO_QUERY);
215 if (m_rSessionManager.is())
217 m_rSessionManager->addSessionManagerListener(this);
221 void SAL_CALL SessionListener::statusChanged(const FeatureStateEvent& event)
222 throw (css::uno::RuntimeException)
224 SAL_INFO("fwk.session", "SessionListener::statusChanged");
225 if ( event.FeatureURL.Complete == "vnd.sun.star.autorecovery:/doSessionRestore" )
227 if (event.FeatureDescriptor.compareToAscii("update")==0)
228 m_bRestored = sal_True; // a document was restored
231 else if ( event.FeatureURL.Complete == "vnd.sun.star.autorecovery:/doSessionSave" )
233 if (event.FeatureDescriptor.compareToAscii("stop")==0)
235 if (m_rSessionManager.is())
236 m_rSessionManager->saveDone(this); // done with save
242 sal_Bool SAL_CALL SessionListener::doRestore()
243 throw (RuntimeException)
245 SAL_INFO("fwk.session", "SessionListener::doRestore");
246 ResetableGuard aGuard(m_aLock);
247 m_bRestored = sal_False;
248 try {
249 css::uno::Reference< XDispatch > xDispatch = css::frame::AutoRecovery::create( ::comphelper::getComponentContext(m_xSMGR) );
251 URL aURL;
252 aURL.Complete = OUString("vnd.sun.star.autorecovery:/doSessionRestore");
253 css::uno::Reference< XURLTransformer > xURLTransformer(URLTransformer::create(::comphelper::getComponentContext(m_xSMGR)));
254 xURLTransformer->parseStrict(aURL);
255 Sequence< PropertyValue > args;
256 xDispatch->addStatusListener(this, aURL);
257 xDispatch->dispatch(aURL, args);
258 m_bRestored = sal_True;
260 } catch (const com::sun::star::uno::Exception& e) {
261 SAL_WARN("fwk.session",e.Message);
264 return m_bRestored;
268 void SAL_CALL SessionListener::doSave( sal_Bool bShutdown, sal_Bool /*bCancelable*/ )
269 throw (RuntimeException)
271 SAL_INFO("fwk.session", "SessionListener::doSave");
272 if (bShutdown)
274 m_bSessionStoreRequested = sal_True; // there is no need to protect it with mutex
275 if ( m_bAllowUserInteractionOnQuit && m_rSessionManager.is() )
276 m_rSessionManager->queryInteraction( static_cast< css::frame::XSessionManagerListener* >( this ) );
277 else
278 StoreSession( sal_True );
280 // we don't have anything to do so tell the session manager we're done
281 else if( m_rSessionManager.is() )
282 m_rSessionManager->saveDone( this );
285 void SAL_CALL SessionListener::approveInteraction( sal_Bool bInteractionGranted )
286 throw (RuntimeException)
288 SAL_INFO("fwk.session", "SessionListener::approveInteraction");
289 // do AutoSave as the first step
290 ResetableGuard aGuard(m_aLock);
292 if ( bInteractionGranted )
294 // close the office documents in normal way
297 // first of all let the session be stored to be sure that we lose no information
298 StoreSession( sal_False );
300 css::uno::Reference< css::frame::XDesktop2 > xDesktop = css::frame::Desktop::create( comphelper::getComponentContext(m_xSMGR) );
301 // honestly: how many implementations of XDesktop will we ever have?
302 // so casting this directly to the implementation
303 Desktop* pDesktop(dynamic_cast<Desktop*>(xDesktop.get()));
304 if(pDesktop)
306 SAL_INFO("fwk.session", "XDesktop is a framework::Desktop -- good.");
307 m_bTerminated = pDesktop->terminateQuickstarterToo();
309 else
311 SAL_WARN("fwk.session", "XDesktop is not a framework::Desktop -- this should never happen.");
312 m_bTerminated = xDesktop->terminate();
315 if ( m_rSessionManager.is() )
317 // false means that the application closing has been cancelled
318 if ( !m_bTerminated )
319 m_rSessionManager->cancelShutdown();
320 else
321 m_rSessionManager->interactionDone( this );
324 catch( const css::uno::Exception& )
326 StoreSession( sal_True );
327 m_rSessionManager->interactionDone( this );
330 if ( m_rSessionManager.is() )
331 m_rSessionManager->saveDone(this);
333 else
335 StoreSession( sal_True );
339 void SessionListener::shutdownCanceled()
340 throw (RuntimeException)
342 SAL_INFO("fwk.session", "SessionListener::shutdownCanceled");
343 // set the state back
344 m_bSessionStoreRequested = sal_False; // there is no need to protect it with mutex
347 void SessionListener::doQuit()
348 throw (RuntimeException)
350 SAL_INFO("fwk.session", "SessionListener::doQuit");
351 if ( m_bSessionStoreRequested && !m_bTerminated )
353 // let the session be closed quietly in this case
354 QuitSessionQuietly();
360 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */