diff options
Diffstat (limited to 'extensions/source/update/check/updatecheck.cxx')
-rw-r--r-- | extensions/source/update/check/updatecheck.cxx | 1692 |
1 files changed, 1692 insertions, 0 deletions
diff --git a/extensions/source/update/check/updatecheck.cxx b/extensions/source/update/check/updatecheck.cxx new file mode 100644 index 000000000000..1e0366f6de11 --- /dev/null +++ b/extensions/source/update/check/updatecheck.cxx @@ -0,0 +1,1692 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_extensions.hxx" + +#include "updatecheck.hxx" + +#include <cppuhelper/implbase1.hxx> +#include <com/sun/star/beans/XFastPropertySet.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/frame/XDesktop.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/DispatchResultEvent.hpp> +#include <com/sun/star/frame/DispatchResultState.hpp> +#include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/system/SystemShellExecuteFlags.hpp> +#include <com/sun/star/task/XJob.hpp> +#include <com/sun/star/task/XJobExecutor.hpp> + +#include <rtl/ustrbuf.hxx> + +#include <rtl/bootstrap.hxx> +#include <osl/process.h> +#include <osl/module.hxx> +#include <osl/file.hxx> +#include <sal/macros.h> + +#ifdef WNT +#ifdef _MSC_VER +#pragma warning(push,1) // disable warnings within system headers +//#pragma warning(disable: 4917) +#endif +#include <objbase.h> +#ifdef _MSC_VER +#pragma warning(pop) +#endif +#endif + +#include "updateprotocol.hxx" +#include "updatecheckconfig.hxx" + +namespace awt = com::sun::star::awt ; +namespace beans = com::sun::star::beans ; +namespace container = com::sun::star::container ; +namespace deployment = com::sun::star::deployment ; +namespace frame = com::sun::star::frame ; +namespace lang = com::sun::star::lang ; +namespace c3s = com::sun::star::system ; +namespace task = com::sun::star::task ; +namespace util = com::sun::star::util ; +namespace uno = com::sun::star::uno ; + +#define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s)) + +#define PROPERTY_TITLE UNISTRING("BubbleHeading") +#define PROPERTY_TEXT UNISTRING("BubbleText") +#define PROPERTY_IMAGE UNISTRING("BubbleImageURL") +#define PROPERTY_SHOW_BUBBLE UNISTRING("BubbleVisible") +#define PROPERTY_CLICK_HDL UNISTRING("MenuClickHDL") +#define PROPERTY_DEFAULT_TITLE UNISTRING("DefaultHeading") +#define PROPERTY_DEFAULT_TEXT UNISTRING("DefaultText") +#define PROPERTY_SHOW_MENUICON UNISTRING("MenuIconVisible") + +//------------------------------------------------------------------------------ + +// Returns the URL of the release note for the given position +rtl::OUString getReleaseNote(const UpdateInfo& rInfo, sal_uInt8 pos, bool autoDownloadEnabled) +{ + std::vector< ReleaseNote >::const_iterator iter = rInfo.ReleaseNotes.begin(); + while( iter != rInfo.ReleaseNotes.end() ) + { + if( pos == iter->Pos ) + { + if( (pos > 2) || !autoDownloadEnabled || ! (iter->URL2.getLength() > 0) ) + return iter->URL; + } + else if( (pos == iter->Pos2) && ((1 == iter->Pos) || (2 == iter->Pos)) && autoDownloadEnabled ) + return iter->URL2; + + ++iter; + } + + return rtl::OUString(); +} + +//------------------------------------------------------------------------------ + +namespace +{ + +static inline rtl::OUString getBuildId() +{ + rtl::OUString aPathVal(UNISTRING("${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}")); + rtl::Bootstrap::expandMacros(aPathVal); + return aPathVal; +} + +//------------------------------------------------------------------------------ +static inline rtl::OUString getBaseInstallation() +{ + rtl::OUString aPathVal(UNISTRING("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":BaseInstallation}")); + rtl::Bootstrap::expandMacros(aPathVal); + return aPathVal; +} + +//------------------------------------------------------------------------------ + +inline bool isObsoleteUpdateInfo(const rtl::OUString& rBuildId) +{ + return sal_True != rBuildId.equals(getBuildId()) && rBuildId.getLength() > 0; +} + + +//------------------------------------------------------------------------------ + +rtl::OUString getImageFromFileName(const rtl::OUString& aFile) +{ +#ifndef WNT + rtl::OUString aUnpackPath; + if( osl_getExecutableFile(&aUnpackPath.pData) == osl_Process_E_None ) + { + sal_uInt32 lastIndex = aUnpackPath.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aUnpackPath = aUnpackPath.copy( 0, lastIndex+1 ); + aUnpackPath += UNISTRING( "unpack_update" ); + } + + oslFileHandle hOut = NULL; + oslProcess hProcess = NULL; + + rtl::OUString aSystemPath; + osl::File::getSystemPathFromFileURL(aFile, aSystemPath); + + oslProcessError rc = osl_executeProcess_WithRedirectedIO( + aUnpackPath.pData, // [in] Image name + &aSystemPath.pData, 1, // [in] Arguments + osl_Process_WAIT || osl_Process_NORMAL, // [in] Options + NULL, // [in] Security + NULL, // [in] Working directory + NULL, 0, // [in] Environment variables + &hProcess, // [out] Process handle + NULL, &hOut, NULL // [out] File handles for redirected I/O + ); + + if( osl_Process_E_None == rc ) + { + oslProcessInfo aInfo; + aInfo.Size = sizeof(oslProcessInfo); + + if( osl_Process_E_None == osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo) ) + { + if( 0 == aInfo.Code ) + { + sal_Char szBuffer[4096]; + sal_uInt64 nBytesRead = 0; + const sal_uInt64 nBytesToRead = sizeof(szBuffer) - 1; + + rtl::OUString aImageName; + while( osl_File_E_None == osl_readFile(hOut, szBuffer, nBytesToRead, &nBytesRead) ) + { + sal_Char *pc = szBuffer + nBytesRead; + do + { + *pc = '\0'; --pc; + } + while( ('\n' == *pc) || ('\r' == *pc) ); + + aImageName += rtl::OUString(szBuffer, pc - szBuffer + 1, osl_getThreadTextEncoding()); + + if( nBytesRead < nBytesToRead ) + break; + } + + if( osl::FileBase::E_None == osl::FileBase::getFileURLFromSystemPath(aImageName, aImageName) ) + return aImageName; + } + } + + osl_closeFile(hOut); + osl_freeProcessHandle(hProcess); + } + } +#endif + + return aFile; +} + + +//------------------------------------------------------------------------------ + +static uno::Reference< beans::XPropertySet > createMenuBarUI( + const uno::Reference< uno::XComponentContext >& xContext, + const uno::Reference< task::XJob >& xJob) +{ + if( !xContext.is() ) + throw uno::RuntimeException( + UNISTRING( "UpdateCheckJob: empty component context" ), uno::Reference< uno::XInterface > () ); + + uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager()); + if( !xServiceManager.is() ) + throw uno::RuntimeException( + UNISTRING( "UpdateCheckJob: unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () ); + + uno::Reference< beans::XPropertySet > xMenuBarUI = + uno::Reference< beans::XPropertySet > ( + xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.setup.UpdateCheckUI" ), xContext ), + uno::UNO_QUERY_THROW); + + xMenuBarUI->setPropertyValue( PROPERTY_CLICK_HDL, uno::makeAny( xJob ) ); + + return xMenuBarUI; +} + +//------------------------------------------------------------------------------ + + + +typedef sal_Bool (* OnlineCheckFunc) (); + +class UpdateCheckThread : public WorkerThread +{ + +public: + UpdateCheckThread( osl::Condition& rCondition, + const uno::Reference<uno::XComponentContext>& xContext ); + + virtual void SAL_CALL join(); + virtual void SAL_CALL terminate(); + virtual void SAL_CALL cancel(); + +protected: + virtual ~UpdateCheckThread(); + + virtual void SAL_CALL run(); + virtual void SAL_CALL onTerminated(); + + /* Wrapper around checkForUpdates */ + bool runCheck( bool & rbExtensionsChecked ); + +private: + + /* Used to avoid dialup login windows (on platforms we know how to double this) */ + inline bool hasInternetConnection() const + { + if(m_pHasInternetConnection != NULL ) + return (sal_True == m_pHasInternetConnection()); + return true; + } + + /* Creates a new instance of UpdateInformationProvider and returns this instance */ + inline uno::Reference<deployment::XUpdateInformationProvider> createProvider() + { + osl::MutexGuard aGuard(m_aMutex); + m_xProvider = deployment::UpdateInformationProvider::create(m_xContext); + return m_xProvider; + }; + + /* Returns the remembered instance of UpdateInformationProvider if any */ + inline uno::Reference<deployment::XUpdateInformationProvider> getProvider() + { osl::MutexGuard aGuard(m_aMutex); return m_xProvider; }; + + /* Releases the remembered instance of UpdateInformationProvider if any */ + inline void clearProvider() + { osl::MutexGuard aGuard(m_aMutex); m_xProvider.clear(); }; + + osl::Mutex m_aMutex; + osl::Module m_aModule; + +protected: + osl::Condition& m_aCondition; + +private: + +// const + OnlineCheckFunc m_pHasInternetConnection; + + const uno::Reference<uno::XComponentContext> m_xContext; + uno::Reference<deployment::XUpdateInformationProvider> m_xProvider; +}; + + +class ManualUpdateCheckThread : public UpdateCheckThread +{ +public: + ManualUpdateCheckThread( osl::Condition& rCondition, const uno::Reference<uno::XComponentContext>& xContext ) : + UpdateCheckThread(rCondition, xContext) {}; + + virtual void SAL_CALL run(); +}; + + +class MenuBarButtonJob : public ::cppu::WeakImplHelper1< task::XJob > +{ +public: + MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck); + + // XJob + virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&) + throw (lang::IllegalArgumentException, uno::Exception); + +private: + rtl::Reference< UpdateCheck > m_aUpdateCheck; +}; + +class DownloadThread : public WorkerThread +{ +public: + DownloadThread( + osl::Condition& rCondition, + const uno::Reference<uno::XComponentContext>& xContext, + const rtl::Reference< DownloadInteractionHandler >& rHandler, + const rtl::OUString& rURL ); + + virtual void SAL_CALL run(); + virtual void SAL_CALL cancel(); + virtual void SAL_CALL suspend(); + virtual void SAL_CALL onTerminated(); + +protected: + ~DownloadThread(); + +private: + osl::Condition& m_aCondition; + const uno::Reference<uno::XComponentContext> m_xContext; + const rtl::OUString m_aURL; + Download m_aDownload; +}; + +//------------------------------------------------------------------------------ +class ShutdownThread : public osl::Thread +{ +public: + ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext ); + + virtual void SAL_CALL run(); + virtual void SAL_CALL onTerminated(); + +protected: + ~ShutdownThread(); + +private: + osl::Condition m_aCondition; + const uno::Reference<uno::XComponentContext> m_xContext; +}; + +//------------------------------------------------------------------------------ + +UpdateCheckThread::UpdateCheckThread( osl::Condition& rCondition, + const uno::Reference<uno::XComponentContext>& xContext ) : + m_aCondition(rCondition), + m_pHasInternetConnection(NULL), + m_xContext(xContext) +{ + +#ifdef WNT + rtl::OUString aPath; + if( osl_getExecutableFile(&aPath.pData) == osl_Process_E_None ) + { + sal_uInt32 lastIndex = aPath.lastIndexOf('/'); + if ( lastIndex > 0 ) + { + aPath = aPath.copy( 0, lastIndex+1 ); + aPath += UNISTRING( "onlinecheck" ); + } + + if ( m_aModule.load(aPath) ) + { + m_pHasInternetConnection = + reinterpret_cast < OnlineCheckFunc > ( + m_aModule.getFunctionSymbol( UNISTRING("hasInternetConnection"))); + } + } +#endif + + createSuspended(); + + // actually run the thread + resume(); +} + +//------------------------------------------------------------------------------ + +UpdateCheckThread::~UpdateCheckThread() +{ +} + +//------------------------------------------------------------------------------ + + +void SAL_CALL +UpdateCheckThread::terminate() +{ + // Cancel potentially hanging http request .. + cancel(); + // .. before terminating + osl::Thread::terminate(); +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +UpdateCheckThread::join() +{ + uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider()); + + // do not join during an update check until #i73893# is fixed + if( ! xProvider.is() ) + { + osl::Thread::join(); + } +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +UpdateCheckThread::cancel() +{ + uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider()); + + if( xProvider.is() ) + xProvider->cancel(); +} + +//------------------------------------------------------------------------------ + +bool +UpdateCheckThread::runCheck( bool & rbExtensionsChecked ) +{ + bool ret = false; + UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL; + + UpdateInfo aInfo; + rtl::Reference< UpdateCheck > aController(UpdateCheck::get()); + + if( checkForUpdates(aInfo, m_xContext, aController->getInteractionHandler(), createProvider()) ) + { + aController->setUpdateInfo(aInfo); + eUIState = aController->getUIState(aInfo); + ret = true; + } + else + aController->setCheckFailedState(); + + // We will only look for extension updates, when there is no 'check for office updates' dialog open + // and when there was no office update found + if ( ( eUIState != UPDATESTATE_UPDATE_AVAIL ) && + ( eUIState != UPDATESTATE_UPDATE_NO_DOWNLOAD ) && + !aController->isDialogShowing() && + !rbExtensionsChecked ) + { + bool bHasExtensionUpdates = checkForExtensionUpdates( m_xContext ); + aController->setHasExtensionUpdates( bHasExtensionUpdates ); + if ( bHasExtensionUpdates ) + aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL ); + rbExtensionsChecked = true; + } + + // joining with this thread is safe again + clearProvider(); + return ret; +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +UpdateCheckThread::onTerminated() +{ + delete this; +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +UpdateCheckThread::run() +{ + bool bExtensionsChecked = false; + TimeValue systime; + TimeValue nExtCheckTime; + osl_getSystemTime( &nExtCheckTime ); + + osl::Condition::Result aResult = osl::Condition::result_timeout; + TimeValue tv = { 10, 0 }; + + // Initial wait to avoid doing further time consuming tasks during start-up + aResult = m_aCondition.wait(&tv); + + try { + + while( sal_True == schedule() ) + { + /* Use cases: + * a) manual check requested from auto check thread - "last check" should not be checked (one time) + * a1) manual check was requested in the middle of a running auto check, + * condition is set + * a2) manual check was requested while waiting for a retry, + * condition is set + * a3) manual check was requested while waiting for time to next + * scheduled check elapsing, condition is set + * a4) manual check was requested during initial wait, condition is set + * b) check interval got changed, condition may be set - same sub-cases as a), + * but "last check" should be honored + * c) normal auto check mode, condition not set - "last check" should be honored + */ + + // Accessing const members without synchronization + rtl::Reference< UpdateCheck > aController(UpdateCheck::get()); + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *aController); + + // FIXME: remember last & offset ? + sal_Int64 last = rModel->getLastChecked(); + sal_Int64 offset = rModel->getCheckInterval(); + + rModel.clear(); + + // last == 0 means check immediately + bool checkNow = ! (last > 0); + + // Reset the condition to avoid busy loops + if( osl::Condition::result_ok == aResult ) + { + m_aCondition.reset(); + aResult = osl::Condition::result_timeout; + checkNow = aController->isDialogShowing(); + } + + if( ! checkNow ) + { + osl_getSystemTime(&systime); + + // Go back to sleep until time has elapsed + sal_Int64 next = last + offset; + if( last + offset > systime.Seconds ) + { + // This can not be > 32 Bit for now .. + tv.Seconds = static_cast< sal_Int32 > (next - systime.Seconds); + aResult = m_aCondition.wait(&tv); + continue; + } + } + + static sal_uInt8 n = 0; + + if( ! hasInternetConnection() || ! runCheck( bExtensionsChecked ) ) + { + // the extension update check should be independent from the office update check + // + osl_getSystemTime( &systime ); + if ( nExtCheckTime.Seconds + offset < systime.Seconds ) + bExtensionsChecked = false; + + // Increase next by 15, 60, .. minutes + static const sal_Int32 nRetryInterval[] = { 900, 3600, 14400, 86400 }; + + if( n < SAL_N_ELEMENTS(nRetryInterval) ) + ++n; + + tv.Seconds = nRetryInterval[n-1]; + aResult = m_aCondition.wait(&tv); + } + else // reset retry counter + { + n = 0; + bExtensionsChecked = false; + } + } + } + + catch(const uno::Exception& e) { + // Silently catch all errors + OSL_TRACE( "Caught exception: %s\n thread terminated.\n", + rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() ); + } +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +ManualUpdateCheckThread::run() +{ + bool bExtensionsChecked = false; + + try { + runCheck( bExtensionsChecked ); + m_aCondition.reset(); + } + catch(const uno::Exception& e) { + // Silently catch all errors + OSL_TRACE( "Caught exception: %s\n thread terminated.\n", + rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() ); + } +} + +//------------------------------------------------------------------------------ + +MenuBarButtonJob::MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck) : + m_aUpdateCheck(rUpdateCheck) +{ +}; + +//------------------------------------------------------------------------------ + +uno::Any SAL_CALL +MenuBarButtonJob::execute(const uno::Sequence<beans::NamedValue>& ) + throw (lang::IllegalArgumentException, uno::Exception) +{ + if ( m_aUpdateCheck->shouldShowExtUpdDlg() ) + m_aUpdateCheck->showExtensionDialog(); + else + m_aUpdateCheck->showDialog(); + + return uno::Any(); +} + +//------------------------------------------------------------------------------ + +DownloadThread::DownloadThread(osl::Condition& rCondition, + const uno::Reference<uno::XComponentContext>& xContext, + const rtl::Reference< DownloadInteractionHandler >& rHandler, + const rtl::OUString& rURL) : + m_aCondition(rCondition), + m_xContext(xContext), + m_aURL(rURL), + m_aDownload(xContext, rHandler) +{ + createSuspended(); +} + +//------------------------------------------------------------------------------ + +DownloadThread::~DownloadThread() +{ +} + +//------------------------------------------------------------------------------ + +void SAL_CALL +DownloadThread::run() +{ +#ifdef WNT + CoUninitialize(); + CoInitialize( NULL ); +#endif + + while( schedule() ) + { + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext); + + rtl::OUString aLocalFile = rModel->getLocalFileName(); + rtl::OUString aDownloadDest = rModel->getDownloadDestination(); + + // release config class for now + rModel.clear(); + + static sal_uInt8 n = 0; + if( ! m_aDownload.start(m_aURL, aLocalFile, aDownloadDest ) ) + { + // retry every 15s unless the dialog is not visible + TimeValue tv; + tv.Seconds = 15; + + if( ! UpdateCheck::get()->isDialogShowing() ) + { + // Increase next by 1, 5, 15, 60, .. minutes + static const sal_Int16 nRetryInterval[] = { 60, 300, 900, 3600 }; + + if( n < SAL_N_ELEMENTS(nRetryInterval) ) + ++n; + + tv.Seconds = nRetryInterval[n-1]; + } + m_aCondition.wait(&tv); + } + else + { + // reset wait period after successful download + n=0; + } + } +} + +//------------------------------------------------------------------------------ + +void SAL_CALL DownloadThread::cancel() +{ + m_aDownload.stop(); + resume(); + + rtl::Reference< UpdateCheck > aController(UpdateCheck::get()); + aController->cancelDownload(); +} + +//------------------------------------------------------------------------------ + +void SAL_CALL DownloadThread::suspend() +{ + osl::Thread::suspend(); + m_aDownload.stop(); +} + +//------------------------------------------------------------------------------ + +void SAL_CALL DownloadThread::onTerminated() +{ + delete this; +} + +//------------------------------------------------------------------------------ +ShutdownThread::ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext) : + m_xContext( xContext ) +{ + create(); +} + +//------------------------------------------------------------------------------ +ShutdownThread::~ShutdownThread() +{ +} + +//------------------------------------------------------------------------------ +void SAL_CALL +ShutdownThread::run() +{ + TimeValue tv = { 0, 250 }; + + m_aCondition.wait(&tv); + + // Tell QuickStarter not to veto .. + uno::Reference< beans::XFastPropertySet > xQuickStarter( + UpdateCheck::createService(UNISTRING("com.sun.star.office.Quickstart"), m_xContext), + uno::UNO_QUERY + ); + + if (xQuickStarter.is()) + xQuickStarter->setFastPropertyValue(0, uno::makeAny(false)); + + // Shutdown the office + uno::Reference< frame::XDesktop > xDesktop( + UpdateCheck::createService(UNISTRING("com.sun.star.frame.Desktop"), m_xContext), + uno::UNO_QUERY); + + if( xDesktop.is() ) + xDesktop->terminate(); +} + +//------------------------------------------------------------------------------ +void SAL_CALL ShutdownThread::onTerminated() +{ + delete this; +} + +//------------------------------------------------------------------------------ + +} // anonymous namespace + + +//------------------------------------------------------------------------------ + + +void +UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues, + const uno::Reference<uno::XComponentContext>& xContext) +{ + osl::MutexGuard aGuard(m_aMutex); + + if( NOT_INITIALIZED == m_eState ) + { + NamedValueByNameAccess aNameAccess(rValues); + UpdateCheckROModel aModel( aNameAccess ); + m_xContext = xContext; + + rtl::OUString aUpdateEntryVersion = aModel.getUpdateEntryVersion(); + + aModel.getUpdateEntry(m_aUpdateInfo); + + bool obsoleteUpdateInfo = isObsoleteUpdateInfo(aUpdateEntryVersion); + bool bContinueDownload = false; + bool bDownloadAvailable = false; + + m_bHasExtensionUpdate = checkForPendingUpdates( xContext ); + m_bShowExtUpdDlg = false; + + rtl::OUString aLocalFileName = aModel.getLocalFileName(); + + if( aLocalFileName.getLength() > 0 ) + { + bContinueDownload = true; + + // Try to get the number of bytes already on disk + osl::DirectoryItem aDirectoryItem; + if( osl::DirectoryItem::E_None == osl::DirectoryItem::get(aLocalFileName, aDirectoryItem) ) + { + osl::FileStatus aFileStatus(FileStatusMask_FileSize); + if( osl::DirectoryItem::E_None == aDirectoryItem.getFileStatus(aFileStatus) ) + { + sal_Int64 nDownloadSize = aModel.getDownloadSize(); + sal_Int64 nFileSize = aFileStatus.getFileSize(); + + if( nDownloadSize > 0 ) + { + if ( nDownloadSize <= nFileSize ) // we have already downloaded everthing + { + bContinueDownload = false; + bDownloadAvailable = true; + m_aImageName = getImageFromFileName( aLocalFileName ); + } + else // Calculate initial percent value. + { + sal_Int32 nPercent = (sal_Int32) (100 * nFileSize / nDownloadSize); + getUpdateHandler()->setProgress( nPercent ); + } + } + } + } + + if ( bContinueDownload ) + { + bool downloadPaused = aModel.isDownloadPaused(); + + enableDownload(true, downloadPaused); + setUIState(downloadPaused ? UPDATESTATE_DOWNLOAD_PAUSED : UPDATESTATE_DOWNLOADING); + } + + } + if ( !bContinueDownload ) + { + // We do this intentionally only if no download is in progress .. + if( obsoleteUpdateInfo ) + { + // Bring-up release note for position 5 .. + const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 5)); + if( aURL.getLength() > 0 ) + showReleaseNote(aURL); + + // Data is outdated, probably due to installed update + rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( xContext, *this ); + aConfig->clearUpdateFound(); + aConfig->clearLocalFileName(); + + + m_aUpdateInfo = UpdateInfo(); + // Remove outdated release notes + storeReleaseNote( 1, rtl::OUString() ); + storeReleaseNote( 2, rtl::OUString() ); + } + else + { + enableAutoCheck(aModel.isAutoCheckEnabled()); + if ( bDownloadAvailable ) + setUIState( UPDATESTATE_DOWNLOAD_AVAIL ); + else + setUIState(getUIState(m_aUpdateInfo)); + } + } + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::cancel() +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + WorkerThread *pThread = m_pThread; + UpdateState eUIState = getUIState(m_aUpdateInfo); + + aGuard.clear(); + + if( NULL != pThread ) + pThread->cancel(); + + setUIState(eUIState); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::download() +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + UpdateInfo aInfo(m_aUpdateInfo); + State eState = m_eState; + aGuard.clear(); + + if( aInfo.Sources[0].IsDirect ) + { + // Ignore second click of a double click + if( DOWNLOADING != eState ) + { + shutdownThread(true); + + osl::ClearableMutexGuard aGuard2(m_aMutex); + enableDownload(true); + aGuard2.clear(); + setUIState(UPDATESTATE_DOWNLOADING); + } + } + else + { + showReleaseNote(aInfo.Sources[0].URL); // Display in browser + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::install() +{ + osl::MutexGuard aGuard(m_aMutex); + + const uno::Reference< c3s::XSystemShellExecute > xShellExecute( + createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ), + uno::UNO_QUERY ); + + try { + // Construct install command ?? + + // Store release note for position 3 and 4 + rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 3)); + storeReleaseNote(1, aURL); + + aURL = getReleaseNote(m_aUpdateInfo, 4); + storeReleaseNote(2, aURL); + + if( xShellExecute.is() ) + { + rtl::OUString aInstallImage(m_aImageName); + osl::FileBase::getSystemPathFromFileURL(aInstallImage, aInstallImage); + + rtl::OUString aParameter; + sal_Int32 nFlags = c3s::SystemShellExecuteFlags::DEFAULTS; +#if ( defined LINUX || defined SOLARIS ) + nFlags = 42; + aParameter = getBaseInstallation(); + if( aParameter.getLength() > 0 ) + osl::FileBase::getSystemPathFromFileURL(aParameter, aParameter); + + aParameter += UNISTRING(" &"); +#endif + + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext ); + rModel->clearLocalFileName(); + + xShellExecute->execute(aInstallImage, aParameter, nFlags); + ShutdownThread *pShutdownThread = new ShutdownThread( m_xContext ); + (void) pShutdownThread; + } + } catch(uno::Exception&) { + m_aUpdateHandler->setErrorMessage( m_aUpdateHandler->getDefaultInstErrMsg() ); + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::pause() +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + if( NULL != m_pThread ) + m_pThread->suspend(); + + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext); + aGuard.clear(); + + rModel->storeDownloadPaused(true); + setUIState(UPDATESTATE_DOWNLOAD_PAUSED); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::resume() +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + if( NULL != m_pThread ) + m_pThread->resume(); + + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext); + aGuard.clear(); + + rModel->storeDownloadPaused(false); + setUIState(UPDATESTATE_DOWNLOADING); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::closeAfterFailure() +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + if ( ( m_eState == DISABLED ) || ( m_eState == CHECK_SCHEDULED ) ) + { + const UpdateState eUIState = getUIState( m_aUpdateInfo ); + aGuard.clear(); + setUIState( eUIState, true ); + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::shutdownThread(bool join) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + // copy thread object pointer to stack + osl::Thread *pThread = m_pThread; + m_pThread = NULL; + aGuard.clear(); + + if( NULL != pThread ) + { + pThread->terminate(); + if( join ) + { + m_aCondition.set(); + pThread->join(); + m_aCondition.reset(); + } + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::enableAutoCheck(bool enable) +{ + if( enable ) + m_pThread = new UpdateCheckThread(m_aCondition, m_xContext); + + m_eState = enable ? CHECK_SCHEDULED : DISABLED; +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::enableDownload(bool enable, bool paused) +{ + OSL_ASSERT(NULL == m_pThread); + + State eState = DISABLED; + if( enable ) + { + m_pThread = new DownloadThread(m_aCondition, m_xContext, this, m_aUpdateInfo.Sources[0].URL ); + if( !paused ) + { + eState = DOWNLOADING; + m_pThread->resume(); + } + else + eState = DOWNLOAD_PAUSED; + + m_eState = eState; + } + else { + enableAutoCheck(UpdateCheckConfig::get(m_xContext)->isAutoCheckEnabled()); + } + +} + +//------------------------------------------------------------------------------ + +bool +UpdateCheck::downloadTargetExists(const rtl::OUString& rFileName) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler()); + UpdateState eUIState = UPDATESTATE_DOWNLOADING; + + bool cont = false; + + if( aUpdateHandler->isVisible() ) + { + cont = aUpdateHandler->showOverwriteWarning(); + if( cont ) + { + if( osl_File_E_None != osl_removeFile(rFileName.pData) ) + { + // FIXME: error message + cont = false; + } + } + else + eUIState = getUIState(m_aUpdateInfo); + } + else + { + m_aImageName = getImageFromFileName(rFileName); + eUIState = UPDATESTATE_DOWNLOAD_AVAIL; + } + + if( !cont ) + { + shutdownThread(false); + enableDownload(false); + + aGuard.clear(); + setUIState(eUIState); + } + + return cont; +} + +//------------------------------------------------------------------------------ +bool UpdateCheck::checkDownloadDestination( const rtl::OUString& rFileName ) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + rtl::Reference< UpdateHandler > aUpdateHandler( getUpdateHandler() ); + + bool bReload = false; + + if( aUpdateHandler->isVisible() ) + { + bReload = aUpdateHandler->showOverwriteWarning( rFileName ); + } + + return bReload; +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::downloadStalled(const rtl::OUString& rErrorMessage) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler()); + aGuard.clear(); + + aUpdateHandler->setErrorMessage(rErrorMessage); + setUIState(UPDATESTATE_ERROR_DOWNLOADING); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::downloadProgressAt(sal_Int8 nPercent) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler()); + aGuard.clear(); + + aUpdateHandler->setProgress(nPercent); + setUIState(UPDATESTATE_DOWNLOADING); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize) +{ + if ( nFileSize > 0 ) + { + osl::MutexGuard aGuard(m_aMutex); + + rtl::Reference< UpdateCheckConfig > aModel(UpdateCheckConfig::get(m_xContext)); + aModel->storeLocalFileName(rLocalFileName, nFileSize); + + // Bring-up release note for position 1 .. + const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 1, aModel->isAutoDownloadEnabled())); + if( aURL.getLength() > 0 ) + showReleaseNote(aURL); + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::downloadFinished(const rtl::OUString& rLocalFileName) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + // no more retries + m_pThread->terminate(); + + m_aImageName = getImageFromFileName(rLocalFileName); + UpdateInfo aUpdateInfo(m_aUpdateInfo); + + aGuard.clear(); + setUIState(UPDATESTATE_DOWNLOAD_AVAIL); + + // Bring-up release note for position 2 .. + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext ); + const rtl::OUString aURL(getReleaseNote(aUpdateInfo, 2, rModel->isAutoDownloadEnabled())); + if( aURL.getLength() > 0 ) + showReleaseNote(aURL); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::cancelDownload() +{ + shutdownThread(true); + + osl::MutexGuard aGuard(m_aMutex); + enableDownload(false); + + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext); + + rtl::OUString aLocalFile(rModel->getLocalFileName()); + rModel->clearLocalFileName(); + rModel->storeDownloadPaused(false); + + if( isObsoleteUpdateInfo(rModel->getUpdateEntryVersion()) ) + { + rModel->clearUpdateFound(); // This wasn't done during init yet .. + m_aUpdateInfo = UpdateInfo(); + } + + /*oslFileError rc =*/ osl_removeFile(aLocalFile.pData); + // FIXME: error handling .. + +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::showDialog(bool forceCheck) +{ + osl::ResettableMutexGuard aGuard(m_aMutex); + + bool update_found = m_aUpdateInfo.BuildId.getLength() > 0; + bool bSetUIState = ! m_aUpdateHandler.is(); + + UpdateState eDialogState = UPDATESTATES_COUNT; + + switch( m_eState ) + { + case DISABLED: + case CHECK_SCHEDULED: + if( forceCheck || ! update_found ) // Run check when forced or if we did not find an update yet + { + eDialogState = UPDATESTATE_CHECKING; + bSetUIState = true; + } + else if(m_aUpdateInfo.Sources[0].IsDirect) + eDialogState = UPDATESTATE_UPDATE_AVAIL; + else + eDialogState = UPDATESTATE_UPDATE_NO_DOWNLOAD; + break; + + case DOWNLOADING: + eDialogState = UPDATESTATE_DOWNLOADING; + break; + + case DOWNLOAD_PAUSED: + eDialogState = UPDATESTATE_DOWNLOAD_PAUSED; + break; + + case NOT_INITIALIZED: + OSL_ASSERT( false ); + break; + } + + if( bSetUIState ) + { + aGuard.clear(); + setUIState(eDialogState, true); // suppress bubble as Dialog will be visible soon + aGuard.reset(); + } + + getUpdateHandler()->setVisible(true); + + // Run check in separate thread .. + if( UPDATESTATE_CHECKING == eDialogState ) + { + if( DISABLED == m_eState ) + { + // destructs itself when done, not cancellable for now .. + new ManualUpdateCheckThread(m_aCondition, m_xContext); + } + + m_aCondition.set(); + } +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::setUpdateInfo(const UpdateInfo& aInfo) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + bool bSuppressBubble = (sal_True == aInfo.BuildId.equals(m_aUpdateInfo.BuildId)); + m_aUpdateInfo = aInfo; + + OSL_ASSERT(DISABLED == m_eState || CHECK_SCHEDULED == m_eState); + + // Ignore leading non direct download if we get direct ones + std::vector< DownloadSource >::iterator iter = m_aUpdateInfo.Sources.begin(); + while( iter != m_aUpdateInfo.Sources.end() ) + { + if( iter->IsDirect ) + break; + + ++iter; + } + + if( (iter != m_aUpdateInfo.Sources.begin()) && + (iter != m_aUpdateInfo.Sources.end()) && + iter->IsDirect ) + { + m_aUpdateInfo.Sources.erase(m_aUpdateInfo.Sources.begin(), --iter); + } + + rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *this); + OSL_ASSERT( rModel.is() ); + + // Decide whether to use alternate release note pos .. + bool autoDownloadEnabled = rModel->isAutoDownloadEnabled(); + + std::vector< ReleaseNote >::iterator iter2 = m_aUpdateInfo.ReleaseNotes.begin(); + while( iter2 != m_aUpdateInfo.ReleaseNotes.end() ) + { + if( ((1 == iter2->Pos) || (2 == iter2->Pos)) && autoDownloadEnabled && (iter2->URL2.getLength() > 0)) + { + iter2->URL = iter2->URL2; + iter2->URL2 = rtl::OUString(); + iter2->Pos = iter2->Pos2; + iter2->Pos2 = 0; + } + + ++iter2; + } + + // do not move below store/clear .. + rModel->updateLastChecked(); + + UpdateState eUIState; + if( m_aUpdateInfo.Sources.size() > 0 ) + { + rModel->storeUpdateFound(aInfo, getBuildId()); + + if( m_aUpdateInfo.Sources[0].IsDirect ) + { + eUIState = UPDATESTATE_UPDATE_AVAIL; + + if( rModel->isAutoDownloadEnabled() ) + { + shutdownThread(false); + eUIState = UPDATESTATE_DOWNLOADING; + enableDownload(true); + } + } + else + eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD; + } + else + { + eUIState = UPDATESTATE_NO_UPDATE_AVAIL; + rModel->clearUpdateFound(); + } + + aGuard.clear(); + setUIState(eUIState, bSuppressBubble); +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::setCheckFailedState() +{ + setUIState(UPDATESTATE_ERROR_CHECKING); +} + +//------------------------------------------------------------------------------ +void UpdateCheck::handleMenuBarUI( rtl::Reference< UpdateHandler > rUpdateHandler, + UpdateState& eState, + bool suppressBubble ) +{ + uno::Reference<beans::XPropertySet> xMenuBarUI( m_xMenuBarUI ); + + if ( ( UPDATESTATE_NO_UPDATE_AVAIL == eState ) && m_bHasExtensionUpdate ) + eState = UPDATESTATE_EXT_UPD_AVAIL; + + if ( UPDATESTATE_EXT_UPD_AVAIL == eState ) + m_bShowExtUpdDlg = true; + else + m_bShowExtUpdDlg = false; + + if( xMenuBarUI.is() ) + { + if( UPDATESTATE_NO_UPDATE_AVAIL == eState ) + { + xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_False) ); + } + else + { + xMenuBarUI->setPropertyValue( PROPERTY_TITLE, uno::makeAny(rUpdateHandler->getBubbleTitle(eState)) ); + xMenuBarUI->setPropertyValue( PROPERTY_TEXT, uno::makeAny(rUpdateHandler->getBubbleText(eState)) ); + + if( ! suppressBubble && ( ! rUpdateHandler->isVisible() || rUpdateHandler->isMinimized() ) ) + xMenuBarUI->setPropertyValue( PROPERTY_SHOW_BUBBLE, uno::makeAny( sal_True ) ); + + if( UPDATESTATE_CHECKING != eState ) + xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_True) ); + } + } +} + +//------------------------------------------------------------------------------ +void UpdateCheck::setUIState(UpdateState eState, bool suppressBubble) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + if( ! m_xMenuBarUI.is() && + (DISABLED != m_eState) && + ( m_bHasExtensionUpdate || (UPDATESTATE_NO_UPDATE_AVAIL != eState)) && + (UPDATESTATE_CHECKING != eState) && + (UPDATESTATE_ERROR_CHECKING != eState) + ) + { + m_xMenuBarUI = createMenuBarUI(m_xContext, new MenuBarButtonJob(this)); + } + + // Show bubble only when the status has changed + if ( eState == m_eUpdateState ) + suppressBubble = true; + else + m_eUpdateState = eState; + + rtl::Reference<UpdateHandler> aUpdateHandler(getUpdateHandler()); + OSL_ASSERT( aUpdateHandler.is() ); + + UpdateInfo aUpdateInfo(m_aUpdateInfo); + rtl::OUString aImageName(m_aImageName); + + aGuard.clear(); + + handleMenuBarUI( aUpdateHandler, eState, suppressBubble ); + + if( (UPDATESTATE_UPDATE_AVAIL == eState) + || (UPDATESTATE_DOWNLOAD_PAUSED == eState) + || (UPDATESTATE_DOWNLOADING == eState) ) + { + uno::Reference< uno::XComponentContext > xContext(m_xContext); + + rtl::OUString aDownloadDestination = + UpdateCheckConfig::get(xContext, this)->getDownloadDestination(); + + osl_getSystemPathFromFileURL(aDownloadDestination.pData, &aDownloadDestination.pData); + + aUpdateHandler->setDownloadPath(aDownloadDestination); + } + else if( UPDATESTATE_DOWNLOAD_AVAIL == eState ) + { + aUpdateHandler->setDownloadFile(aImageName); + } + + aUpdateHandler->setDescription(aUpdateInfo.Description); + aUpdateHandler->setNextVersion(aUpdateInfo.Version); + aUpdateHandler->setState(eState); +} + +//------------------------------------------------------------------------------ + +UpdateState +UpdateCheck::getUIState(const UpdateInfo& rInfo) +{ + UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL; + + if( rInfo.BuildId.getLength() > 0 ) + { + if( rInfo.Sources[0].IsDirect ) + eUIState = UPDATESTATE_UPDATE_AVAIL; + else + eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD; + } + + return eUIState; +} + +//------------------------------------------------------------------------------ + +void +UpdateCheck::showReleaseNote(const rtl::OUString& rURL) const +{ + const uno::Reference< c3s::XSystemShellExecute > xShellExecute( + createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ), + uno::UNO_QUERY ); + + try { + + if( xShellExecute.is() ) + xShellExecute->execute(rURL, rtl::OUString(), c3s::SystemShellExecuteFlags::DEFAULTS); + } catch(c3s::SystemShellExecuteException&) { + } +} + +//------------------------------------------------------------------------------ + +bool +UpdateCheck::storeReleaseNote(sal_Int8 nNum, const rtl::OUString &rURL) +{ + osl::FileBase::RC rc; + rtl::OUString aTargetDir( UpdateCheckConfig::getAllUsersDirectory() + UNISTRING( "/sun" ) ); + + rc = osl::Directory::createPath( aTargetDir ); + + rtl::OUString aFileName = UNISTRING("releasenote") + + rtl::OUString::valueOf( (sal_Int32) nNum ) + + UNISTRING(".url"); + + rtl::OUString aFilePath; + rc = osl::FileBase::getAbsoluteFileURL( aTargetDir, aFileName, aFilePath ); + if ( rc != osl::FileBase::E_None ) return false; + + rc = osl::File::remove( aFilePath ); + + // don't store empty release notes, but delete old ones + if ( rURL.getLength() == 0 ) + return true; + + osl::File aFile( aFilePath ); + rc = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create ); + + if ( rc != osl::FileBase::E_None ) return false; + + rtl::OString aLineBuf("[InternetShortcut]\r\n"); + sal_uInt64 nWritten = 0; + + rtl::OUString aURL( rURL ); +#ifdef WNT + rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten ); + if ( rc != osl::FileBase::E_None ) return false; + aURL = UNISTRING("URL=") + rURL; +#endif + aLineBuf = rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 ); + rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten ); + if ( rc != osl::FileBase::E_None ) return false; + + aFile.close(); + return true; +} + +//------------------------------------------------------------------------------ +void UpdateCheck::showExtensionDialog() +{ + rtl::OUString sServiceName = UNISTRING("com.sun.star.deployment.ui.PackageManagerDialog"); + rtl::OUString sArguments = UNISTRING("SHOW_UPDATE_DIALOG"); + uno::Reference< uno::XInterface > xService; + + if( ! m_xContext.is() ) + throw uno::RuntimeException( + UNISTRING( "UpdateCheck::showExtensionDialog(): empty component context" ), uno::Reference< uno::XInterface > () ); + + uno::Reference< lang::XMultiComponentFactory > xServiceManager( m_xContext->getServiceManager() ); + if( !xServiceManager.is() ) + throw uno::RuntimeException( + UNISTRING( "UpdateCheck::showExtensionDialog(): unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () ); + + xService = xServiceManager->createInstanceWithContext( sServiceName, m_xContext ); + uno::Reference< task::XJobExecutor > xExecuteable( xService, uno::UNO_QUERY ); + if ( xExecuteable.is() ) + xExecuteable->trigger( sArguments ); +} + +//------------------------------------------------------------------------------ + +rtl::Reference<UpdateHandler> +UpdateCheck::getUpdateHandler() +{ + osl::MutexGuard aGuard(m_aMutex); + + if( ! m_aUpdateHandler.is() ) + m_aUpdateHandler = new UpdateHandler(m_xContext, this); + + return m_aUpdateHandler; +} + +//------------------------------------------------------------------------------ + +uno::Reference< task::XInteractionHandler > +UpdateCheck::getInteractionHandler() const +{ + osl::MutexGuard aGuard(m_aMutex); + + uno::Reference< task::XInteractionHandler > xHandler; + + if( m_aUpdateHandler.is() && m_aUpdateHandler->isVisible() ) + xHandler = m_aUpdateHandler.get(); + + return xHandler; +} + +//------------------------------------------------------------------------------ + +uno::Reference< uno::XInterface > +UpdateCheck::createService(const rtl::OUString& rServiceName, + const uno::Reference<uno::XComponentContext>& xContext) +{ + if( !xContext.is() ) + throw uno::RuntimeException( + UNISTRING( "UpdateCheckConfig: empty component context" ), + uno::Reference< uno::XInterface >() ); + + const uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager()); + + if( !xServiceManager.is() ) + throw uno::RuntimeException( + UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ), + uno::Reference< uno::XInterface >() ); + + return xServiceManager->createInstanceWithContext(rServiceName, xContext); +} + +//------------------------------------------------------------------------------ + +bool +UpdateCheck::isDialogShowing() const +{ + osl::MutexGuard aGuard(m_aMutex); + return sal_True == m_aUpdateHandler.is() && m_aUpdateHandler->isVisible(); +}; + +//------------------------------------------------------------------------------ + +void +UpdateCheck::autoCheckStatusChanged(bool enabled) +{ + osl::ClearableMutexGuard aGuard(m_aMutex); + + if( (CHECK_SCHEDULED == m_eState) && !enabled ) + shutdownThread(false); + + if( (DISABLED == m_eState) || (CHECK_SCHEDULED == m_eState) ) + { + enableAutoCheck(enabled); + UpdateState eState = getUIState(m_aUpdateInfo); + aGuard.clear(); + setUIState(eState); + } +}; + +//------------------------------------------------------------------------------ + +void +UpdateCheck::autoCheckIntervalChanged() +{ + // just wake-up + m_aCondition.set(); +}; + +//------------------------------------------------------------------------------ + +oslInterlockedCount SAL_CALL +UpdateCheck::acquire() SAL_THROW(()) +{ + return ReferenceObject::acquire(); +} + +//------------------------------------------------------------------------------ + +oslInterlockedCount SAL_CALL +UpdateCheck::release() SAL_THROW(()) +{ + return ReferenceObject::release(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |