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_extensions.hxx" 30 31 #include <memory> 32 33 #include "updatecheck.hxx" 34 #include "updatecheckconfig.hxx" 35 #include "updatehdl.hxx" 36 #include "updateprotocol.hxx" 37 38 #include <cppuhelper/implbase3.hxx> 39 #include <cppuhelper/implementationentry.hxx> 40 41 #include "com/sun/star/frame/XDesktop.hpp" 42 #include "com/sun/star/frame/XTerminateListener.hpp" 43 #include <com/sun/star/task/XJob.hpp> 44 45 namespace beans = com::sun::star::beans ; 46 namespace frame = com::sun::star::frame ; 47 namespace lang = com::sun::star::lang ; 48 namespace task = com::sun::star::task ; 49 namespace uno = com::sun::star::uno ; 50 51 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) 52 53 namespace 54 { 55 56 class InitUpdateCheckJobThread : public osl::Thread 57 { 58 public: 59 InitUpdateCheckJobThread( const uno::Reference< uno::XComponentContext > &xContext, 60 const uno::Sequence< beans::NamedValue > &xParameters, 61 bool bShowDialog ); 62 63 virtual void SAL_CALL run(); 64 65 void setTerminating(); 66 67 private: 68 osl::Condition m_aCondition; 69 uno::Reference<uno::XComponentContext> m_xContext; 70 uno::Sequence<beans::NamedValue> m_xParameters; 71 bool m_bShowDialog; 72 bool m_bTerminating; 73 }; 74 75 class UpdateCheckJob : 76 public ::cppu::WeakImplHelper3< task::XJob, lang::XServiceInfo, frame::XTerminateListener > 77 { 78 virtual ~UpdateCheckJob(); 79 80 public: 81 82 UpdateCheckJob(const uno::Reference<uno::XComponentContext>& xContext); 83 84 static uno::Sequence< rtl::OUString > getServiceNames(); 85 static rtl::OUString getImplName(); 86 87 // Allows runtime exceptions to be thrown by const methods 88 inline SAL_CALL operator uno::Reference< uno::XInterface > () const 89 { return const_cast< cppu::OWeakObject * > (static_cast< cppu::OWeakObject const * > (this)); }; 90 91 // XJob 92 virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&) 93 throw (lang::IllegalArgumentException, uno::Exception); 94 95 // XServiceInfo 96 virtual rtl::OUString SAL_CALL getImplementationName() 97 throw (uno::RuntimeException); 98 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName) 99 throw (uno::RuntimeException); 100 virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames() 101 throw (uno::RuntimeException); 102 103 // XEventListener 104 virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt ) 105 throw (::com::sun::star::uno::RuntimeException); 106 107 // XTerminateListener 108 virtual void SAL_CALL queryTermination( lang::EventObject const & evt ) 109 throw ( frame::TerminationVetoException, uno::RuntimeException ); 110 virtual void SAL_CALL notifyTermination( lang::EventObject const & evt ) 111 throw ( uno::RuntimeException ); 112 113 private: 114 uno::Reference<uno::XComponentContext> m_xContext; 115 uno::Reference< frame::XDesktop > m_xDesktop; 116 std::auto_ptr< InitUpdateCheckJobThread > m_pInitThread; 117 118 void handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp ); 119 }; 120 121 //------------------------------------------------------------------------------ 122 //------------------------------------------------------------------------------ 123 //------------------------------------------------------------------------------ 124 InitUpdateCheckJobThread::InitUpdateCheckJobThread( 125 const uno::Reference< uno::XComponentContext > &xContext, 126 const uno::Sequence< beans::NamedValue > &xParameters, 127 bool bShowDialog ) : 128 m_xContext( xContext ), 129 m_xParameters( xParameters ), 130 m_bShowDialog( bShowDialog ), 131 m_bTerminating( false ) 132 { 133 create(); 134 } 135 136 //------------------------------------------------------------------------------ 137 void SAL_CALL InitUpdateCheckJobThread::run() 138 { 139 if (!m_bShowDialog) { 140 TimeValue tv = { 25, 0 }; 141 m_aCondition.wait( &tv ); 142 if ( m_bTerminating ) 143 return; 144 } 145 146 rtl::Reference< UpdateCheck > aController( UpdateCheck::get() ); 147 aController->initialize( m_xParameters, m_xContext ); 148 149 if ( m_bShowDialog ) 150 aController->showDialog( true ); 151 } 152 153 void InitUpdateCheckJobThread::setTerminating() { 154 m_bTerminating = true; 155 m_aCondition.set(); 156 } 157 158 //------------------------------------------------------------------------------ 159 //------------------------------------------------------------------------------ 160 //------------------------------------------------------------------------------ 161 162 UpdateCheckJob::UpdateCheckJob( const uno::Reference<uno::XComponentContext>& xContext ) : 163 m_xContext(xContext) 164 { 165 m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext( UNISTRING("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY ); 166 if ( m_xDesktop.is() ) 167 m_xDesktop->addTerminateListener( this ); 168 } 169 170 //------------------------------------------------------------------------------ 171 172 UpdateCheckJob::~UpdateCheckJob() 173 { 174 } 175 176 //------------------------------------------------------------------------------ 177 178 uno::Sequence< rtl::OUString > 179 UpdateCheckJob::getServiceNames() 180 { 181 uno::Sequence< rtl::OUString > aServiceList(1); 182 aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheck"); 183 return aServiceList; 184 }; 185 186 //------------------------------------------------------------------------------ 187 188 rtl::OUString 189 UpdateCheckJob::getImplName() 190 { 191 return UNISTRING( "vnd.sun.UpdateCheck"); 192 } 193 194 195 //------------------------------------------------------------------------------ 196 197 uno::Any 198 UpdateCheckJob::execute(const uno::Sequence<beans::NamedValue>& namedValues) 199 throw (lang::IllegalArgumentException, uno::Exception) 200 { 201 for ( sal_Int32 n=namedValues.getLength(); n-- > 0; ) 202 { 203 if ( namedValues[ n ].Name.equalsAscii( "DynamicData" ) ) 204 { 205 uno::Sequence<beans::NamedValue> aListProp; 206 if ( namedValues[n].Value >>= aListProp ) 207 { 208 for ( sal_Int32 i=aListProp.getLength(); i-- > 0; ) 209 { 210 if ( aListProp[ i ].Name.equalsAscii( "updateList" ) ) 211 { 212 handleExtensionUpdates( aListProp ); 213 return uno::Any(); 214 } 215 } 216 } 217 } 218 } 219 220 uno::Sequence<beans::NamedValue> aConfig = 221 getValue< uno::Sequence<beans::NamedValue> > (namedValues, "JobConfig"); 222 223 /* Determine the way we got invoked here - 224 * see Developers Guide Chapter "4.7.2 Jobs" to understand the magic 225 */ 226 227 uno::Sequence<beans::NamedValue> aEnvironment = 228 getValue< uno::Sequence<beans::NamedValue> > (namedValues, "Environment"); 229 230 rtl::OUString aEventName = getValue< rtl::OUString > (aEnvironment, "EventName"); 231 232 m_pInitThread.reset( 233 new InitUpdateCheckJobThread( 234 m_xContext, aConfig, 235 !aEventName.equalsAscii("onFirstVisibleTask"))); 236 237 return uno::Any(); 238 } 239 240 //------------------------------------------------------------------------------ 241 void UpdateCheckJob::handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp ) 242 { 243 try { 244 uno::Sequence< uno::Sequence< rtl::OUString > > aList = 245 getValue< uno::Sequence< uno::Sequence< rtl::OUString > > > ( rListProp, "updateList" ); 246 bool bPrepareOnly = getValue< bool > ( rListProp, "prepareOnly" ); 247 248 // we will first store any new found updates and then check, if there are any 249 // pending updates. 250 storeExtensionUpdateInfos( m_xContext, aList ); 251 252 if ( bPrepareOnly ) 253 return; 254 255 bool bHasUpdates = checkForPendingUpdates( m_xContext ); 256 257 rtl::Reference<UpdateCheck> aController( UpdateCheck::get() ); 258 if ( ! aController.is() ) 259 return; 260 261 aController->setHasExtensionUpdates( bHasUpdates ); 262 263 if ( ! aController->hasOfficeUpdate() ) 264 { 265 if ( bHasUpdates ) 266 aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL, true ); 267 else 268 aController->setUIState( UPDATESTATE_NO_UPDATE_AVAIL, true ); 269 } 270 } 271 catch( const uno::Exception& e ) 272 { 273 OSL_TRACE( "Caught exception: %s\n thread terminated.\n", 274 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr()); 275 } 276 } 277 278 //------------------------------------------------------------------------------ 279 280 rtl::OUString SAL_CALL 281 UpdateCheckJob::getImplementationName() throw (uno::RuntimeException) 282 { 283 return getImplName(); 284 } 285 286 //------------------------------------------------------------------------------ 287 288 uno::Sequence< rtl::OUString > SAL_CALL 289 UpdateCheckJob::getSupportedServiceNames() throw (uno::RuntimeException) 290 { 291 return getServiceNames(); 292 } 293 294 //------------------------------------------------------------------------------ 295 296 sal_Bool SAL_CALL 297 UpdateCheckJob::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException) 298 { 299 uno::Sequence< rtl::OUString > aServiceNameList = getServiceNames(); 300 301 for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ ) 302 if( aServiceNameList[n].equals(serviceName) ) 303 return sal_True; 304 305 return sal_False; 306 } 307 308 //------------------------------------------------------------------------------ 309 // XEventListener 310 void SAL_CALL UpdateCheckJob::disposing( lang::EventObject const & rEvt ) 311 throw ( uno::RuntimeException ) 312 { 313 bool shutDown = ( rEvt.Source == m_xDesktop ); 314 315 if ( shutDown && m_xDesktop.is() ) 316 { 317 m_xDesktop->removeTerminateListener( this ); 318 m_xDesktop.clear(); 319 } 320 } 321 322 //------------------------------------------------------------------------------ 323 // XTerminateListener 324 void SAL_CALL UpdateCheckJob::queryTermination( lang::EventObject const & ) 325 throw ( frame::TerminationVetoException, uno::RuntimeException ) 326 { 327 } 328 329 //------------------------------------------------------------------------------ 330 void SAL_CALL UpdateCheckJob::notifyTermination( lang::EventObject const & ) 331 throw ( uno::RuntimeException ) 332 { 333 if ( m_pInitThread.get() != 0 ) 334 { 335 m_pInitThread->setTerminating(); 336 m_pInitThread->join(); 337 } 338 } 339 340 } // anonymous namespace 341 342 //------------------------------------------------------------------------------ 343 344 static uno::Reference<uno::XInterface> SAL_CALL 345 createJobInstance(const uno::Reference<uno::XComponentContext>& xContext) 346 { 347 return *new UpdateCheckJob(xContext); 348 } 349 350 //------------------------------------------------------------------------------ 351 352 static uno::Reference<uno::XInterface> SAL_CALL 353 createConfigInstance(const uno::Reference<uno::XComponentContext>& xContext) 354 { 355 return *UpdateCheckConfig::get(xContext, *UpdateCheck::get()); 356 } 357 358 //------------------------------------------------------------------------------ 359 360 static const cppu::ImplementationEntry kImplementations_entries[] = 361 { 362 { 363 createJobInstance, 364 UpdateCheckJob::getImplName, 365 UpdateCheckJob::getServiceNames, 366 cppu::createSingleComponentFactory, 367 NULL, 368 0 369 }, 370 { 371 createConfigInstance, 372 UpdateCheckConfig::getImplName, 373 UpdateCheckConfig::getServiceNames, 374 cppu::createSingleComponentFactory, 375 NULL, 376 0 377 }, 378 { NULL, NULL, NULL, NULL, NULL, 0 } 379 } ; 380 381 //------------------------------------------------------------------------------ 382 383 extern "C" void SAL_CALL 384 component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **) 385 { 386 *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; 387 } 388 389 //------------------------------------------------------------------------------ 390 391 extern "C" void * 392 component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey) 393 { 394 return cppu::component_getFactoryHelper( 395 pszImplementationName, 396 pServiceManager, 397 pRegistryKey, 398 kImplementations_entries) ; 399 } 400