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