summaryrefslogtreecommitdiff
path: root/framework
diff options
context:
space:
mode:
authorMikhail Voitenko <mav@openoffice.org>2009-12-03 10:37:54 +0000
committerMikhail Voitenko <mav@openoffice.org>2009-12-03 10:37:54 +0000
commit83551c86578375623fa8e670bbfe1c976b3bd665 (patch)
tree999b9bdf092072743327637712fc515969039d26 /framework
parent245aaeb38f6d1f0ed1ac892da302772e6f71a9f3 (diff)
#i105172# allow to request storing of documents from the user on session shutdown
Diffstat (limited to 'framework')
-rw-r--r--framework/inc/services/autorecovery.hxx7
-rw-r--r--framework/inc/services/sessionlistener.hxx20
-rw-r--r--framework/source/services/autorecovery.cxx143
-rw-r--r--framework/source/services/sessionlistener.cxx142
4 files changed, 217 insertions, 95 deletions
diff --git a/framework/inc/services/autorecovery.hxx b/framework/inc/services/autorecovery.hxx
index 8f6c62a2f39e..ed3630ed1583 100644
--- a/framework/inc/services/autorecovery.hxx
+++ b/framework/inc/services/autorecovery.hxx
@@ -239,7 +239,8 @@ class AutoRecovery : public css::lang::XTypeProvider
E_SESSION_SAVE = 64,
E_SESSION_RESTORE = 128,
E_DISABLE_AUTORECOVERY = 256,
- E_SET_AUTOSAVE_STATE = 512
+ E_SET_AUTOSAVE_STATE = 512,
+ E_SESSION_QUIET_QUIT = 1024
};
//---------------------------------------
@@ -884,6 +885,10 @@ class AutoRecovery : public css::lang::XTypeProvider
//---------------------------------------
// TODO document me
+ void implts_doSessionQuietQuit(const DispatchParams& aParams);
+
+ //---------------------------------------
+ // TODO document me
void implts_doSessionRestore(const DispatchParams& aParams);
//---------------------------------------
diff --git a/framework/inc/services/sessionlistener.hxx b/framework/inc/services/sessionlistener.hxx
index cbb22a322d48..c8e54d4bcbaa 100644
--- a/framework/inc/services/sessionlistener.hxx
+++ b/framework/inc/services/sessionlistener.hxx
@@ -49,7 +49,7 @@
#include <com/sun/star/lang/XInitialization.hpp>
-#include <com/sun/star/frame/XSessionManagerListener.hpp>
+#include <com/sun/star/frame/XSessionManagerListener2.hpp>
#include <com/sun/star/frame/XSessionManagerClient.hpp>
#include <com/sun/star/frame/XStatusListener.hpp>
#include <com/sun/star/frame/FeatureStateEvent.hpp>
@@ -98,7 +98,7 @@ namespace framework{
class SessionListener : // interfaces
public css::lang::XTypeProvider,
public css::lang::XInitialization,
- public css::frame::XSessionManagerListener,
+ public css::frame::XSessionManagerListener2,
public css::frame::XStatusListener,
public css::lang::XServiceInfo,
// baseclasses (order important for initialization!)
@@ -120,6 +120,18 @@ class SessionListener : // interfaces
// restore handling
sal_Bool m_bRestored;
+ sal_Bool m_bSessionStoreRequested;
+
+ sal_Bool m_bAllowUserInteractionOnQuit;
+ sal_Bool m_bTerminated;
+
+
+ // in case of synchronous call the caller should do saveDone() call himself!
+ void StoreSession( sal_Bool bAsync );
+
+ // let session quietly close the documents, remove lock files, store configuration and etc.
+ void QuitSessionQuietly();
+
public:
//---------------------------------------
@@ -163,6 +175,10 @@ class SessionListener : // interfaces
virtual sal_Bool SAL_CALL doRestore()
throw (css::uno::RuntimeException);
+ // XSessionManagerListener2
+ virtual void SAL_CALL doQuit()
+ throw (::com::sun::star::uno::RuntimeException);
+
// XStatusListener
virtual void SAL_CALL statusChanged(const com::sun::star::frame::FeatureStateEvent& event)
throw (css::uno::RuntimeException);
diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index 9328ed9d9a5c..1555b7db33a1 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -170,6 +170,7 @@ static const ::rtl::OUString CMD_DO_RECOVERY = ::rtl::OUString::
static const ::rtl::OUString CMD_DO_ENTRY_BACKUP = ::rtl::OUString::createFromAscii("/doEntryBackup" ); // try to store a temp or original file to a user defined location
static const ::rtl::OUString CMD_DO_ENTRY_CLEANUP = ::rtl::OUString::createFromAscii("/doEntryCleanUp" ); // remove the specified entry from the recovery cache
static const ::rtl::OUString CMD_DO_SESSION_SAVE = ::rtl::OUString::createFromAscii("/doSessionSave" ); // save all open documents if e.g. a window manager closes an user session
+static const ::rtl::OUString CMD_DO_SESSION_QUIET_QUIT = ::rtl::OUString::createFromAscii("/doSessionQuietQuit" ); // let the current session be quietly closed ( the saving should be done using doSessionSave previously ) if e.g. a window manager closes an user session
static const ::rtl::OUString CMD_DO_SESSION_RESTORE = ::rtl::OUString::createFromAscii("/doSessionRestore" ); // restore a saved user session from disc
static const ::rtl::OUString CMD_DO_DISABLE_RECOVERY = ::rtl::OUString::createFromAscii("/disableRecovery" ); // disable recovery and auto save (!) temp. for this office session
static const ::rtl::OUString CMD_DO_SET_AUTOSAVE_STATE = ::rtl::OUString::createFromAscii("/setAutoSaveState" ); // disable/enable auto save (not crash save) for this office session
@@ -725,6 +726,16 @@ void AutoRecovery::implts_dispatch(const DispatchParams& aParams)
}
else
if (
+ ((eJob & AutoRecovery::E_SESSION_QUIET_QUIT ) == AutoRecovery::E_SESSION_QUIET_QUIT ) &&
+ ((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
+ )
+ {
+ LOG_RECOVERY("... do session quiet quit ...")
+ bAllowAutoSaveReactivation = sal_False;
+ implts_doSessionQuietQuit(aParams);
+ }
+ else
+ if (
((eJob & AutoRecovery::E_SESSION_RESTORE ) == AutoRecovery::E_SESSION_RESTORE ) &&
((eJob & AutoRecovery::E_DISABLE_AUTORECOVERY) != AutoRecovery::E_DISABLE_AUTORECOVERY)
)
@@ -1987,6 +1998,30 @@ void AutoRecovery::implts_changeAllDocVisibility(sal_Bool bVisible)
}
//-----------------------------------------------
+/* Currently the document is not closed in case of crash,
+ so the lock file must be removed explicitly
+*/
+void lc_removeLockFile(AutoRecovery::TDocumentInfo& rInfo)
+{
+ if ( rInfo.Document.is() )
+ {
+ try
+ {
+ css::uno::Reference< css::frame::XStorable > xStore(rInfo.Document, css::uno::UNO_QUERY_THROW);
+ ::rtl::OUString aURL = xStore->getLocation();
+ if ( aURL.getLength() )
+ {
+ ::svt::DocumentLockFile aLockFile( aURL );
+ aLockFile.RemoveFile();
+ }
+ }
+ catch( const css::uno::Exception& )
+ {}
+ }
+}
+
+
+//-----------------------------------------------
void AutoRecovery::implts_prepareSessionShutdown()
{
LOG_RECOVERY("AutoRecovery::implts_prepareSessionShutdown() starts ...")
@@ -2004,6 +2039,10 @@ void AutoRecovery::implts_prepareSessionShutdown()
{
AutoRecovery::TDocumentInfo& rInfo = *pIt;
+ // WORKAROUND... Since the documents are not closed the lock file must be removed explicitly
+ // it is not done on documents saving since shutdown can be cancelled
+ lc_removeLockFile( rInfo );
+
// Prevent us from deregistration of these documents.
// Because we close these documents by ourself (see XClosable below) ...
// it's fact, that we reach our deregistration method. There we
@@ -2014,31 +2053,38 @@ void AutoRecovery::implts_prepareSessionShutdown()
// reset modified flag of these documents (ignoring the notification about it!)
// Otherwise a message box is shown on closing these models.
implts_stopModifyListeningOnDoc(rInfo);
- css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY);
- if (xModify.is())
- xModify->setModified(sal_False);
- // close the model.
- css::uno::Reference< css::util::XCloseable > xClose(rInfo.Document, css::uno::UNO_QUERY);
- if (xClose.is())
+ // if the session save is still running the documents should not be thrown away,
+ // actually that would be a bad sign, that means that the SessionManager tryes
+ // to kill the session before the saving is ready
+ if ((m_eJob & AutoRecovery::E_SESSION_SAVE) != AutoRecovery::E_SESSION_SAVE)
{
- try
+ css::uno::Reference< css::util::XModifiable > xModify(rInfo.Document, css::uno::UNO_QUERY);
+ if (xModify.is())
+ xModify->setModified(sal_False);
+
+ // close the model.
+ css::uno::Reference< css::util::XCloseable > xClose(rInfo.Document, css::uno::UNO_QUERY);
+ if (xClose.is())
{
- xClose->close(sal_False);
- }
- /*
- catch(const css::lang::DisposedException&)
- {
- // closed ... disposed ... always the same .-)
- }
- */
- catch(const css::uno::Exception&)
+ try
{
- // At least it's only a try to close these documents before anybody else it does.
- // So it seams to be possible to ignore any error here .-)
+ xClose->close(sal_False);
}
+ /*
+ catch(const css::lang::DisposedException&)
+ {
+ // closed ... disposed ... always the same .-)
+ }
+ */
+ catch(const css::uno::Exception&)
+ {
+ // At least it's only a try to close these documents before anybody else it does.
+ // So it seams to be possible to ignore any error here .-)
+ }
- rInfo.Document.clear();
+ rInfo.Document.clear();
+ }
}
}
@@ -2047,30 +2093,6 @@ void AutoRecovery::implts_prepareSessionShutdown()
}
//-----------------------------------------------
-/* Currently the document is not closed in case of crash,
- so the lock file must be removed explicitly
-*/
-void lc_removeLockFile(AutoRecovery::TDocumentInfo& rInfo)
-{
- if ( rInfo.Document.is() )
- {
- try
- {
- css::uno::Reference< css::frame::XStorable > xStore(rInfo.Document, css::uno::UNO_QUERY_THROW);
- ::rtl::OUString aURL = xStore->getLocation();
- if ( aURL.getLength() )
- {
- ::svt::DocumentLockFile aLockFile( aURL );
- aLockFile.RemoveFile();
- }
- }
- catch( const css::uno::Exception& )
- {}
- }
-}
-
-
-//-----------------------------------------------
/* TODO WORKAROUND:
#i64599#
@@ -2750,6 +2772,9 @@ void AutoRecovery::implts_informListener( sal_Int32 eJ
if ((eJob & AutoRecovery::E_SESSION_SAVE) == AutoRecovery::E_SESSION_SAVE)
sFeature.append(CMD_DO_SESSION_SAVE);
else
+ if ((eJob & AutoRecovery::E_SESSION_QUIET_QUIT) == AutoRecovery::E_SESSION_QUIET_QUIT)
+ sFeature.append(CMD_DO_SESSION_QUIET_QUIT);
+ else
if ((eJob & AutoRecovery::E_SESSION_RESTORE) == AutoRecovery::E_SESSION_RESTORE)
sFeature.append(CMD_DO_SESSION_RESTORE);
else
@@ -2792,6 +2817,9 @@ sal_Int32 AutoRecovery::implst_classifyJob(const css::util::URL& aURL)
if (aURL.Path.equals(CMD_DO_SESSION_SAVE))
return AutoRecovery::E_SESSION_SAVE;
else
+ if (aURL.Path.equals(CMD_DO_SESSION_QUIET_QUIT))
+ return AutoRecovery::E_SESSION_QUIET_QUIT;
+ else
if (aURL.Path.equals(CMD_DO_SESSION_RESTORE))
return AutoRecovery::E_SESSION_RESTORE;
else
@@ -2968,14 +2996,6 @@ void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams)
{
LOG_RECOVERY("AutoRecovery::implts_doSessionSave()")
- // try to make sure next time office will be started user wont be
- // notified about any other might be running office instance
- // remove ".lock" file from disc !
- // it is done as a first action for session save since Gnome sessions
- // do not provide enough time for shutdown, and the dialog looks to be
- // confusing for the user
- AutoRecovery::st_impl_removeLockFile();
-
// Be sure to know all open documents realy .-)
implts_verifyCacheAgainstDesktopDocumentList();
@@ -2991,7 +3011,8 @@ void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams)
AutoRecovery::ETimerType eSuggestedTimer = AutoRecovery::E_DONT_START_TIMER;
do
{
- eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_True, &aParams);
+ // do not remove lock files of the documents, it will be done on session quit
+ eSuggestedTimer = implts_saveDocs(bAllowUserIdleLoop, sal_False, &aParams);
}
while(eSuggestedTimer == AutoRecovery::E_CALL_ME_BACK);
@@ -3002,6 +3023,23 @@ void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams)
// any "handle" state ...
implts_resetHandleStates(sal_False);
+ // flush config cached back to disc.
+ impl_flushALLConfigChanges();
+}
+
+//-----------------------------------------------
+void AutoRecovery::implts_doSessionQuietQuit(const DispatchParams& /*aParams*/)
+{
+ LOG_RECOVERY("AutoRecovery::implts_doSessionQuietQuit()")
+
+ // try to make sure next time office will be started user wont be
+ // notified about any other might be running office instance
+ // remove ".lock" file from disc !
+ // it is done as a first action for session save since Gnome sessions
+ // do not provide enough time for shutdown, and the dialog looks to be
+ // confusing for the user
+ AutoRecovery::st_impl_removeLockFile();
+
// reset all modified documents, so the dont show any UI on closing ...
// and close all documents, so we can shutdown the OS!
implts_prepareSessionShutdown();
@@ -3020,6 +3058,7 @@ void AutoRecovery::implts_doSessionSave(const DispatchParams& aParams)
impl_flushALLConfigChanges();
}
+
//-----------------------------------------------
void AutoRecovery::implts_doSessionRestore(const DispatchParams& aParams)
{
diff --git a/framework/source/services/sessionlistener.cxx b/framework/source/services/sessionlistener.cxx
index 4a58a483ea3c..6dd559adf0e7 100644
--- a/framework/source/services/sessionlistener.cxx
+++ b/framework/source/services/sessionlistener.cxx
@@ -104,12 +104,13 @@ namespace framework{
//***********************************************
// XInterface, XTypeProvider, XServiceInfo
-DEFINE_XINTERFACE_5(
+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))
@@ -117,7 +118,7 @@ DEFINE_XTYPEPROVIDER_5(
SessionListener,
css::lang::XTypeProvider,
css::lang::XInitialization,
- css::frame::XSessionManagerListener,
+ css::frame::XSessionManagerListener2,
css::frame::XStatusListener,
css::lang::XServiceInfo)
@@ -138,7 +139,10 @@ SessionListener::SessionListener(const css::uno::Reference< css::lang::XMultiSer
: ThreadHelpBase (&Application::GetSolarMutex())
, OWeakObject ( )
, m_xSMGR (xSMGR )
- , m_bRestored( false )
+ , m_bRestored( sal_False )
+ , m_bSessionStoreRequested( sal_False )
+ , m_bAllowUserInteractionOnQuit( sal_False )
+ , m_bTerminated( sal_False )
{
}
@@ -151,6 +155,63 @@ SessionListener::~SessionListener()
}
}
+void SessionListener::StoreSession( sal_Bool bAsync )
+{
+ ResetableGuard aGuard(m_aLock);
+ try
+ {
+ // xd create SERVICENAME_AUTORECOVERY -> XDispatch
+ // xd->dispatch("vnd.sun.star.autorecovery:/doSessionSave, async=bAsync
+ // on stop event m_rSessionManager->saveDone(this); in case of asynchronous call
+ // in case of synchronous call the caller should do saveDone() call himself!
+
+ css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
+ css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionSave");
+ xURLTransformer->parseStrict(aURL);
+
+ // in case of asynchronous call the notification will trigger saveDone()
+ if ( bAsync )
+ xDispatch->addStatusListener(this, aURL);
+
+ Sequence< PropertyValue > args(1);
+ args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(bAsync),PropertyState_DIRECT_VALUE);
+ xDispatch->dispatch(aURL, args);
+ } catch (com::sun::star::uno::Exception& e) {
+ OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
+ OSL_ENSURE(sal_False, aMsg.getStr());
+ // save failed, but tell manager to go on if we havent yet dispatched the request
+ // in case of synchronous saving the notification is done by the caller
+ if ( bAsync && m_rSessionManager.is() )
+ m_rSessionManager->saveDone(this);
+ }
+}
+
+void SessionListener::QuitSessionQuietly()
+{
+ ResetableGuard aGuard(m_aLock);
+ try
+ {
+ // xd create SERVICENAME_AUTORECOVERY -> XDispatch
+ // xd->dispatch("vnd.sun.star.autorecovery:/doSessionQuietQuit, async=false
+ // it is done synchronously to avoid conflict with normal quit process
+
+ css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
+ css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
+ URL aURL;
+ aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionQuietQuit");
+ xURLTransformer->parseStrict(aURL);
+
+ Sequence< PropertyValue > args(1);
+ args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(sal_False),PropertyState_DIRECT_VALUE);
+ xDispatch->dispatch(aURL, args);
+ } catch (com::sun::star::uno::Exception& e) {
+ OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
+ OSL_ENSURE(sal_False, aMsg.getStr());
+ }
+}
+
void SAL_CALL SessionListener::disposing(const com::sun::star::lang::EventObject&) throw (RuntimeException)
{
}
@@ -171,6 +232,8 @@ void SAL_CALL SessionListener::initialize(const Sequence< Any >& args)
v.Value >>= aSMgr;
else if (v.Name.equalsAscii("SessionManager"))
v.Value >>= m_rSessionManager;
+ else if (v.Name.equalsAscii("AllowUserInteractionOnQuit"))
+ v.Value >>= m_bAllowUserInteractionOnQuit;
}
}
}
@@ -236,9 +299,11 @@ void SAL_CALL SessionListener::doSave( sal_Bool bShutdown, sal_Bool /*bCancelabl
{
if (bShutdown)
{
- if ( m_rSessionManager.is() )
+ m_bSessionStoreRequested = sal_True; // there is no need to protect it with mutex
+ if ( m_bAllowUserInteractionOnQuit && m_rSessionManager.is() )
m_rSessionManager->queryInteraction( static_cast< css::frame::XSessionManagerListener* >( this ) );
-
+ else
+ StoreSession( sal_True );
}
// we don't have anything to do so tell the session manager we're done
else if( m_rSessionManager.is() )
@@ -250,63 +315,60 @@ void SAL_CALL SessionListener::doSave( sal_Bool bShutdown, sal_Bool /*bCancelabl
void SAL_CALL SessionListener::approveInteraction( sal_Bool bInteractionGranted )
throw (RuntimeException)
{
- sal_Bool bClosed = sal_False;
+ // do AutoSave as the first step
+ sal_Bool bDispatched = sal_False;
+ ResetableGuard aGuard(m_aLock);
+
if ( bInteractionGranted )
{
- ResetableGuard aGuard(m_aLock);
-
// close the office documents in normal way
try
{
+ // first of all let the session be stored to be sure that we lose no information
+ StoreSession( sal_False );
+
css::uno::Reference< css::frame::XDesktop > xDesktop( m_xSMGR->createInstance(SERVICENAME_DESKTOP), css::uno::UNO_QUERY_THROW);
- bClosed = xDesktop->terminate();
+ m_bTerminated = xDesktop->terminate();
if ( m_rSessionManager.is() )
{
// false means that the application closing has been cancelled
- if ( !bClosed )
+ if ( !m_bTerminated )
m_rSessionManager->cancelShutdown();
else
m_rSessionManager->interactionDone( this );
}
}
catch( css::uno::Exception& )
- {}
- }
-
- if ( !bClosed )
- {
- sal_Bool bDispatched = sal_False;
- ResetableGuard aGuard(m_aLock);
- try
{
- // xd create SERVICENAME_AUTORECOVERY -> XDispatch
- // xd->dispatch("vnd.sun.star.autorecovery:/doSessionSave, async=true
- // on stop event m_rSessionManager->saveDone(this);
-
- css::uno::Reference< XDispatch > xDispatch(m_xSMGR->createInstance(SERVICENAME_AUTORECOVERY), UNO_QUERY_THROW);
- css::uno::Reference< XURLTransformer > xURLTransformer(m_xSMGR->createInstance(SERVICENAME_URLTRANSFORMER), UNO_QUERY_THROW);
- URL aURL;
- aURL.Complete = OUString::createFromAscii("vnd.sun.star.autorecovery:/doSessionSave");
- xURLTransformer->parseStrict(aURL);
- xDispatch->addStatusListener(this, aURL);
- Sequence< PropertyValue > args(1);
- args[0] = PropertyValue(OUString::createFromAscii("DispatchAsynchron"),-1,makeAny(sal_True),PropertyState_DIRECT_VALUE);
- xDispatch->dispatch(aURL, args);
- bDispatched = sal_True;
- // on stop event set call m_rSessionManager->saveDone(this);
- } catch (com::sun::star::uno::Exception& e) {
- OString aMsg = OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8);
- OSL_ENSURE(sal_False, aMsg.getStr());
- // save failed, but tell manager to go on if we havent yet dispatched the request
- if (m_rSessionManager.is() && !bDispatched)
- m_rSessionManager->saveDone(this);
+ StoreSession( sal_True );
+ m_rSessionManager->interactionDone( this );
}
+
+ if ( m_rSessionManager.is() )
+ m_rSessionManager->saveDone(this);
+ }
+ else
+ {
+ StoreSession( sal_True );
}
}
void SessionListener::shutdownCanceled()
throw (RuntimeException)
-{}
+{
+ // set the state back
+ m_bSessionStoreRequested = sal_False; // there is no need to protect it with mutex
+}
+
+void SessionListener::doQuit()
+ throw (RuntimeException)
+{
+ if ( m_bSessionStoreRequested && !m_bTerminated )
+ {
+ // let the session be closed quietly in this case
+ QuitSessionQuietly();
+ }
+}
}