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 { 74 return RecoveryUI::st_getImplementationName(); 75 } 76 77 //=============================================== 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 //=============================================== 93 css::uno::Sequence< ::rtl::OUString > SAL_CALL RecoveryUI::getSupportedServiceNames() 94 { 95 return RecoveryUI::st_getSupportedServiceNames(); 96 } 97 98 //=============================================== 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 //=============================================== 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 //=============================================== 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 //=============================================== 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 //=============================================== 157 ::rtl::OUString RecoveryUI::st_getImplementationName() 158 { 159 static ::rtl::OUString IMPLEMENTATIONNAME = IMPLEMENTATIONNAME_RECOVERYUI; 160 return IMPLEMENTATIONNAME; 161 } 162 163 //=============================================== 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 //=============================================== 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 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 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 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 233 static bool delete_pending_crash() 234 { 235 OUString aUnsentURL = GetUnsentURL(); 236 return ( FileBase::E_None == File::remove( aUnsentURL ) ); 237 } 238 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 //=============================================== 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 //=============================================== 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 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 //=============================================== 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