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&)
209 {
210 }
211
initialize(const Sequence<Any> & args)212 void SAL_CALL SessionListener::initialize(const Sequence< Any >& args)
213 {
214
215 OUString aSMgr = OUString::createFromAscii("com.sun.star.frame.SessionManagerClient");
216 if (args.getLength() > 0)
217 {
218 NamedValue v;
219 for (int i = 0; i < args.getLength(); i++)
220 {
221 if (args[i] >>= v)
222 {
223 if (v.Name.equalsAscii("SessionManagerName"))
224 v.Value >>= aSMgr;
225 else if (v.Name.equalsAscii("SessionManager"))
226 v.Value >>= m_rSessionManager;
227 else if (v.Name.equalsAscii("AllowUserInteractionOnQuit"))
228 v.Value >>= m_bAllowUserInteractionOnQuit;
229 }
230 }
231 }
232 if (!m_rSessionManager.is())
233 m_rSessionManager = css::uno::Reference< XSessionManagerClient >
234 (m_xSMGR->createInstance(aSMgr), UNO_QUERY);
235
236 if (m_rSessionManager.is())
237 {
238 m_rSessionManager->addSessionManagerListener(this);
239 }
240 }
241
statusChanged(const FeatureStateEvent & event)242 void SAL_CALL SessionListener::statusChanged(const FeatureStateEvent& event)
243 {
244 if (event.FeatureURL.Complete.equalsAscii("vnd.sun.star.autorecovery:/doSessionRestore"))
245 {
246 if (event.FeatureDescriptor.compareToAscii("update")==0)
247 m_bRestored = sal_True; // a document was restored
248 // if (event.FeatureDescriptor.compareToAscii("stop")==0)
249
250 }
251 else if (event.FeatureURL.Complete.equalsAscii("vnd.sun.star.autorecovery:/doSessionSave"))
252 {
253 if (event.FeatureDescriptor.compareToAscii("stop")==0)
254 {
255 if (m_rSessionManager.is())
256 m_rSessionManager->saveDone(this); // done with save
257 }
258 }
259 }
260
261
doRestore()262 sal_Bool SAL_CALL SessionListener::doRestore()
263 {
264 ResetableGuard aGuard(m_aLock);
265 m_bRestored = sal_False;
266 try {
267 css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
268
269 URL aURL;
270 aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionRestore");
271 css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
272 xURLTransformer->parseStrict(aURL);
273 Sequence< PropertyValue > args;
274 xDispatch->addStatusListener(this, aURL);
275 xDispatch->dispatch(aURL, args);
276 m_bRestored = sal_True;
277
278 } catch (com::sun::star::uno::Exception& e) {
279 OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
280 OSL_ENSURE(sal_False, aMsg.getStr());
281 }
282
283 return m_bRestored;
284 }
285
286
doSave(sal_Bool bShutdown,sal_Bool)287 void SAL_CALL SessionListener::doSave( sal_Bool bShutdown, sal_Bool /*bCancelable*/ )
288 {
289 if (bShutdown)
290 {
291 m_bSessionStoreRequested = sal_True; // there is no need to protect it with mutex
292 if ( m_bAllowUserInteractionOnQuit && m_rSessionManager.is() )
293 m_rSessionManager->queryInteraction( static_cast< css::frame::XSessionManagerListener* >( this ) );
294 else
295 StoreSession( sal_True );
296 }
297 // we don't have anything to do so tell the session manager we're done
298 else if( m_rSessionManager.is() )
299 m_rSessionManager->saveDone( this );
300 }
301
approveInteraction(sal_Bool bInteractionGranted)302 void SAL_CALL SessionListener::approveInteraction( sal_Bool bInteractionGranted )
303 {
304 // do AutoSave as the first step
305 ResetableGuard aGuard(m_aLock);
306
307 if ( bInteractionGranted )
308 {
309 // close the office documents in normal way
310 try
311 {
312 // first of all let the session be stored to be sure that we lose no information
313 StoreSession( sal_False );
314
315 css::uno::Reference< css::frame::XDesktop > xDesktop( m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
316 m_bTerminated = xDesktop->terminate();
317
318 if ( m_rSessionManager.is() )
319 {
320 // false means that the application closing has been canceled
321 if ( !m_bTerminated )
322 m_rSessionManager->cancelShutdown();
323 else
324 m_rSessionManager->interactionDone( this );
325 }
326 }
327 catch( css::uno::Exception& )
328 {
329 StoreSession( sal_True );
330 m_rSessionManager->interactionDone( this );
331 }
332
333 if ( m_rSessionManager.is() )
334 m_rSessionManager->saveDone(this);
335 }
336 else
337 {
338 StoreSession( sal_True );
339 }
340 }
341
shutdownCanceled()342 void SessionListener::shutdownCanceled()
343 {
344 // set the state back
345 m_bSessionStoreRequested = sal_False; // there is no need to protect it with mutex
346 }
347
doQuit()348 void SessionListener::doQuit()
349 {
350 if ( m_bSessionStoreRequested && !m_bTerminated )
351 {
352 // let the session be closed quietly in this case
353 QuitSessionQuietly();
354 }
355 }
356
357 }
358