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 throw(css::uno::RuntimeException)
74 {
75 return RecoveryUI::st_getImplementationName();
76 }
77
78 //===============================================
supportsService(const::rtl::OUString & sServiceName)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 //===============================================
getSupportedServiceNames()95 css::uno::Sequence< ::rtl::OUString > SAL_CALL RecoveryUI::getSupportedServiceNames()
96 throw(css::uno::RuntimeException)
97 {
98 return RecoveryUI::st_getSupportedServiceNames();
99 }
100
101 //===============================================
dispatchWithReturnValue(const css::util::URL & aURL,const css::uno::Sequence<css::beans::PropertyValue> &)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 //===============================================
dispatch(const css::util::URL & aURL,const css::uno::Sequence<css::beans::PropertyValue> & lArguments)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 //===============================================
addStatusListener(const css::uno::Reference<css::frame::XStatusListener> &,const css::util::URL &)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 //===============================================
removeStatusListener(const css::uno::Reference<css::frame::XStatusListener> &,const css::util::URL &)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 //===============================================
st_getImplementationName()163 ::rtl::OUString RecoveryUI::st_getImplementationName()
164 {
165 static ::rtl::OUString IMPLEMENTATIONNAME = IMPLEMENTATIONNAME_RECOVERYUI;
166 return IMPLEMENTATIONNAME;
167 }
168
169 //===============================================
st_getSupportedServiceNames()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 //===============================================
st_createInstance(const css::uno::Reference<css::lang::XMultiServiceFactory> & xSMGR)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
GetCrashConfigDir()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
GetUnsentURL()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
new_crash_pending()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
delete_pending_crash()239 static bool delete_pending_crash()
240 {
241 OUString aUnsentURL = GetUnsentURL();
242 return ( FileBase::E_None == File::remove( aUnsentURL ) );
243 }
244
impl_classifyJob(const css::util::URL & aURL)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 //===============================================
impl_doEmergencySave()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 //===============================================
impl_doRecovery()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
impl_doCrashReport()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 //===============================================
impl_showAllRecoveredDocs()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