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