xref: /trunk/main/svx/source/unodraw/recoveryui.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_svx.hxx"
30 
31 //===============================================
32 // includes
33 #include "recoveryui.hxx"
34 #include "docrecovery.hxx"
35 #include <com/sun/star/lang/XInitialization.hpp>
36 #include <com/sun/star/frame/XFramesSupplier.hpp>
37 #include <com/sun/star/beans/NamedValue.hpp>
38 #include <osl/file.hxx>
39 #include <rtl/bootstrap.hxx>
40 #include <comphelper/configurationhelper.hxx>
41 
42 #include <vcl/svapp.hxx>
43 
44 //===============================================
45 // const
46 
47 #define IMPLEMENTATIONNAME_RECOVERYUI       ::rtl::OUString::createFromAscii("com.sun.star.comp.svx.RecoveryUI")
48 #define SERVICENAME_RECOVERYUI              ::rtl::OUString::createFromAscii("com.sun.star.dialog.RecoveryUI")
49 
50 //===============================================
51 // namespace
52 
53 namespace svx
54 {
55 
56 namespace css   = ::com::sun::star;
57 namespace svxdr = ::svx::DocRecovery;
58 
59 using namespace ::rtl;
60 using namespace ::osl;
61 
62 //===============================================
63 RecoveryUI::RecoveryUI(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
64     : m_xSMGR        (xSMGR                    )
65     , m_pParentWindow(0                        )
66     , m_eJob         (RecoveryUI::E_JOB_UNKNOWN)
67 {
68 }
69 
70 //===============================================
71 RecoveryUI::~RecoveryUI()
72 {
73 }
74 
75 //===============================================
76 ::rtl::OUString SAL_CALL RecoveryUI::getImplementationName()
77     throw(css::uno::RuntimeException)
78 {
79     return RecoveryUI::st_getImplementationName();
80 }
81 
82 //===============================================
83 sal_Bool SAL_CALL RecoveryUI::supportsService(const ::rtl::OUString& sServiceName)
84     throw(css::uno::RuntimeException)
85 {
86     const css::uno::Sequence< ::rtl::OUString > lServices = RecoveryUI::st_getSupportedServiceNames();
87           sal_Int32                             c         = lServices.getLength();
88           sal_Int32                             i         = 0;
89     for (i=0; i<c; ++i)
90     {
91         const ::rtl::OUString& sSupportedService = lServices[i];
92         if (sSupportedService.equals(sServiceName))
93             return sal_True;
94     }
95     return sal_False;
96 }
97 
98 //===============================================
99 css::uno::Sequence< ::rtl::OUString > SAL_CALL RecoveryUI::getSupportedServiceNames()
100     throw(css::uno::RuntimeException)
101 {
102     return RecoveryUI::st_getSupportedServiceNames();
103 }
104 
105 //===============================================
106 css::uno::Any SAL_CALL RecoveryUI::dispatchWithReturnValue(const css::util::URL& aURL,
107                                                    const css::uno::Sequence< css::beans::PropertyValue >& )
108     throw(css::uno::RuntimeException)
109 {
110     // Internaly we use VCL ... every call into vcl based code must
111     // be guarded by locking the global solar mutex.
112     ::vos::OGuard aSolarLock(&Application::GetSolarMutex());
113 
114     css::uno::Any aRet;
115     RecoveryUI::EJob eJob = impl_classifyJob(aURL);
116     // TODO think about outside arguments
117 
118     switch(eJob)
119     {
120         case RecoveryUI::E_DO_EMERGENCY_SAVE :
121         {
122             sal_Bool bRet = impl_doEmergencySave();
123             aRet <<= bRet;
124             break;
125         }
126 
127         case RecoveryUI::E_DO_RECOVERY :
128             impl_doRecovery();
129             break;
130 
131         case RecoveryUI::E_DO_CRASHREPORT :
132             impl_doCrashReport();
133             break;
134 
135         default :
136             break;
137     }
138 
139     return aRet;
140 }
141 
142 //===============================================
143 void SAL_CALL RecoveryUI::dispatch(const css::util::URL&                                  aURL      ,
144                                    const css::uno::Sequence< css::beans::PropertyValue >& lArguments)
145     throw(css::uno::RuntimeException)
146 {
147     // recycle this method :-)
148     dispatchWithReturnValue(aURL, lArguments);
149 }
150 
151 //===============================================
152 void SAL_CALL RecoveryUI::addStatusListener(const css::uno::Reference< css::frame::XStatusListener >&, const css::util::URL& ) throw(css::uno::RuntimeException)
153 {
154     // TODO
155     OSL_ENSURE(sal_False, "RecoveryUI::addStatusListener()\nNot implemented yet!");
156 }
157 
158 //===============================================
159 void SAL_CALL RecoveryUI::removeStatusListener(const css::uno::Reference< css::frame::XStatusListener >&, const css::util::URL& )
160     throw(css::uno::RuntimeException)
161 {
162     // TODO
163     OSL_ENSURE(sal_False, "RecoveryUI::removeStatusListener()\nNot implemented yet!");
164 }
165 
166 //===============================================
167 ::rtl::OUString RecoveryUI::st_getImplementationName()
168 {
169     static ::rtl::OUString IMPLEMENTATIONNAME = IMPLEMENTATIONNAME_RECOVERYUI;
170     return IMPLEMENTATIONNAME;
171 }
172 
173 //===============================================
174 css::uno::Sequence< ::rtl::OUString > RecoveryUI::st_getSupportedServiceNames()
175 {
176     css::uno::Sequence< ::rtl::OUString > lServiceNames(1);    lServiceNames.getArray() [0] = SERVICENAME_RECOVERYUI;
177     return lServiceNames;
178 }
179 
180 //===============================================
181 css::uno::Reference< css::uno::XInterface > SAL_CALL RecoveryUI::st_createInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& xSMGR)
182 {
183     RecoveryUI* pNew = new RecoveryUI(xSMGR);
184     return css::uno::Reference< css::uno::XInterface >(static_cast< css::lang::XServiceInfo* >(pNew));
185 }
186 
187 //===============================================
188 
189 static OUString GetCrashConfigDir()
190 {
191 
192 #if defined(WNT) || defined(OS2)
193 	OUString	ustrValue = OUString::createFromAscii("${$BRAND_BASE_DIR/program/bootstrap.ini:UserInstallation}");
194 #elif defined(MACOSX)
195 	OUString	ustrValue = OUString::createFromAscii("~");
196 #else
197 	OUString	ustrValue = OUString::createFromAscii("$SYSUSERCONFIG");
198 #endif
199 	Bootstrap::expandMacros( ustrValue );
200 
201 #if defined(WNT) || defined(OS2)
202 	ustrValue += OUString::createFromAscii("/user/crashdata");
203 #endif
204 	return ustrValue;
205 }
206 
207 //===============================================
208 
209 #if defined(WNT) || defined(OS2)
210 #define LCKFILE "crashdat.lck"
211 #else
212 #define LCKFILE ".crash_report_unsent"
213 #endif
214 
215 
216 static OUString GetUnsentURL()
217 {
218 	OUString	aURL = GetCrashConfigDir();
219 
220 	aURL += OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) );
221 	aURL += OUString( RTL_CONSTASCII_USTRINGPARAM( LCKFILE ) );
222 
223 	return aURL;
224 }
225 
226 //===============================================
227 
228 static bool new_crash_pending()
229 {
230 	OUString	aUnsentURL = GetUnsentURL();
231 	File	aFile( aUnsentURL );
232 
233 	if ( FileBase::E_None == aFile.open( OpenFlag_Read ) )
234 	{
235 		aFile.close();
236 		return true;
237 	}
238 
239 	return false;
240 }
241 //===============================================
242 
243 static bool delete_pending_crash()
244 {
245 	OUString	aUnsentURL = GetUnsentURL();
246 	return ( FileBase::E_None == File::remove( aUnsentURL ) );
247 }
248 
249 RecoveryUI::EJob RecoveryUI::impl_classifyJob(const css::util::URL& aURL)
250 {
251     m_eJob = RecoveryUI::E_JOB_UNKNOWN;
252     if (aURL.Protocol.equals(RECOVERY_CMDPART_PROTOCOL))
253     {
254         if (aURL.Path.equals(RECOVERY_CMDPART_DO_EMERGENCY_SAVE))
255             m_eJob = RecoveryUI::E_DO_EMERGENCY_SAVE;
256         else
257         if (aURL.Path.equals(RECOVERY_CMDPART_DO_RECOVERY))
258             m_eJob = RecoveryUI::E_DO_RECOVERY;
259         else
260         if (aURL.Path.equals(RECOVERY_CMDPART_DO_CRASHREPORT))
261             m_eJob = RecoveryUI::E_DO_CRASHREPORT;
262     }
263 
264     return m_eJob;
265 }
266 
267 //===============================================
268 sal_Bool RecoveryUI::impl_doEmergencySave()
269 {
270     // create core service, which implements the real "emergency save" algorithm.
271     svxdr::RecoveryCore* pCore = new svxdr::RecoveryCore(m_xSMGR, sal_True);
272     css::uno::Reference< css::frame::XStatusListener > xCore(pCore);
273 
274     // create all needed dialogs for this operation
275     // and bind it to the used core service
276     svxdr::TabDialog4Recovery* pWizard = new svxdr::TabDialog4Recovery(m_pParentWindow);
277     svxdr::IExtendedTabPage*   pPage1  = new svxdr::SaveDialog        (pWizard, pCore );
278     pWizard->addTabPage(pPage1);
279 
280     // start the wizard
281     short nRet = pWizard->Execute();
282 
283     delete pPage1 ;
284     delete pWizard;
285 
286     return (nRet==DLG_RET_OK_AUTOLUNCH);
287 }
288 
289 //===============================================
290 void RecoveryUI::impl_doRecovery()
291 {
292     sal_Bool bRecoveryOnly( sal_False );
293 
294     ::rtl::OUString CFG_PACKAGE_RECOVERY( RTL_CONSTASCII_USTRINGPARAM  ( "org.openoffice.Office.Recovery/" ));
295     ::rtl::OUString CFG_PATH_CRASHREPORTER( RTL_CONSTASCII_USTRINGPARAM( "CrashReporter"                 ));
296     ::rtl::OUString CFG_ENTRY_ENABLED( RTL_CONSTASCII_USTRINGPARAM     ( "Enabled"                       ));
297 
298     sal_Bool bCrashRepEnabled( sal_True );
299     css::uno::Any aVal = ::comphelper::ConfigurationHelper::readDirectKey(
300                                 m_xSMGR,
301                                 CFG_PACKAGE_RECOVERY,
302                                 CFG_PATH_CRASHREPORTER,
303                                 CFG_ENTRY_ENABLED,
304                                 ::comphelper::ConfigurationHelper::E_READONLY);
305     aVal >>= bCrashRepEnabled;
306     bRecoveryOnly = !bCrashRepEnabled;
307 
308     // create core service, which implements the real "emergency save" algorithm.
309     svxdr::RecoveryCore* pCore = new svxdr::RecoveryCore(m_xSMGR, sal_False);
310     css::uno::Reference< css::frame::XStatusListener > xCore(pCore);
311 
312     // create all needed dialogs for this operation
313     // and bind it to the used core service
314     svxdr::TabDialog4Recovery* pWizard = new svxdr::TabDialog4Recovery   (m_pParentWindow);
315     svxdr::IExtendedTabPage*   pPage1  = new svxdr::RecoveryDialog       (pWizard, pCore );
316     svxdr::IExtendedTabPage*   pPage2  = 0;
317     svxdr::IExtendedTabPage*   pPage3  = 0;
318 
319     pWizard->addTabPage(pPage1);
320     if ( !bRecoveryOnly && new_crash_pending() )
321     {
322         pPage2 = new svxdr::ErrorRepWelcomeDialog(pWizard        );
323         pPage3 = new svxdr::ErrorRepSendDialog   (pWizard        );
324         pWizard->addTabPage(pPage2);
325         pWizard->addTabPage(pPage3);
326     }
327 
328     // start the wizard
329     pWizard->Execute();
330 
331     impl_showAllRecoveredDocs();
332 
333     delete pPage3 ;
334     delete pPage2 ;
335     delete pPage1 ;
336     delete pWizard;
337 
338 	delete_pending_crash();
339 }
340 
341 //===============================================
342 
343 void RecoveryUI::impl_doCrashReport()
344 {
345 	if ( new_crash_pending() )
346 	{
347 		svxdr::TabDialog4Recovery* pWizard = new svxdr::TabDialog4Recovery   (m_pParentWindow   );
348 		svxdr::IExtendedTabPage*   pPage1  = new svxdr::ErrorRepWelcomeDialog(pWizard, sal_False);
349 		svxdr::IExtendedTabPage*   pPage2  = new svxdr::ErrorRepSendDialog   (pWizard           );
350 		pWizard->addTabPage(pPage1);
351 		pWizard->addTabPage(pPage2);
352 
353 		// start the wizard
354 		pWizard->Execute();
355 
356 		delete pPage2 ;
357 		delete pPage1 ;
358 		delete pWizard;
359 
360 		delete_pending_crash();
361 	}
362 }
363 
364 //===============================================
365 void RecoveryUI::impl_showAllRecoveredDocs()
366 {
367     css::uno::Reference< css::frame::XFramesSupplier > xDesktop(
368         m_xSMGR->createInstance(SERVICENAME_DESKTOP),
369         css::uno::UNO_QUERY_THROW);
370 
371     css::uno::Reference< css::container::XIndexAccess > xTaskContainer(
372         xDesktop->getFrames(),
373         css::uno::UNO_QUERY_THROW);
374 
375     sal_Int32 c = xTaskContainer->getCount();
376     sal_Int32 i = 0;
377     for (i=0; i<c; ++i)
378     {
379         try
380         {
381             css::uno::Reference< css::frame::XFrame > xTask;
382             xTaskContainer->getByIndex(i) >>= xTask;
383             if (!xTask.is())
384                 continue;
385 
386             css::uno::Reference< css::awt::XWindow > xWindow = xTask->getContainerWindow();
387             if (!xWindow.is())
388                 continue;
389 
390             xWindow->setVisible(sal_True);
391         }
392         catch(const css::uno::RuntimeException& exRun)
393             { throw exRun; }
394         catch(const css::uno::Exception&)
395             { continue; }
396     }
397 }
398 
399 } // namespace svx
400