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