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