Bump for 3.6-28
[LibreOffice.git] / extensions / source / update / check / updatecheck.cxx
blob7832d8c15d87c5e2403b9c64cbc43c3a8f58df29
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "updatecheck.hxx"
32 #include <cppuhelper/implbase1.hxx>
33 #include <com/sun/star/beans/XFastPropertySet.hpp>
34 #include <com/sun/star/lang/XComponent.hpp>
35 #include <com/sun/star/frame/XDesktop.hpp>
36 #include <com/sun/star/frame/XFrame.hpp>
37 #include <com/sun/star/frame/DispatchResultEvent.hpp>
38 #include <com/sun/star/frame/DispatchResultState.hpp>
39 #include <com/sun/star/system/XSystemShellExecute.hpp>
40 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
41 #include <com/sun/star/task/XJob.hpp>
42 #include <com/sun/star/task/XJobExecutor.hpp>
44 #include <rtl/ustrbuf.hxx>
46 #include <rtl/bootstrap.hxx>
47 #include <osl/process.h>
48 #include <osl/module.hxx>
49 #include <osl/file.hxx>
50 #include <sal/macros.h>
52 #ifdef WNT
53 #ifdef _MSC_VER
54 #pragma warning(push,1) // disable warnings within system headers
55 //#pragma warning(disable: 4917)
56 #endif
57 #include <objbase.h>
58 #ifdef _MSC_VER
59 #pragma warning(pop)
60 #endif
61 #endif
63 #include "updateprotocol.hxx"
64 #include "updatecheckconfig.hxx"
66 namespace beans = com::sun::star::beans ;
67 namespace deployment = com::sun::star::deployment ;
68 namespace frame = com::sun::star::frame ;
69 namespace lang = com::sun::star::lang ;
70 namespace c3s = com::sun::star::system ;
71 namespace task = com::sun::star::task ;
72 namespace uno = com::sun::star::uno ;
74 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
76 #define PROPERTY_TITLE UNISTRING("BubbleHeading")
77 #define PROPERTY_TEXT UNISTRING("BubbleText")
78 #define PROPERTY_IMAGE UNISTRING("BubbleImageURL")
79 #define PROPERTY_SHOW_BUBBLE UNISTRING("BubbleVisible")
80 #define PROPERTY_CLICK_HDL UNISTRING("MenuClickHDL")
81 #define PROPERTY_DEFAULT_TITLE UNISTRING("DefaultHeading")
82 #define PROPERTY_DEFAULT_TEXT UNISTRING("DefaultText")
83 #define PROPERTY_SHOW_MENUICON UNISTRING("MenuIconVisible")
85 extern "C" bool SAL_CALL WNT_hasInternetConnection();
86 //------------------------------------------------------------------------------
88 // Returns the URL of the release note for the given position
89 rtl::OUString getReleaseNote(const UpdateInfo& rInfo, sal_uInt8 pos, bool autoDownloadEnabled)
91 std::vector< ReleaseNote >::const_iterator iter = rInfo.ReleaseNotes.begin();
92 while( iter != rInfo.ReleaseNotes.end() )
94 if( pos == iter->Pos )
96 if( (pos > 2) || !autoDownloadEnabled || iter->URL2.isEmpty() )
97 return iter->URL;
99 else if( (pos == iter->Pos2) && ((1 == iter->Pos) || (2 == iter->Pos)) && autoDownloadEnabled )
100 return iter->URL2;
102 ++iter;
105 return rtl::OUString();
108 //------------------------------------------------------------------------------
110 namespace
113 static inline rtl::OUString getBuildId()
115 rtl::OUString aPathVal(UNISTRING("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}"));
116 rtl::Bootstrap::expandMacros(aPathVal);
117 return aPathVal;
120 //------------------------------------------------------------------------------
121 static inline rtl::OUString getBaseInstallation()
123 rtl::OUString aPathVal(UNISTRING("$BRAND_BASE_DIR"));
124 rtl::Bootstrap::expandMacros(aPathVal);
125 return aPathVal;
128 //------------------------------------------------------------------------------
130 inline bool isObsoleteUpdateInfo(const rtl::OUString& rBuildId)
132 return sal_True != rBuildId.equals(getBuildId()) && !rBuildId.isEmpty();
136 //------------------------------------------------------------------------------
138 rtl::OUString getImageFromFileName(const rtl::OUString& aFile)
140 #ifndef WNT
141 rtl::OUString aUnpackPath;
142 if( osl_getExecutableFile(&aUnpackPath.pData) == osl_Process_E_None )
144 sal_uInt32 lastIndex = aUnpackPath.lastIndexOf('/');
145 if ( lastIndex > 0 )
147 aUnpackPath = aUnpackPath.copy( 0, lastIndex+1 );
148 aUnpackPath += UNISTRING( "unpack_update" );
151 oslFileHandle hOut = NULL;
152 oslProcess hProcess = NULL;
154 rtl::OUString aSystemPath;
155 osl::File::getSystemPathFromFileURL(aFile, aSystemPath);
157 oslProcessError rc = osl_executeProcess_WithRedirectedIO(
158 aUnpackPath.pData, // [in] Image name
159 &aSystemPath.pData, 1, // [in] Arguments
160 osl_Process_WAIT | osl_Process_NORMAL, // [in] Options
161 NULL, // [in] Security
162 NULL, // [in] Working directory
163 NULL, 0, // [in] Environment variables
164 &hProcess, // [out] Process handle
165 NULL, &hOut, NULL // [out] File handles for redirected I/O
168 if( osl_Process_E_None == rc )
170 oslProcessInfo aInfo;
171 aInfo.Size = sizeof(oslProcessInfo);
173 if( osl_Process_E_None == osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo) )
175 if( 0 == aInfo.Code )
177 sal_Char szBuffer[4096];
178 sal_uInt64 nBytesRead = 0;
179 const sal_uInt64 nBytesToRead = sizeof(szBuffer) - 1;
181 rtl::OUString aImageName;
182 while( osl_File_E_None == osl_readFile(hOut, szBuffer, nBytesToRead, &nBytesRead) )
184 sal_Char *pc = szBuffer + nBytesRead;
187 *pc = '\0'; --pc;
189 while( ('\n' == *pc) || ('\r' == *pc) );
191 aImageName += rtl::OUString(szBuffer, pc - szBuffer + 1, osl_getThreadTextEncoding());
193 if( nBytesRead < nBytesToRead )
194 break;
197 if( osl::FileBase::E_None == osl::FileBase::getFileURLFromSystemPath(aImageName, aImageName) )
198 return aImageName;
202 osl_closeFile(hOut);
203 osl_freeProcessHandle(hProcess);
206 #endif
208 return aFile;
212 //------------------------------------------------------------------------------
214 static uno::Reference< beans::XPropertySet > createMenuBarUI(
215 const uno::Reference< uno::XComponentContext >& xContext,
216 const uno::Reference< task::XJob >& xJob)
218 if( !xContext.is() )
219 throw uno::RuntimeException(
220 UNISTRING( "UpdateCheckJob: empty component context" ), uno::Reference< uno::XInterface > () );
222 uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
223 if( !xServiceManager.is() )
224 throw uno::RuntimeException(
225 UNISTRING( "UpdateCheckJob: unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () );
227 uno::Reference< beans::XPropertySet > xMenuBarUI =
228 uno::Reference< beans::XPropertySet > (
229 xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.setup.UpdateCheckUI" ), xContext ),
230 uno::UNO_QUERY_THROW);
232 xMenuBarUI->setPropertyValue( PROPERTY_CLICK_HDL, uno::makeAny( xJob ) );
234 return xMenuBarUI;
237 //------------------------------------------------------------------------------
241 typedef sal_Bool (* OnlineCheckFunc) ();
243 class UpdateCheckThread : public WorkerThread
246 public:
247 UpdateCheckThread( osl::Condition& rCondition,
248 const uno::Reference<uno::XComponentContext>& xContext );
250 virtual void SAL_CALL join();
251 virtual void SAL_CALL terminate();
252 virtual void SAL_CALL cancel();
254 protected:
255 virtual ~UpdateCheckThread();
257 virtual void SAL_CALL run();
258 virtual void SAL_CALL onTerminated();
260 /* Wrapper around checkForUpdates */
261 bool runCheck( bool & rbExtensionsChecked );
263 private:
265 /* Used to avoid dialup login windows (on platforms we know how to double this) */
266 inline bool hasInternetConnection() const
268 #ifdef WNT
269 return WNT_hasInternetConnection();
270 #else
271 return true;
272 #endif
275 /* Creates a new instance of UpdateInformationProvider and returns this instance */
276 inline uno::Reference<deployment::XUpdateInformationProvider> createProvider()
278 osl::MutexGuard aGuard(m_aMutex);
279 m_xProvider = deployment::UpdateInformationProvider::create(m_xContext);
280 return m_xProvider;
283 /* Returns the remembered instance of UpdateInformationProvider if any */
284 inline uno::Reference<deployment::XUpdateInformationProvider> getProvider()
285 { osl::MutexGuard aGuard(m_aMutex); return m_xProvider; };
287 /* Releases the remembered instance of UpdateInformationProvider if any */
288 inline void clearProvider()
289 { osl::MutexGuard aGuard(m_aMutex); m_xProvider.clear(); };
291 osl::Mutex m_aMutex;
292 osl::Module m_aModule;
294 protected:
295 osl::Condition& m_aCondition;
297 private:
298 const uno::Reference<uno::XComponentContext> m_xContext;
299 uno::Reference<deployment::XUpdateInformationProvider> m_xProvider;
303 class ManualUpdateCheckThread : public UpdateCheckThread
305 public:
306 ManualUpdateCheckThread( osl::Condition& rCondition, const uno::Reference<uno::XComponentContext>& xContext ) :
307 UpdateCheckThread(rCondition, xContext) {};
309 virtual void SAL_CALL run();
313 class MenuBarButtonJob : public ::cppu::WeakImplHelper1< task::XJob >
315 public:
316 MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck);
318 // XJob
319 virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&)
320 throw (lang::IllegalArgumentException, uno::Exception);
322 private:
323 rtl::Reference< UpdateCheck > m_aUpdateCheck;
326 class DownloadThread : public WorkerThread
328 public:
329 DownloadThread(
330 osl::Condition& rCondition,
331 const uno::Reference<uno::XComponentContext>& xContext,
332 const rtl::Reference< DownloadInteractionHandler >& rHandler,
333 const rtl::OUString& rURL );
335 virtual void SAL_CALL run();
336 virtual void SAL_CALL cancel();
337 virtual void SAL_CALL suspend();
338 virtual void SAL_CALL onTerminated();
340 protected:
341 ~DownloadThread();
343 private:
344 osl::Condition& m_aCondition;
345 const uno::Reference<uno::XComponentContext> m_xContext;
346 const rtl::OUString m_aURL;
347 Download m_aDownload;
350 //------------------------------------------------------------------------------
351 class ShutdownThread : public osl::Thread
353 public:
354 ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext );
356 virtual void SAL_CALL run();
357 virtual void SAL_CALL onTerminated();
359 protected:
360 ~ShutdownThread();
362 private:
363 osl::Condition m_aCondition;
364 const uno::Reference<uno::XComponentContext> m_xContext;
367 //------------------------------------------------------------------------------
369 UpdateCheckThread::UpdateCheckThread( osl::Condition& rCondition,
370 const uno::Reference<uno::XComponentContext>& xContext ) :
371 m_aCondition(rCondition),
372 m_xContext(xContext)
374 createSuspended();
376 // actually run the thread
377 resume();
380 //------------------------------------------------------------------------------
382 UpdateCheckThread::~UpdateCheckThread()
386 //------------------------------------------------------------------------------
389 void SAL_CALL
390 UpdateCheckThread::terminate()
392 // Cancel potentially hanging http request ..
393 cancel();
394 // .. before terminating
395 osl::Thread::terminate();
398 //------------------------------------------------------------------------------
400 void SAL_CALL
401 UpdateCheckThread::join()
403 uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider());
405 // do not join during an update check until #i73893# is fixed
406 if( ! xProvider.is() )
408 osl::Thread::join();
412 //------------------------------------------------------------------------------
414 void SAL_CALL
415 UpdateCheckThread::cancel()
417 uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider());
419 if( xProvider.is() )
420 xProvider->cancel();
423 //------------------------------------------------------------------------------
425 bool
426 UpdateCheckThread::runCheck( bool & rbExtensionsChecked )
428 bool ret = false;
429 UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
431 UpdateInfo aInfo;
432 rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
434 if( checkForUpdates(aInfo, m_xContext, aController->getInteractionHandler(), createProvider()) )
436 aController->setUpdateInfo(aInfo);
437 eUIState = aController->getUIState(aInfo);
438 ret = true;
440 else
441 aController->setCheckFailedState();
443 // We will only look for extension updates, when there is no 'check for office updates' dialog open
444 // and when there was no office update found
445 if ( ( eUIState != UPDATESTATE_UPDATE_AVAIL ) &&
446 ( eUIState != UPDATESTATE_UPDATE_NO_DOWNLOAD ) &&
447 !aController->isDialogShowing() &&
448 !rbExtensionsChecked )
450 bool bHasExtensionUpdates = checkForExtensionUpdates( m_xContext );
451 aController->setHasExtensionUpdates( bHasExtensionUpdates );
452 if ( bHasExtensionUpdates )
453 aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL );
454 rbExtensionsChecked = true;
457 // joining with this thread is safe again
458 clearProvider();
459 return ret;
462 //------------------------------------------------------------------------------
464 void SAL_CALL
465 UpdateCheckThread::onTerminated()
467 delete this;
470 //------------------------------------------------------------------------------
472 void SAL_CALL
473 UpdateCheckThread::run()
475 bool bExtensionsChecked = false;
476 TimeValue systime;
477 TimeValue nExtCheckTime;
478 osl_getSystemTime( &nExtCheckTime );
480 osl::Condition::Result aResult = osl::Condition::result_timeout;
481 TimeValue tv = { 10, 0 };
483 // Initial wait to avoid doing further time consuming tasks during start-up
484 aResult = m_aCondition.wait(&tv);
486 try {
488 while( sal_True == schedule() )
490 /* Use cases:
491 * a) manual check requested from auto check thread - "last check" should not be checked (one time)
492 * a1) manual check was requested in the middle of a running auto check,
493 * condition is set
494 * a2) manual check was requested while waiting for a retry,
495 * condition is set
496 * a3) manual check was requested while waiting for time to next
497 * scheduled check elapsing, condition is set
498 * a4) manual check was requested during initial wait, condition is set
499 * b) check interval got changed, condition may be set - same sub-cases as a),
500 * but "last check" should be honored
501 * c) normal auto check mode, condition not set - "last check" should be honored
504 // Accessing const members without synchronization
505 rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
506 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *aController);
508 // FIXME: remember last & offset ?
509 sal_Int64 last = rModel->getLastChecked();
510 sal_Int64 offset = rModel->getCheckInterval();
512 rModel.clear();
514 // last == 0 means check immediately
515 bool checkNow = ! (last > 0);
517 // Reset the condition to avoid busy loops
518 if( osl::Condition::result_ok == aResult )
520 m_aCondition.reset();
521 aResult = osl::Condition::result_timeout;
522 checkNow = aController->isDialogShowing();
525 if( ! checkNow )
527 osl_getSystemTime(&systime);
529 // Go back to sleep until time has elapsed
530 sal_Int64 next = last + offset;
531 if( last + offset > systime.Seconds )
533 // This can not be > 32 Bit for now ..
534 tv.Seconds = static_cast< sal_Int32 > (next - systime.Seconds);
535 aResult = m_aCondition.wait(&tv);
536 continue;
540 static sal_uInt8 n = 0;
542 if( ! hasInternetConnection() || ! runCheck( bExtensionsChecked ) )
544 // the extension update check should be independent from the office update check
546 osl_getSystemTime( &systime );
547 if ( nExtCheckTime.Seconds + offset < systime.Seconds )
548 bExtensionsChecked = false;
550 // Increase next by 15, 60, .. minutes
551 static const sal_Int32 nRetryInterval[] = { 900, 3600, 14400, 86400 };
553 if( n < SAL_N_ELEMENTS(nRetryInterval) )
554 ++n;
556 tv.Seconds = nRetryInterval[n-1];
557 aResult = m_aCondition.wait(&tv);
559 else // reset retry counter
561 n = 0;
562 bExtensionsChecked = false;
567 catch(const uno::Exception& e) {
568 // Silently catch all errors
569 OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
570 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
574 //------------------------------------------------------------------------------
576 void SAL_CALL
577 ManualUpdateCheckThread::run()
579 bool bExtensionsChecked = false;
581 try {
582 runCheck( bExtensionsChecked );
583 m_aCondition.reset();
585 catch(const uno::Exception& e) {
586 // Silently catch all errors
587 OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
588 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
592 //------------------------------------------------------------------------------
594 MenuBarButtonJob::MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck) :
595 m_aUpdateCheck(rUpdateCheck)
599 //------------------------------------------------------------------------------
601 uno::Any SAL_CALL
602 MenuBarButtonJob::execute(const uno::Sequence<beans::NamedValue>& )
603 throw (lang::IllegalArgumentException, uno::Exception)
605 if ( m_aUpdateCheck->shouldShowExtUpdDlg() )
606 m_aUpdateCheck->showExtensionDialog();
607 else
608 m_aUpdateCheck->showDialog();
610 return uno::Any();
613 //------------------------------------------------------------------------------
615 DownloadThread::DownloadThread(osl::Condition& rCondition,
616 const uno::Reference<uno::XComponentContext>& xContext,
617 const rtl::Reference< DownloadInteractionHandler >& rHandler,
618 const rtl::OUString& rURL) :
619 m_aCondition(rCondition),
620 m_xContext(xContext),
621 m_aURL(rURL),
622 m_aDownload(xContext, rHandler)
624 createSuspended();
627 //------------------------------------------------------------------------------
629 DownloadThread::~DownloadThread()
633 //------------------------------------------------------------------------------
635 void SAL_CALL
636 DownloadThread::run()
638 #ifdef WNT
639 CoUninitialize();
640 CoInitialize( NULL );
641 #endif
643 while( schedule() )
645 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
647 rtl::OUString aLocalFile = rModel->getLocalFileName();
648 rtl::OUString aDownloadDest = rModel->getDownloadDestination();
650 // release config class for now
651 rModel.clear();
653 static sal_uInt8 n = 0;
654 if( ! m_aDownload.start(m_aURL, aLocalFile, aDownloadDest ) )
656 // retry every 15s unless the dialog is not visible
657 TimeValue tv;
658 tv.Seconds = 15;
660 if( ! UpdateCheck::get()->isDialogShowing() )
662 // Increase next by 1, 5, 15, 60, .. minutes
663 static const sal_Int16 nRetryInterval[] = { 60, 300, 900, 3600 };
665 if( n < SAL_N_ELEMENTS(nRetryInterval) )
666 ++n;
668 tv.Seconds = nRetryInterval[n-1];
670 m_aCondition.wait(&tv);
672 else
674 // reset wait period after successful download
675 n=0;
680 //------------------------------------------------------------------------------
682 void SAL_CALL DownloadThread::cancel()
684 m_aDownload.stop();
685 resume();
687 rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
688 aController->cancelDownload();
691 //------------------------------------------------------------------------------
693 void SAL_CALL DownloadThread::suspend()
695 osl::Thread::suspend();
696 m_aDownload.stop();
699 //------------------------------------------------------------------------------
701 void SAL_CALL DownloadThread::onTerminated()
703 delete this;
706 //------------------------------------------------------------------------------
707 ShutdownThread::ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext) :
708 m_xContext( xContext )
710 create();
713 //------------------------------------------------------------------------------
714 ShutdownThread::~ShutdownThread()
718 //------------------------------------------------------------------------------
719 void SAL_CALL
720 ShutdownThread::run()
722 TimeValue tv = { 0, 250 };
724 m_aCondition.wait(&tv);
726 // Tell QuickStarter not to veto ..
727 uno::Reference< beans::XFastPropertySet > xQuickStarter(
728 UpdateCheck::createService(UNISTRING("com.sun.star.office.Quickstart"), m_xContext),
729 uno::UNO_QUERY
732 if (xQuickStarter.is())
733 xQuickStarter->setFastPropertyValue(0, uno::makeAny(false));
735 // Shutdown the office
736 uno::Reference< frame::XDesktop > xDesktop(
737 UpdateCheck::createService(UNISTRING("com.sun.star.frame.Desktop"), m_xContext),
738 uno::UNO_QUERY);
740 if( xDesktop.is() )
741 xDesktop->terminate();
744 //------------------------------------------------------------------------------
745 void SAL_CALL ShutdownThread::onTerminated()
747 delete this;
750 //------------------------------------------------------------------------------
752 } // anonymous namespace
755 //------------------------------------------------------------------------------
757 UpdateCheck::UpdateCheck():
758 m_eState(NOT_INITIALIZED), m_eUpdateState(UPDATESTATES_COUNT),
759 m_pThread(NULL)
762 UpdateCheck::~UpdateCheck() {}
764 void
765 UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues,
766 const uno::Reference<uno::XComponentContext>& xContext)
768 osl::MutexGuard aGuard(m_aMutex);
770 if( NOT_INITIALIZED == m_eState )
772 NamedValueByNameAccess aNameAccess(rValues);
773 UpdateCheckROModel aModel( aNameAccess );
774 m_xContext = xContext;
776 rtl::OUString aUpdateEntryVersion = aModel.getUpdateEntryVersion();
778 aModel.getUpdateEntry(m_aUpdateInfo);
780 bool obsoleteUpdateInfo = isObsoleteUpdateInfo(aUpdateEntryVersion);
781 bool bContinueDownload = false;
782 bool bDownloadAvailable = false;
784 m_bHasExtensionUpdate = checkForPendingUpdates( xContext );
785 m_bShowExtUpdDlg = false;
787 rtl::OUString aLocalFileName = aModel.getLocalFileName();
789 if( !aLocalFileName.isEmpty() )
791 bContinueDownload = true;
793 // Try to get the number of bytes already on disk
794 osl::DirectoryItem aDirectoryItem;
795 if( osl::DirectoryItem::E_None == osl::DirectoryItem::get(aLocalFileName, aDirectoryItem) )
797 osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileSize);
798 if( osl::DirectoryItem::E_None == aDirectoryItem.getFileStatus(aFileStatus) )
800 sal_Int64 nDownloadSize = aModel.getDownloadSize();
801 sal_Int64 nFileSize = aFileStatus.getFileSize();
803 if( nDownloadSize > 0 )
805 if ( nDownloadSize <= nFileSize ) // we have already downloaded everthing
807 bContinueDownload = false;
808 bDownloadAvailable = true;
809 m_aImageName = getImageFromFileName( aLocalFileName );
811 else // Calculate initial percent value.
813 sal_Int32 nPercent = (sal_Int32) (100 * nFileSize / nDownloadSize);
814 getUpdateHandler()->setProgress( nPercent );
820 if ( bContinueDownload )
822 bool downloadPaused = aModel.isDownloadPaused();
824 enableDownload(true, downloadPaused);
825 setUIState(downloadPaused ? UPDATESTATE_DOWNLOAD_PAUSED : UPDATESTATE_DOWNLOADING);
829 if ( !bContinueDownload )
831 // We do this intentionally only if no download is in progress ..
832 if( obsoleteUpdateInfo )
834 // Bring-up release note for position 5 ..
835 const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 5));
836 if( !aURL.isEmpty() )
837 showReleaseNote(aURL);
839 // Data is outdated, probably due to installed update
840 rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( xContext, *this );
841 aConfig->clearUpdateFound();
842 aConfig->clearLocalFileName();
845 m_aUpdateInfo = UpdateInfo();
846 // Remove outdated release notes
847 storeReleaseNote( 1, rtl::OUString() );
848 storeReleaseNote( 2, rtl::OUString() );
850 else
852 enableAutoCheck(aModel.isAutoCheckEnabled());
853 if ( bDownloadAvailable )
854 setUIState( UPDATESTATE_DOWNLOAD_AVAIL );
855 else
856 setUIState(getUIState(m_aUpdateInfo));
862 //------------------------------------------------------------------------------
864 void
865 UpdateCheck::cancel()
867 osl::ClearableMutexGuard aGuard(m_aMutex);
869 WorkerThread *pThread = m_pThread;
870 UpdateState eUIState = getUIState(m_aUpdateInfo);
872 aGuard.clear();
874 if( NULL != pThread )
875 pThread->cancel();
877 setUIState(eUIState);
880 //------------------------------------------------------------------------------
882 void
883 UpdateCheck::download()
885 osl::ClearableMutexGuard aGuard(m_aMutex);
886 UpdateInfo aInfo(m_aUpdateInfo);
887 State eState = m_eState;
888 aGuard.clear();
890 if( aInfo.Sources[0].IsDirect )
892 // Ignore second click of a double click
893 if( DOWNLOADING != eState )
895 shutdownThread(true);
897 osl::ClearableMutexGuard aGuard2(m_aMutex);
898 enableDownload(true);
899 aGuard2.clear();
900 setUIState(UPDATESTATE_DOWNLOADING);
903 else
905 showReleaseNote(aInfo.Sources[0].URL); // Display in browser
909 //------------------------------------------------------------------------------
911 void
912 UpdateCheck::install()
914 osl::MutexGuard aGuard(m_aMutex);
916 const uno::Reference< c3s::XSystemShellExecute > xShellExecute(
917 createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ),
918 uno::UNO_QUERY );
920 try {
921 // Construct install command ??
923 // Store release note for position 3 and 4
924 rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 3));
925 storeReleaseNote(1, aURL);
927 aURL = getReleaseNote(m_aUpdateInfo, 4);
928 storeReleaseNote(2, aURL);
930 if( xShellExecute.is() )
932 rtl::OUString aInstallImage(m_aImageName);
933 osl::FileBase::getSystemPathFromFileURL(aInstallImage, aInstallImage);
935 rtl::OUString aParameter;
936 sal_Int32 nFlags = c3s::SystemShellExecuteFlags::DEFAULTS;
937 #if ( defined LINUX || defined SOLARIS )
938 nFlags = 42;
939 aParameter = getBaseInstallation();
940 if( !aParameter.isEmpty() )
941 osl::FileBase::getSystemPathFromFileURL(aParameter, aParameter);
943 aParameter += UNISTRING(" &");
944 #endif
946 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext );
947 rModel->clearLocalFileName();
949 xShellExecute->execute(aInstallImage, aParameter, nFlags);
950 ShutdownThread *pShutdownThread = new ShutdownThread( m_xContext );
951 (void) pShutdownThread;
953 } catch(const uno::Exception&) {
954 m_aUpdateHandler->setErrorMessage( m_aUpdateHandler->getDefaultInstErrMsg() );
958 //------------------------------------------------------------------------------
960 void
961 UpdateCheck::pause()
963 osl::ClearableMutexGuard aGuard(m_aMutex);
965 if( NULL != m_pThread )
966 m_pThread->suspend();
968 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
969 aGuard.clear();
971 rModel->storeDownloadPaused(true);
972 setUIState(UPDATESTATE_DOWNLOAD_PAUSED);
975 //------------------------------------------------------------------------------
977 void
978 UpdateCheck::resume()
980 osl::ClearableMutexGuard aGuard(m_aMutex);
982 if( NULL != m_pThread )
983 m_pThread->resume();
985 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
986 aGuard.clear();
988 rModel->storeDownloadPaused(false);
989 setUIState(UPDATESTATE_DOWNLOADING);
992 //------------------------------------------------------------------------------
994 void
995 UpdateCheck::closeAfterFailure()
997 osl::ClearableMutexGuard aGuard(m_aMutex);
999 if ( ( m_eState == DISABLED ) || ( m_eState == CHECK_SCHEDULED ) )
1001 const UpdateState eUIState = getUIState( m_aUpdateInfo );
1002 aGuard.clear();
1003 setUIState( eUIState, true );
1007 //------------------------------------------------------------------------------
1009 void
1010 UpdateCheck::shutdownThread(bool join)
1012 osl::ClearableMutexGuard aGuard(m_aMutex);
1014 // copy thread object pointer to stack
1015 osl::Thread *pThread = m_pThread;
1016 m_pThread = NULL;
1017 aGuard.clear();
1019 if( NULL != pThread )
1021 pThread->terminate();
1022 if( join )
1024 m_aCondition.set();
1025 pThread->join();
1026 m_aCondition.reset();
1031 //------------------------------------------------------------------------------
1033 void
1034 UpdateCheck::enableAutoCheck(bool enable)
1036 if( enable )
1037 m_pThread = new UpdateCheckThread(m_aCondition, m_xContext);
1039 m_eState = enable ? CHECK_SCHEDULED : DISABLED;
1042 //------------------------------------------------------------------------------
1044 void
1045 UpdateCheck::enableDownload(bool enable, bool paused)
1047 OSL_ASSERT(NULL == m_pThread);
1049 State eState = DISABLED;
1050 if( enable )
1052 m_pThread = new DownloadThread(m_aCondition, m_xContext, this, m_aUpdateInfo.Sources[0].URL );
1053 if( !paused )
1055 eState = DOWNLOADING;
1056 m_pThread->resume();
1058 else
1059 eState = DOWNLOAD_PAUSED;
1061 m_eState = eState;
1063 else {
1064 enableAutoCheck(UpdateCheckConfig::get(m_xContext)->isAutoCheckEnabled());
1069 //------------------------------------------------------------------------------
1071 bool
1072 UpdateCheck::downloadTargetExists(const rtl::OUString& rFileName)
1074 osl::ClearableMutexGuard aGuard(m_aMutex);
1076 rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
1077 UpdateState eUIState = UPDATESTATE_DOWNLOADING;
1079 bool cont = false;
1081 if( aUpdateHandler->isVisible() )
1083 cont = aUpdateHandler->showOverwriteWarning();
1084 if( cont )
1086 if( osl_File_E_None != osl_removeFile(rFileName.pData) )
1088 // FIXME: error message
1089 cont = false;
1092 else
1093 eUIState = getUIState(m_aUpdateInfo);
1095 else
1097 m_aImageName = getImageFromFileName(rFileName);
1098 eUIState = UPDATESTATE_DOWNLOAD_AVAIL;
1101 if( !cont )
1103 shutdownThread(false);
1104 enableDownload(false);
1106 aGuard.clear();
1107 setUIState(eUIState);
1110 return cont;
1113 //------------------------------------------------------------------------------
1114 bool UpdateCheck::checkDownloadDestination( const rtl::OUString& rFileName )
1116 osl::ClearableMutexGuard aGuard(m_aMutex);
1118 rtl::Reference< UpdateHandler > aUpdateHandler( getUpdateHandler() );
1120 bool bReload = false;
1122 if( aUpdateHandler->isVisible() )
1124 bReload = aUpdateHandler->showOverwriteWarning( rFileName );
1127 return bReload;
1130 //------------------------------------------------------------------------------
1132 void
1133 UpdateCheck::downloadStalled(const rtl::OUString& rErrorMessage)
1135 osl::ClearableMutexGuard aGuard(m_aMutex);
1136 rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
1137 aGuard.clear();
1139 aUpdateHandler->setErrorMessage(rErrorMessage);
1140 setUIState(UPDATESTATE_ERROR_DOWNLOADING);
1143 //------------------------------------------------------------------------------
1145 void
1146 UpdateCheck::downloadProgressAt(sal_Int8 nPercent)
1148 osl::ClearableMutexGuard aGuard(m_aMutex);
1149 rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
1150 aGuard.clear();
1152 aUpdateHandler->setProgress(nPercent);
1153 setUIState(UPDATESTATE_DOWNLOADING);
1156 //------------------------------------------------------------------------------
1158 void
1159 UpdateCheck::downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize)
1161 if ( nFileSize > 0 )
1163 osl::MutexGuard aGuard(m_aMutex);
1165 rtl::Reference< UpdateCheckConfig > aModel(UpdateCheckConfig::get(m_xContext));
1166 aModel->storeLocalFileName(rLocalFileName, nFileSize);
1168 // Bring-up release note for position 1 ..
1169 const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 1, aModel->isAutoDownloadEnabled()));
1170 if( !aURL.isEmpty() )
1171 showReleaseNote(aURL);
1175 //------------------------------------------------------------------------------
1177 void
1178 UpdateCheck::downloadFinished(const rtl::OUString& rLocalFileName)
1180 osl::ClearableMutexGuard aGuard(m_aMutex);
1182 // no more retries
1183 m_pThread->terminate();
1185 m_aImageName = getImageFromFileName(rLocalFileName);
1186 UpdateInfo aUpdateInfo(m_aUpdateInfo);
1188 aGuard.clear();
1189 setUIState(UPDATESTATE_DOWNLOAD_AVAIL);
1191 // Bring-up release note for position 2 ..
1192 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext );
1193 const rtl::OUString aURL(getReleaseNote(aUpdateInfo, 2, rModel->isAutoDownloadEnabled()));
1194 if( !aURL.isEmpty() )
1195 showReleaseNote(aURL);
1198 //------------------------------------------------------------------------------
1200 void
1201 UpdateCheck::cancelDownload()
1203 shutdownThread(true);
1205 osl::MutexGuard aGuard(m_aMutex);
1206 enableDownload(false);
1208 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
1210 rtl::OUString aLocalFile(rModel->getLocalFileName());
1211 rModel->clearLocalFileName();
1212 rModel->storeDownloadPaused(false);
1214 if( isObsoleteUpdateInfo(rModel->getUpdateEntryVersion()) )
1216 rModel->clearUpdateFound(); // This wasn't done during init yet ..
1217 m_aUpdateInfo = UpdateInfo();
1220 /*oslFileError rc =*/ osl_removeFile(aLocalFile.pData);
1221 // FIXME: error handling ..
1225 //------------------------------------------------------------------------------
1227 void
1228 UpdateCheck::showDialog(bool forceCheck)
1230 osl::ResettableMutexGuard aGuard(m_aMutex);
1232 bool update_found = !m_aUpdateInfo.BuildId.isEmpty();
1233 bool bSetUIState = ! m_aUpdateHandler.is();
1235 UpdateState eDialogState = UPDATESTATES_COUNT;
1237 switch( m_eState )
1239 case DISABLED:
1240 case CHECK_SCHEDULED:
1241 if( forceCheck || ! update_found ) // Run check when forced or if we did not find an update yet
1243 eDialogState = UPDATESTATE_CHECKING;
1244 bSetUIState = true;
1246 else if(m_aUpdateInfo.Sources[0].IsDirect)
1247 eDialogState = UPDATESTATE_UPDATE_AVAIL;
1248 else
1249 eDialogState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
1250 break;
1252 case DOWNLOADING:
1253 eDialogState = UPDATESTATE_DOWNLOADING;
1254 break;
1256 case DOWNLOAD_PAUSED:
1257 eDialogState = UPDATESTATE_DOWNLOAD_PAUSED;
1258 break;
1260 case NOT_INITIALIZED:
1261 OSL_ASSERT( false );
1262 break;
1265 if( bSetUIState )
1267 aGuard.clear();
1268 setUIState(eDialogState, true); // suppress bubble as Dialog will be visible soon
1269 aGuard.reset();
1272 getUpdateHandler()->setVisible(true);
1274 // Run check in separate thread ..
1275 if( UPDATESTATE_CHECKING == eDialogState )
1277 if( DISABLED == m_eState )
1279 // destructs itself when done, not cancellable for now ..
1280 new ManualUpdateCheckThread(m_aCondition, m_xContext);
1283 m_aCondition.set();
1287 //------------------------------------------------------------------------------
1289 void
1290 UpdateCheck::setUpdateInfo(const UpdateInfo& aInfo)
1292 osl::ClearableMutexGuard aGuard(m_aMutex);
1294 bool bSuppressBubble = (sal_True == aInfo.BuildId.equals(m_aUpdateInfo.BuildId));
1295 m_aUpdateInfo = aInfo;
1297 OSL_ASSERT(DISABLED == m_eState || CHECK_SCHEDULED == m_eState);
1299 // Ignore leading non direct download if we get direct ones
1300 std::vector< DownloadSource >::iterator iter = m_aUpdateInfo.Sources.begin();
1301 while( iter != m_aUpdateInfo.Sources.end() )
1303 if( iter->IsDirect )
1304 break;
1306 ++iter;
1309 if( (iter != m_aUpdateInfo.Sources.begin()) &&
1310 (iter != m_aUpdateInfo.Sources.end()) &&
1311 iter->IsDirect )
1313 m_aUpdateInfo.Sources.erase(m_aUpdateInfo.Sources.begin(), --iter);
1316 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *this);
1317 OSL_ASSERT( rModel.is() );
1319 // Decide whether to use alternate release note pos ..
1320 bool autoDownloadEnabled = rModel->isAutoDownloadEnabled();
1322 std::vector< ReleaseNote >::iterator iter2 = m_aUpdateInfo.ReleaseNotes.begin();
1323 while( iter2 != m_aUpdateInfo.ReleaseNotes.end() )
1325 if( ((1 == iter2->Pos) || (2 == iter2->Pos)) && autoDownloadEnabled && !iter2->URL2.isEmpty())
1327 iter2->URL = iter2->URL2;
1328 iter2->URL2 = rtl::OUString();
1329 iter2->Pos = iter2->Pos2;
1330 iter2->Pos2 = 0;
1333 ++iter2;
1336 // do not move below store/clear ..
1337 rModel->updateLastChecked();
1339 UpdateState eUIState;
1340 if( !m_aUpdateInfo.Sources.empty() )
1342 rModel->storeUpdateFound(aInfo, getBuildId());
1344 if( m_aUpdateInfo.Sources[0].IsDirect )
1346 eUIState = UPDATESTATE_UPDATE_AVAIL;
1348 if( rModel->isAutoDownloadEnabled() )
1350 shutdownThread(false);
1351 eUIState = UPDATESTATE_DOWNLOADING;
1352 enableDownload(true);
1355 else
1356 eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
1358 else
1360 eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
1361 rModel->clearUpdateFound();
1364 aGuard.clear();
1365 setUIState(eUIState, bSuppressBubble);
1368 //------------------------------------------------------------------------------
1370 void
1371 UpdateCheck::setCheckFailedState()
1373 setUIState(UPDATESTATE_ERROR_CHECKING);
1376 //------------------------------------------------------------------------------
1377 void UpdateCheck::handleMenuBarUI( rtl::Reference< UpdateHandler > rUpdateHandler,
1378 UpdateState& eState,
1379 bool suppressBubble )
1381 uno::Reference<beans::XPropertySet> xMenuBarUI( m_xMenuBarUI );
1383 if ( ( UPDATESTATE_NO_UPDATE_AVAIL == eState ) && m_bHasExtensionUpdate )
1384 eState = UPDATESTATE_EXT_UPD_AVAIL;
1386 if ( UPDATESTATE_EXT_UPD_AVAIL == eState )
1387 m_bShowExtUpdDlg = true;
1388 else
1389 m_bShowExtUpdDlg = false;
1391 if( xMenuBarUI.is() )
1393 if( UPDATESTATE_NO_UPDATE_AVAIL == eState )
1395 xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_False) );
1397 else
1399 xMenuBarUI->setPropertyValue( PROPERTY_TITLE, uno::makeAny(rUpdateHandler->getBubbleTitle(eState)) );
1400 xMenuBarUI->setPropertyValue( PROPERTY_TEXT, uno::makeAny(rUpdateHandler->getBubbleText(eState)) );
1402 if( ! suppressBubble && ( ! rUpdateHandler->isVisible() || rUpdateHandler->isMinimized() ) )
1403 xMenuBarUI->setPropertyValue( PROPERTY_SHOW_BUBBLE, uno::makeAny( sal_True ) );
1405 if( UPDATESTATE_CHECKING != eState )
1406 xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_True) );
1411 //------------------------------------------------------------------------------
1412 void UpdateCheck::setUIState(UpdateState eState, bool suppressBubble)
1414 osl::ClearableMutexGuard aGuard(m_aMutex);
1416 if( ! m_xMenuBarUI.is() &&
1417 (DISABLED != m_eState) &&
1418 ( m_bHasExtensionUpdate || (UPDATESTATE_NO_UPDATE_AVAIL != eState)) &&
1419 (UPDATESTATE_CHECKING != eState) &&
1420 (UPDATESTATE_ERROR_CHECKING != eState)
1423 m_xMenuBarUI = createMenuBarUI(m_xContext, new MenuBarButtonJob(this));
1426 // Show bubble only when the status has changed
1427 if ( eState == m_eUpdateState )
1428 suppressBubble = true;
1429 else
1430 m_eUpdateState = eState;
1432 rtl::Reference<UpdateHandler> aUpdateHandler(getUpdateHandler());
1433 OSL_ASSERT( aUpdateHandler.is() );
1435 UpdateInfo aUpdateInfo(m_aUpdateInfo);
1436 rtl::OUString aImageName(m_aImageName);
1438 aGuard.clear();
1440 handleMenuBarUI( aUpdateHandler, eState, suppressBubble );
1442 if( (UPDATESTATE_UPDATE_AVAIL == eState)
1443 || (UPDATESTATE_DOWNLOAD_PAUSED == eState)
1444 || (UPDATESTATE_DOWNLOADING == eState) )
1446 uno::Reference< uno::XComponentContext > xContext(m_xContext);
1448 rtl::OUString aDownloadDestination =
1449 UpdateCheckConfig::get(xContext, this)->getDownloadDestination();
1451 osl_getSystemPathFromFileURL(aDownloadDestination.pData, &aDownloadDestination.pData);
1453 aUpdateHandler->setDownloadPath(aDownloadDestination);
1455 else if( UPDATESTATE_DOWNLOAD_AVAIL == eState )
1457 aUpdateHandler->setDownloadFile(aImageName);
1460 aUpdateHandler->setDescription(aUpdateInfo.Description);
1461 aUpdateHandler->setNextVersion(aUpdateInfo.Version);
1462 aUpdateHandler->setState(eState);
1465 //------------------------------------------------------------------------------
1467 UpdateState
1468 UpdateCheck::getUIState(const UpdateInfo& rInfo)
1470 UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
1472 if( !rInfo.BuildId.isEmpty() )
1474 if( rInfo.Sources[0].IsDirect )
1475 eUIState = UPDATESTATE_UPDATE_AVAIL;
1476 else
1477 eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
1480 return eUIState;
1483 //------------------------------------------------------------------------------
1485 void
1486 UpdateCheck::showReleaseNote(const rtl::OUString& rURL) const
1488 const uno::Reference< c3s::XSystemShellExecute > xShellExecute(
1489 createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ),
1490 uno::UNO_QUERY );
1492 try {
1494 if( xShellExecute.is() )
1495 xShellExecute->execute(rURL, rtl::OUString(), c3s::SystemShellExecuteFlags::URIS_ONLY);
1496 } catch(const c3s::SystemShellExecuteException&) {
1500 //------------------------------------------------------------------------------
1502 bool
1503 UpdateCheck::storeReleaseNote(sal_Int8 nNum, const rtl::OUString &rURL)
1505 osl::FileBase::RC rc;
1506 rtl::OUString aTargetDir( UpdateCheckConfig::getAllUsersDirectory() + UNISTRING( "/sun" ) );
1508 rc = osl::Directory::createPath( aTargetDir );
1510 rtl::OUString aFileName = UNISTRING("releasenote") +
1511 rtl::OUString::valueOf( (sal_Int32) nNum ) +
1512 UNISTRING(".url");
1514 rtl::OUString aFilePath;
1515 rc = osl::FileBase::getAbsoluteFileURL( aTargetDir, aFileName, aFilePath );
1516 if ( rc != osl::FileBase::E_None ) return false;
1518 rc = osl::File::remove( aFilePath );
1520 // don't store empty release notes, but delete old ones
1521 if ( rURL.isEmpty() )
1522 return true;
1524 osl::File aFile( aFilePath );
1525 rc = aFile.open( osl_File_OpenFlag_Write | osl_File_OpenFlag_Create );
1527 if ( rc != osl::FileBase::E_None ) return false;
1529 rtl::OString aLineBuf("[InternetShortcut]\r\n");
1530 sal_uInt64 nWritten = 0;
1532 rtl::OUString aURL( rURL );
1533 #ifdef WNT
1534 rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten );
1535 if ( rc != osl::FileBase::E_None ) return false;
1536 aURL = UNISTRING("URL=") + rURL;
1537 #endif
1538 aLineBuf = rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 );
1539 rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten );
1540 if ( rc != osl::FileBase::E_None ) return false;
1542 aFile.close();
1543 return true;
1546 //------------------------------------------------------------------------------
1547 void UpdateCheck::showExtensionDialog()
1549 rtl::OUString sServiceName = UNISTRING("com.sun.star.deployment.ui.PackageManagerDialog");
1550 rtl::OUString sArguments = UNISTRING("SHOW_UPDATE_DIALOG");
1551 uno::Reference< uno::XInterface > xService;
1553 if( ! m_xContext.is() )
1554 throw uno::RuntimeException(
1555 UNISTRING( "UpdateCheck::showExtensionDialog(): empty component context" ), uno::Reference< uno::XInterface > () );
1557 uno::Reference< lang::XMultiComponentFactory > xServiceManager( m_xContext->getServiceManager() );
1558 if( !xServiceManager.is() )
1559 throw uno::RuntimeException(
1560 UNISTRING( "UpdateCheck::showExtensionDialog(): unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () );
1562 xService = xServiceManager->createInstanceWithContext( sServiceName, m_xContext );
1563 uno::Reference< task::XJobExecutor > xExecuteable( xService, uno::UNO_QUERY );
1564 if ( xExecuteable.is() )
1565 xExecuteable->trigger( sArguments );
1568 //------------------------------------------------------------------------------
1570 rtl::Reference<UpdateHandler>
1571 UpdateCheck::getUpdateHandler()
1573 osl::MutexGuard aGuard(m_aMutex);
1575 if( ! m_aUpdateHandler.is() )
1576 m_aUpdateHandler = new UpdateHandler(m_xContext, this);
1578 return m_aUpdateHandler;
1581 //------------------------------------------------------------------------------
1583 uno::Reference< task::XInteractionHandler >
1584 UpdateCheck::getInteractionHandler() const
1586 osl::MutexGuard aGuard(m_aMutex);
1588 uno::Reference< task::XInteractionHandler > xHandler;
1590 if( m_aUpdateHandler.is() && m_aUpdateHandler->isVisible() )
1591 xHandler = m_aUpdateHandler.get();
1593 return xHandler;
1596 //------------------------------------------------------------------------------
1598 uno::Reference< uno::XInterface >
1599 UpdateCheck::createService(const rtl::OUString& rServiceName,
1600 const uno::Reference<uno::XComponentContext>& xContext)
1602 if( !xContext.is() )
1603 throw uno::RuntimeException(
1604 UNISTRING( "UpdateCheckConfig: empty component context" ),
1605 uno::Reference< uno::XInterface >() );
1607 const uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
1609 if( !xServiceManager.is() )
1610 throw uno::RuntimeException(
1611 UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ),
1612 uno::Reference< uno::XInterface >() );
1614 return xServiceManager->createInstanceWithContext(rServiceName, xContext);
1617 //------------------------------------------------------------------------------
1619 bool
1620 UpdateCheck::isDialogShowing() const
1622 osl::MutexGuard aGuard(m_aMutex);
1623 return sal_True == m_aUpdateHandler.is() && m_aUpdateHandler->isVisible();
1626 //------------------------------------------------------------------------------
1628 void
1629 UpdateCheck::autoCheckStatusChanged(bool enabled)
1631 osl::ClearableMutexGuard aGuard(m_aMutex);
1633 if( (CHECK_SCHEDULED == m_eState) && !enabled )
1634 shutdownThread(false);
1636 if( (DISABLED == m_eState) || (CHECK_SCHEDULED == m_eState) )
1638 enableAutoCheck(enabled);
1639 UpdateState eState = getUIState(m_aUpdateInfo);
1640 aGuard.clear();
1641 setUIState(eState);
1645 //------------------------------------------------------------------------------
1647 void
1648 UpdateCheck::autoCheckIntervalChanged()
1650 // just wake-up
1651 m_aCondition.set();
1654 //------------------------------------------------------------------------------
1656 oslInterlockedCount SAL_CALL
1657 UpdateCheck::acquire() SAL_THROW(())
1659 return ReferenceObject::acquire();
1662 //------------------------------------------------------------------------------
1664 oslInterlockedCount SAL_CALL
1665 UpdateCheck::release() SAL_THROW(())
1667 return ReferenceObject::release();
1670 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */