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