merged tag ooo/OOO330_m14
[LibreOffice.git] / extensions / source / update / check / updatecheck.cxx
blob8419569bd9494254eb3e108e2e7f73eb54f20c6f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_extensions.hxx"
31 #include "updatecheck.hxx"
33 #include <cppuhelper/implbase1.hxx>
34 #include <com/sun/star/beans/XFastPropertySet.hpp>
35 #include <com/sun/star/lang/XComponent.hpp>
36 #include <com/sun/star/frame/XDesktop.hpp>
37 #include <com/sun/star/frame/XFrame.hpp>
38 #include <com/sun/star/frame/DispatchResultEvent.hpp>
39 #include <com/sun/star/frame/DispatchResultState.hpp>
40 #include <com/sun/star/system/XSystemShellExecute.hpp>
41 #include <com/sun/star/system/SystemShellExecuteFlags.hpp>
42 #include <com/sun/star/task/XJob.hpp>
43 #include <com/sun/star/task/XJobExecutor.hpp>
45 // #include <comphelper/processfactory.hxx>
47 #include <rtl/ustrbuf.hxx>
49 #include <rtl/bootstrap.hxx>
50 #include <osl/process.h>
51 #include <osl/module.hxx>
52 #include <osl/file.hxx>
54 #ifdef WNT
55 #ifdef _MSC_VER
56 #pragma warning(push,1) // disable warnings within system headers
57 //#pragma warning(disable: 4917)
58 #endif
59 #include <objbase.h>
60 #ifdef _MSC_VER
61 #pragma warning(pop)
62 #endif
63 #endif
65 #include "updateprotocol.hxx"
66 #include "updatecheckconfig.hxx"
68 namespace awt = com::sun::star::awt ;
69 namespace beans = com::sun::star::beans ;
70 namespace container = com::sun::star::container ;
71 namespace deployment = com::sun::star::deployment ;
72 namespace frame = com::sun::star::frame ;
73 namespace lang = com::sun::star::lang ;
74 namespace c3s = com::sun::star::system ;
75 namespace task = com::sun::star::task ;
76 namespace util = com::sun::star::util ;
77 namespace uno = com::sun::star::uno ;
79 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
81 #define PROPERTY_TITLE UNISTRING("BubbleHeading")
82 #define PROPERTY_TEXT UNISTRING("BubbleText")
83 #define PROPERTY_IMAGE UNISTRING("BubbleImageURL")
84 #define PROPERTY_SHOW_BUBBLE UNISTRING("BubbleVisible")
85 #define PROPERTY_CLICK_HDL UNISTRING("MenuClickHDL")
86 #define PROPERTY_DEFAULT_TITLE UNISTRING("DefaultHeading")
87 #define PROPERTY_DEFAULT_TEXT UNISTRING("DefaultText")
88 #define PROPERTY_SHOW_MENUICON UNISTRING("MenuIconVisible")
90 //------------------------------------------------------------------------------
92 // Returns the URL of the release note for the given position
93 rtl::OUString getReleaseNote(const UpdateInfo& rInfo, sal_uInt8 pos, bool autoDownloadEnabled)
95 std::vector< ReleaseNote >::const_iterator iter = rInfo.ReleaseNotes.begin();
96 while( iter != rInfo.ReleaseNotes.end() )
98 if( pos == iter->Pos )
100 if( (pos > 2) || !autoDownloadEnabled || ! (iter->URL2.getLength() > 0) )
101 return iter->URL;
103 else if( (pos == iter->Pos2) && ((1 == iter->Pos) || (2 == iter->Pos)) && autoDownloadEnabled )
104 return iter->URL2;
106 ++iter;
109 return rtl::OUString();
112 //------------------------------------------------------------------------------
114 namespace
117 static inline rtl::OUString getBuildId()
119 rtl::OUString aPathVal(UNISTRING("${$OOO_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}"));
120 rtl::Bootstrap::expandMacros(aPathVal);
121 return aPathVal;
124 //------------------------------------------------------------------------------
125 static inline rtl::OUString getBaseInstallation()
127 rtl::OUString aPathVal(UNISTRING("${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("bootstrap") ":BaseInstallation}"));
128 rtl::Bootstrap::expandMacros(aPathVal);
129 return aPathVal;
132 //------------------------------------------------------------------------------
134 inline bool isObsoleteUpdateInfo(const rtl::OUString& rBuildId)
136 return sal_True != rBuildId.equals(getBuildId()) && rBuildId.getLength() > 0;
140 //------------------------------------------------------------------------------
142 rtl::OUString getImageFromFileName(const rtl::OUString& aFile)
144 #ifndef WNT
145 rtl::OUString aUnpackPath;
146 if( osl_getExecutableFile(&aUnpackPath.pData) == osl_Process_E_None )
148 sal_uInt32 lastIndex = aUnpackPath.lastIndexOf('/');
149 if ( lastIndex > 0 )
151 aUnpackPath = aUnpackPath.copy( 0, lastIndex+1 );
152 aUnpackPath += UNISTRING( "unpack_update" );
155 oslFileHandle hOut = NULL;
156 oslProcess hProcess = NULL;
158 rtl::OUString aSystemPath;
159 osl::File::getSystemPathFromFileURL(aFile, aSystemPath);
161 oslProcessError rc = osl_executeProcess_WithRedirectedIO(
162 aUnpackPath.pData, // [in] Image name
163 &aSystemPath.pData, 1, // [in] Arguments
164 osl_Process_WAIT || osl_Process_NORMAL, // [in] Options
165 NULL, // [in] Security
166 NULL, // [in] Working directory
167 NULL, 0, // [in] Environment variables
168 &hProcess, // [out] Process handle
169 NULL, &hOut, NULL // [out] File handles for redirected I/O
172 if( osl_Process_E_None == rc )
174 oslProcessInfo aInfo;
175 aInfo.Size = sizeof(oslProcessInfo);
177 if( osl_Process_E_None == osl_getProcessInfo(hProcess, osl_Process_EXITCODE, &aInfo) )
179 if( 0 == aInfo.Code )
181 sal_Char szBuffer[4096];
182 sal_uInt64 nBytesRead = 0;
183 const sal_uInt64 nBytesToRead = sizeof(szBuffer) - 1;
185 rtl::OUString aImageName;
186 while( osl_File_E_None == osl_readFile(hOut, szBuffer, nBytesToRead, &nBytesRead) )
188 sal_Char *pc = szBuffer + nBytesRead;
191 *pc = '\0'; --pc;
193 while( ('\n' == *pc) || ('\r' == *pc) );
195 aImageName += rtl::OUString(szBuffer, pc - szBuffer + 1, osl_getThreadTextEncoding());
197 if( nBytesRead < nBytesToRead )
198 break;
201 if( osl::FileBase::E_None == osl::FileBase::getFileURLFromSystemPath(aImageName, aImageName) )
202 return aImageName;
206 osl_closeFile(hOut);
207 osl_freeProcessHandle(hProcess);
210 #endif
212 return aFile;
216 //------------------------------------------------------------------------------
218 static uno::Reference< beans::XPropertySet > createMenuBarUI(
219 const uno::Reference< uno::XComponentContext >& xContext,
220 const uno::Reference< task::XJob >& xJob)
222 if( !xContext.is() )
223 throw uno::RuntimeException(
224 UNISTRING( "UpdateCheckJob: empty component context" ), uno::Reference< uno::XInterface > () );
226 uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
227 if( !xServiceManager.is() )
228 throw uno::RuntimeException(
229 UNISTRING( "UpdateCheckJob: unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () );
231 uno::Reference< beans::XPropertySet > xMenuBarUI =
232 uno::Reference< beans::XPropertySet > (
233 xServiceManager->createInstanceWithContext( UNISTRING( "com.sun.star.setup.UpdateCheckUI" ), xContext ),
234 uno::UNO_QUERY_THROW);
236 xMenuBarUI->setPropertyValue( PROPERTY_CLICK_HDL, uno::makeAny( xJob ) );
238 return xMenuBarUI;
241 //------------------------------------------------------------------------------
245 typedef sal_Bool (* OnlineCheckFunc) ();
247 class UpdateCheckThread : public WorkerThread
250 public:
251 UpdateCheckThread( osl::Condition& rCondition,
252 const uno::Reference<uno::XComponentContext>& xContext );
254 virtual void SAL_CALL join();
255 virtual void SAL_CALL terminate();
256 virtual void SAL_CALL cancel();
258 protected:
259 virtual ~UpdateCheckThread();
261 virtual void SAL_CALL run();
262 virtual void SAL_CALL onTerminated();
264 /* Wrapper around checkForUpdates */
265 bool runCheck( bool & rbExtensionsChecked );
267 private:
269 /* Used to avoid dialup login windows (on platforms we know how to double this) */
270 inline bool hasInternetConnection() const
272 if(m_pHasInternetConnection != NULL )
273 return (sal_True == m_pHasInternetConnection());
274 return true;
277 /* Creates a new instance of UpdateInformationProvider and returns this instance */
278 inline uno::Reference<deployment::XUpdateInformationProvider> createProvider()
280 osl::MutexGuard aGuard(m_aMutex);
281 m_xProvider = deployment::UpdateInformationProvider::create(m_xContext);
282 return m_xProvider;
285 /* Returns the remembered instance of UpdateInformationProvider if any */
286 inline uno::Reference<deployment::XUpdateInformationProvider> getProvider()
287 { osl::MutexGuard aGuard(m_aMutex); return m_xProvider; };
289 /* Releases the remembered instance of UpdateInformationProvider if any */
290 inline void clearProvider()
291 { osl::MutexGuard aGuard(m_aMutex); m_xProvider.clear(); };
293 osl::Mutex m_aMutex;
294 osl::Module m_aModule;
296 protected:
297 osl::Condition& m_aCondition;
299 private:
301 // const
302 OnlineCheckFunc m_pHasInternetConnection;
304 const uno::Reference<uno::XComponentContext> m_xContext;
305 uno::Reference<deployment::XUpdateInformationProvider> m_xProvider;
309 class ManualUpdateCheckThread : public UpdateCheckThread
311 public:
312 ManualUpdateCheckThread( osl::Condition& rCondition, const uno::Reference<uno::XComponentContext>& xContext ) :
313 UpdateCheckThread(rCondition, xContext) {};
315 virtual void SAL_CALL run();
319 class MenuBarButtonJob : public ::cppu::WeakImplHelper1< task::XJob >
321 public:
322 MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck);
324 // XJob
325 virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&)
326 throw (lang::IllegalArgumentException, uno::Exception);
328 private:
329 rtl::Reference< UpdateCheck > m_aUpdateCheck;
332 class DownloadThread : public WorkerThread
334 public:
335 DownloadThread(
336 osl::Condition& rCondition,
337 const uno::Reference<uno::XComponentContext>& xContext,
338 const rtl::Reference< DownloadInteractionHandler >& rHandler,
339 const rtl::OUString& rURL );
341 virtual void SAL_CALL run();
342 virtual void SAL_CALL cancel();
343 virtual void SAL_CALL suspend();
344 virtual void SAL_CALL onTerminated();
346 protected:
347 ~DownloadThread();
349 private:
350 osl::Condition& m_aCondition;
351 const uno::Reference<uno::XComponentContext> m_xContext;
352 const rtl::OUString m_aURL;
353 Download m_aDownload;
356 //------------------------------------------------------------------------------
357 class ShutdownThread : public osl::Thread
359 public:
360 ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext );
362 virtual void SAL_CALL run();
363 virtual void SAL_CALL onTerminated();
365 protected:
366 ~ShutdownThread();
368 private:
369 osl::Condition m_aCondition;
370 const uno::Reference<uno::XComponentContext> m_xContext;
373 //------------------------------------------------------------------------------
375 UpdateCheckThread::UpdateCheckThread( osl::Condition& rCondition,
376 const uno::Reference<uno::XComponentContext>& xContext ) :
377 m_aCondition(rCondition),
378 m_pHasInternetConnection(NULL),
379 m_xContext(xContext)
382 #ifdef WNT
383 rtl::OUString aPath;
384 if( osl_getExecutableFile(&aPath.pData) == osl_Process_E_None )
386 sal_uInt32 lastIndex = aPath.lastIndexOf('/');
387 if ( lastIndex > 0 )
389 aPath = aPath.copy( 0, lastIndex+1 );
390 aPath += UNISTRING( "onlinecheck" );
393 if ( m_aModule.load(aPath) )
395 m_pHasInternetConnection =
396 reinterpret_cast < OnlineCheckFunc > (
397 m_aModule.getFunctionSymbol( UNISTRING("hasInternetConnection")));
400 #endif
402 createSuspended();
404 // actually run the thread
405 resume();
408 //------------------------------------------------------------------------------
410 UpdateCheckThread::~UpdateCheckThread()
414 //------------------------------------------------------------------------------
417 void SAL_CALL
418 UpdateCheckThread::terminate()
420 // Cancel potentially hanging http request ..
421 cancel();
422 // .. before terminating
423 osl::Thread::terminate();
426 //------------------------------------------------------------------------------
428 void SAL_CALL
429 UpdateCheckThread::join()
431 uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider());
433 // do not join during an update check until #i73893# is fixed
434 if( ! xProvider.is() )
436 osl::Thread::join();
440 //------------------------------------------------------------------------------
442 void SAL_CALL
443 UpdateCheckThread::cancel()
445 uno::Reference< deployment::XUpdateInformationProvider > xProvider(getProvider());
447 if( xProvider.is() )
448 xProvider->cancel();
451 //------------------------------------------------------------------------------
453 bool
454 UpdateCheckThread::runCheck( bool & rbExtensionsChecked )
456 bool ret = false;
457 UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
459 UpdateInfo aInfo;
460 rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
462 if( checkForUpdates(aInfo, m_xContext, aController->getInteractionHandler(), createProvider()) )
464 aController->setUpdateInfo(aInfo);
465 eUIState = aController->getUIState(aInfo);
466 ret = true;
468 else
469 aController->setCheckFailedState();
471 // We will only look for extension updates, when there is no 'check for office updates' dialog open
472 // and when there was no office update found
473 if ( ( eUIState != UPDATESTATE_UPDATE_AVAIL ) &&
474 ( eUIState != UPDATESTATE_UPDATE_NO_DOWNLOAD ) &&
475 !aController->isDialogShowing() &&
476 !rbExtensionsChecked )
478 bool bHasExtensionUpdates = checkForExtensionUpdates( m_xContext );
479 aController->setHasExtensionUpdates( bHasExtensionUpdates );
480 if ( bHasExtensionUpdates )
481 aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL );
482 rbExtensionsChecked = true;
485 // joining with this thread is safe again
486 clearProvider();
487 return ret;
490 //------------------------------------------------------------------------------
492 void SAL_CALL
493 UpdateCheckThread::onTerminated()
495 delete this;
498 //------------------------------------------------------------------------------
500 void SAL_CALL
501 UpdateCheckThread::run()
503 bool bExtensionsChecked = false;
504 TimeValue systime;
505 TimeValue nExtCheckTime;
506 osl_getSystemTime( &nExtCheckTime );
508 osl::Condition::Result aResult = osl::Condition::result_timeout;
509 TimeValue tv = { 10, 0 };
511 // Initial wait to avoid doing further time consuming tasks during start-up
512 aResult = m_aCondition.wait(&tv);
514 try {
516 while( sal_True == schedule() )
518 /* Use cases:
519 * a) manual check requested from auto check thread - "last check" should not be checked (one time)
520 * a1) manual check was requested in the middle of a running auto check,
521 * condition is set
522 * a2) manual check was requested while waiting for a retry,
523 * condition is set
524 * a3) manual check was requested while waiting for time to next
525 * scheduled check elapsing, condition is set
526 * a4) manual check was requested during initial wait, condition is set
527 * b) check interval got changed, condition may be set - same sub-cases as a),
528 * but "last check" should be honored
529 * c) normal auto check mode, condition not set - "last check" should be honored
532 // Accessing const members without synchronization
533 rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
534 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *aController);
536 // FIXME: remember last & offset ?
537 sal_Int64 last = rModel->getLastChecked();
538 sal_Int64 offset = rModel->getCheckInterval();
540 rModel.clear();
542 // last == 0 means check immediately
543 bool checkNow = ! (last > 0);
545 // Reset the condition to avoid busy loops
546 if( osl::Condition::result_ok == aResult )
548 m_aCondition.reset();
549 aResult = osl::Condition::result_timeout;
550 checkNow = aController->isDialogShowing();
553 if( ! checkNow )
555 osl_getSystemTime(&systime);
557 // Go back to sleep until time has elapsed
558 sal_Int64 next = last + offset;
559 if( last + offset > systime.Seconds )
561 // This can not be > 32 Bit for now ..
562 tv.Seconds = static_cast< sal_Int32 > (next - systime.Seconds);
563 aResult = m_aCondition.wait(&tv);
564 continue;
568 static sal_uInt8 n = 0;
570 if( ! hasInternetConnection() || ! runCheck( bExtensionsChecked ) )
572 // the extension update check should be independent from the office update check
574 osl_getSystemTime( &systime );
575 if ( nExtCheckTime.Seconds + offset < systime.Seconds )
576 bExtensionsChecked = false;
578 // Increase next by 15, 60, .. minutes
579 static const sal_Int32 nRetryInterval[] = { 900, 3600, 14400, 86400 };
581 if( n < sizeof(nRetryInterval) / sizeof(sal_Int32) )
582 ++n;
584 tv.Seconds = nRetryInterval[n-1];
585 aResult = m_aCondition.wait(&tv);
587 else // reset retry counter
589 n = 0;
590 bExtensionsChecked = false;
595 catch(const uno::Exception& e) {
596 // Silently catch all errors
597 OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
598 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
602 //------------------------------------------------------------------------------
604 void SAL_CALL
605 ManualUpdateCheckThread::run()
607 bool bExtensionsChecked = false;
609 try {
610 runCheck( bExtensionsChecked );
611 m_aCondition.reset();
613 catch(const uno::Exception& e) {
614 // Silently catch all errors
615 OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
616 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr() );
620 //------------------------------------------------------------------------------
622 MenuBarButtonJob::MenuBarButtonJob(const rtl::Reference< UpdateCheck >& rUpdateCheck) :
623 m_aUpdateCheck(rUpdateCheck)
627 //------------------------------------------------------------------------------
629 uno::Any SAL_CALL
630 MenuBarButtonJob::execute(const uno::Sequence<beans::NamedValue>& )
631 throw (lang::IllegalArgumentException, uno::Exception)
633 if ( m_aUpdateCheck->shouldShowExtUpdDlg() )
634 m_aUpdateCheck->showExtensionDialog();
635 else
636 m_aUpdateCheck->showDialog();
638 return uno::Any();
641 //------------------------------------------------------------------------------
643 DownloadThread::DownloadThread(osl::Condition& rCondition,
644 const uno::Reference<uno::XComponentContext>& xContext,
645 const rtl::Reference< DownloadInteractionHandler >& rHandler,
646 const rtl::OUString& rURL) :
647 m_aCondition(rCondition),
648 m_xContext(xContext),
649 m_aURL(rURL),
650 m_aDownload(xContext, rHandler)
652 createSuspended();
655 //------------------------------------------------------------------------------
657 DownloadThread::~DownloadThread()
661 //------------------------------------------------------------------------------
663 void SAL_CALL
664 DownloadThread::run()
666 #ifdef WNT
667 CoUninitialize();
668 CoInitialize( NULL );
669 #endif
671 while( schedule() )
673 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
675 rtl::OUString aLocalFile = rModel->getLocalFileName();
676 rtl::OUString aDownloadDest = rModel->getDownloadDestination();
678 // release config class for now
679 rModel.clear();
681 static sal_uInt8 n = 0;
682 if( ! m_aDownload.start(m_aURL, aLocalFile, aDownloadDest ) )
684 // retry every 15s unless the dialog is not visible
685 TimeValue tv;
686 tv.Seconds = 15;
688 if( ! UpdateCheck::get()->isDialogShowing() )
690 // Increase next by 1, 5, 15, 60, .. minutes
691 static const sal_Int16 nRetryInterval[] = { 60, 300, 900, 3600 };
693 if( n < sizeof(nRetryInterval) / sizeof(sal_Int16) )
694 ++n;
696 tv.Seconds = nRetryInterval[n-1];
698 m_aCondition.wait(&tv);
700 else
702 // reset wait period after successful download
703 n=0;
708 //------------------------------------------------------------------------------
710 void SAL_CALL DownloadThread::cancel()
712 m_aDownload.stop();
713 resume();
715 rtl::Reference< UpdateCheck > aController(UpdateCheck::get());
716 aController->cancelDownload();
719 //------------------------------------------------------------------------------
721 void SAL_CALL DownloadThread::suspend()
723 osl::Thread::suspend();
724 m_aDownload.stop();
727 //------------------------------------------------------------------------------
729 void SAL_CALL DownloadThread::onTerminated()
731 delete this;
734 //------------------------------------------------------------------------------
735 ShutdownThread::ShutdownThread( const uno::Reference<uno::XComponentContext>& xContext) :
736 m_xContext( xContext )
738 create();
741 //------------------------------------------------------------------------------
742 ShutdownThread::~ShutdownThread()
746 //------------------------------------------------------------------------------
747 void SAL_CALL
748 ShutdownThread::run()
750 TimeValue tv = { 0, 250 };
752 m_aCondition.wait(&tv);
754 // Tell QuickStarter not to veto ..
755 uno::Reference< beans::XFastPropertySet > xQuickStarter(
756 UpdateCheck::createService(UNISTRING("com.sun.star.office.Quickstart"), m_xContext),
757 uno::UNO_QUERY
760 if (xQuickStarter.is())
761 xQuickStarter->setFastPropertyValue(0, uno::makeAny(false));
763 // Shutdown the office
764 uno::Reference< frame::XDesktop > xDesktop(
765 UpdateCheck::createService(UNISTRING("com.sun.star.frame.Desktop"), m_xContext),
766 uno::UNO_QUERY);
768 if( xDesktop.is() )
769 xDesktop->terminate();
772 //------------------------------------------------------------------------------
773 void SAL_CALL ShutdownThread::onTerminated()
775 delete this;
778 //------------------------------------------------------------------------------
780 } // anonymous namespace
783 //------------------------------------------------------------------------------
786 void
787 UpdateCheck::initialize(const uno::Sequence< beans::NamedValue >& rValues,
788 const uno::Reference<uno::XComponentContext>& xContext)
790 osl::MutexGuard aGuard(m_aMutex);
792 if( NOT_INITIALIZED == m_eState )
794 NamedValueByNameAccess aNameAccess(rValues);
795 UpdateCheckROModel aModel( aNameAccess );
796 m_xContext = xContext;
798 rtl::OUString aUpdateEntryVersion = aModel.getUpdateEntryVersion();
800 aModel.getUpdateEntry(m_aUpdateInfo);
802 bool obsoleteUpdateInfo = isObsoleteUpdateInfo(aUpdateEntryVersion);
803 bool bContinueDownload = false;
804 bool bDownloadAvailable = false;
806 m_bHasExtensionUpdate = checkForPendingUpdates( xContext );
807 m_bShowExtUpdDlg = false;
809 rtl::OUString aLocalFileName = aModel.getLocalFileName();
811 if( aLocalFileName.getLength() > 0 )
813 bContinueDownload = true;
815 // Try to get the number of bytes already on disk
816 osl::DirectoryItem aDirectoryItem;
817 if( osl::DirectoryItem::E_None == osl::DirectoryItem::get(aLocalFileName, aDirectoryItem) )
819 osl::FileStatus aFileStatus(FileStatusMask_FileSize);
820 if( osl::DirectoryItem::E_None == aDirectoryItem.getFileStatus(aFileStatus) )
822 sal_Int64 nDownloadSize = aModel.getDownloadSize();
823 sal_Int64 nFileSize = aFileStatus.getFileSize();
825 if( nDownloadSize > 0 )
827 if ( nDownloadSize <= nFileSize ) // we have already downloaded everthing
829 bContinueDownload = false;
830 bDownloadAvailable = true;
831 m_aImageName = getImageFromFileName( aLocalFileName );
833 else // Calculate initial percent value.
835 sal_Int32 nPercent = (sal_Int32) (100 * nFileSize / nDownloadSize);
836 getUpdateHandler()->setProgress( nPercent );
842 if ( bContinueDownload )
844 bool downloadPaused = aModel.isDownloadPaused();
846 enableDownload(true, downloadPaused);
847 setUIState(downloadPaused ? UPDATESTATE_DOWNLOAD_PAUSED : UPDATESTATE_DOWNLOADING);
851 if ( !bContinueDownload )
853 // We do this intentionally only if no download is in progress ..
854 if( obsoleteUpdateInfo )
856 // Bring-up release note for position 5 ..
857 const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 5));
858 if( aURL.getLength() > 0 )
859 showReleaseNote(aURL);
861 // Data is outdated, probably due to installed update
862 rtl::Reference< UpdateCheckConfig > aConfig = UpdateCheckConfig::get( xContext, *this );
863 aConfig->clearUpdateFound();
864 aConfig->clearLocalFileName();
867 m_aUpdateInfo = UpdateInfo();
868 // Remove outdated release notes
869 storeReleaseNote( 1, rtl::OUString() );
870 storeReleaseNote( 2, rtl::OUString() );
872 else
874 enableAutoCheck(aModel.isAutoCheckEnabled());
875 if ( bDownloadAvailable )
876 setUIState( UPDATESTATE_DOWNLOAD_AVAIL );
877 else
878 setUIState(getUIState(m_aUpdateInfo));
884 //------------------------------------------------------------------------------
886 void
887 UpdateCheck::cancel()
889 osl::ClearableMutexGuard aGuard(m_aMutex);
891 WorkerThread *pThread = m_pThread;
892 UpdateState eUIState = getUIState(m_aUpdateInfo);
894 aGuard.clear();
896 if( NULL != pThread )
897 pThread->cancel();
899 setUIState(eUIState);
902 //------------------------------------------------------------------------------
904 void
905 UpdateCheck::download()
907 osl::ClearableMutexGuard aGuard(m_aMutex);
908 UpdateInfo aInfo(m_aUpdateInfo);
909 State eState = m_eState;
910 aGuard.clear();
912 if( aInfo.Sources[0].IsDirect )
914 // Ignore second click of a double click
915 if( DOWNLOADING != eState )
917 shutdownThread(true);
919 osl::ClearableMutexGuard aGuard2(m_aMutex);
920 enableDownload(true);
921 aGuard2.clear();
922 setUIState(UPDATESTATE_DOWNLOADING);
925 else
927 showReleaseNote(aInfo.Sources[0].URL); // Display in browser
931 //------------------------------------------------------------------------------
933 void
934 UpdateCheck::install()
936 osl::MutexGuard aGuard(m_aMutex);
938 const uno::Reference< c3s::XSystemShellExecute > xShellExecute(
939 createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ),
940 uno::UNO_QUERY );
942 try {
943 // Construct install command ??
945 // Store release note for position 3 and 4
946 rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 3));
947 storeReleaseNote(1, aURL);
949 aURL = getReleaseNote(m_aUpdateInfo, 4);
950 storeReleaseNote(2, aURL);
952 if( xShellExecute.is() )
954 rtl::OUString aInstallImage(m_aImageName);
955 osl::FileBase::getSystemPathFromFileURL(aInstallImage, aInstallImage);
957 rtl::OUString aParameter;
958 sal_Int32 nFlags = c3s::SystemShellExecuteFlags::DEFAULTS;
959 #if ( defined LINUX || defined SOLARIS )
960 nFlags = 42;
961 aParameter = getBaseInstallation();
962 if( aParameter.getLength() > 0 )
963 osl::FileBase::getSystemPathFromFileURL(aParameter, aParameter);
965 aParameter += UNISTRING(" &");
966 #endif
968 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext );
969 rModel->clearLocalFileName();
971 xShellExecute->execute(aInstallImage, aParameter, nFlags);
972 ShutdownThread *pShutdownThread = new ShutdownThread( m_xContext );
973 (void) pShutdownThread;
975 } catch(uno::Exception&) {
976 m_aUpdateHandler->setErrorMessage( m_aUpdateHandler->getDefaultInstErrMsg() );
980 //------------------------------------------------------------------------------
982 void
983 UpdateCheck::pause()
985 osl::ClearableMutexGuard aGuard(m_aMutex);
987 if( NULL != m_pThread )
988 m_pThread->suspend();
990 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
991 aGuard.clear();
993 rModel->storeDownloadPaused(true);
994 setUIState(UPDATESTATE_DOWNLOAD_PAUSED);
997 //------------------------------------------------------------------------------
999 void
1000 UpdateCheck::resume()
1002 osl::ClearableMutexGuard aGuard(m_aMutex);
1004 if( NULL != m_pThread )
1005 m_pThread->resume();
1007 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
1008 aGuard.clear();
1010 rModel->storeDownloadPaused(false);
1011 setUIState(UPDATESTATE_DOWNLOADING);
1014 //------------------------------------------------------------------------------
1016 void
1017 UpdateCheck::closeAfterFailure()
1019 osl::ClearableMutexGuard aGuard(m_aMutex);
1021 if ( ( m_eState == DISABLED ) || ( m_eState == CHECK_SCHEDULED ) )
1023 const UpdateState eUIState = getUIState( m_aUpdateInfo );
1024 aGuard.clear();
1025 setUIState( eUIState, true );
1029 //------------------------------------------------------------------------------
1031 void
1032 UpdateCheck::shutdownThread(bool join)
1034 osl::ClearableMutexGuard aGuard(m_aMutex);
1036 // copy thread object pointer to stack
1037 osl::Thread *pThread = m_pThread;
1038 m_pThread = NULL;
1039 aGuard.clear();
1041 if( NULL != pThread )
1043 pThread->terminate();
1044 if( join )
1046 m_aCondition.set();
1047 pThread->join();
1048 m_aCondition.reset();
1053 //------------------------------------------------------------------------------
1055 void
1056 UpdateCheck::enableAutoCheck(bool enable)
1058 if( enable )
1059 m_pThread = new UpdateCheckThread(m_aCondition, m_xContext);
1061 m_eState = enable ? CHECK_SCHEDULED : DISABLED;
1064 //------------------------------------------------------------------------------
1066 void
1067 UpdateCheck::enableDownload(bool enable, bool paused)
1069 OSL_ASSERT(NULL == m_pThread);
1071 State eState = DISABLED;
1072 if( enable )
1074 m_pThread = new DownloadThread(m_aCondition, m_xContext, this, m_aUpdateInfo.Sources[0].URL );
1075 if( !paused )
1077 eState = DOWNLOADING;
1078 m_pThread->resume();
1080 else
1081 eState = DOWNLOAD_PAUSED;
1083 m_eState = eState;
1085 else {
1086 enableAutoCheck(UpdateCheckConfig::get(m_xContext)->isAutoCheckEnabled());
1091 //------------------------------------------------------------------------------
1093 bool
1094 UpdateCheck::downloadTargetExists(const rtl::OUString& rFileName)
1096 osl::ClearableMutexGuard aGuard(m_aMutex);
1098 rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
1099 UpdateState eUIState = UPDATESTATE_DOWNLOADING;
1101 bool cont = false;
1103 if( aUpdateHandler->isVisible() )
1105 cont = aUpdateHandler->showOverwriteWarning();
1106 if( cont )
1108 if( osl_File_E_None != osl_removeFile(rFileName.pData) )
1110 // FIXME: error message
1111 cont = false;
1114 else
1115 eUIState = getUIState(m_aUpdateInfo);
1117 else
1119 m_aImageName = getImageFromFileName(rFileName);
1120 eUIState = UPDATESTATE_DOWNLOAD_AVAIL;
1123 if( !cont )
1125 shutdownThread(false);
1126 enableDownload(false);
1128 aGuard.clear();
1129 setUIState(eUIState);
1132 return cont;
1135 //------------------------------------------------------------------------------
1136 bool UpdateCheck::checkDownloadDestination( const rtl::OUString& rFileName )
1138 osl::ClearableMutexGuard aGuard(m_aMutex);
1140 rtl::Reference< UpdateHandler > aUpdateHandler( getUpdateHandler() );
1142 bool bReload = false;
1144 if( aUpdateHandler->isVisible() )
1146 bReload = aUpdateHandler->showOverwriteWarning( rFileName );
1149 return bReload;
1152 //------------------------------------------------------------------------------
1154 void
1155 UpdateCheck::downloadStalled(const rtl::OUString& rErrorMessage)
1157 osl::ClearableMutexGuard aGuard(m_aMutex);
1158 rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
1159 aGuard.clear();
1161 aUpdateHandler->setErrorMessage(rErrorMessage);
1162 setUIState(UPDATESTATE_ERROR_DOWNLOADING);
1165 //------------------------------------------------------------------------------
1167 void
1168 UpdateCheck::downloadProgressAt(sal_Int8 nPercent)
1170 osl::ClearableMutexGuard aGuard(m_aMutex);
1171 rtl::Reference< UpdateHandler > aUpdateHandler(getUpdateHandler());
1172 aGuard.clear();
1174 aUpdateHandler->setProgress(nPercent);
1175 setUIState(UPDATESTATE_DOWNLOADING);
1178 //------------------------------------------------------------------------------
1180 void
1181 UpdateCheck::downloadStarted(const rtl::OUString& rLocalFileName, sal_Int64 nFileSize)
1183 if ( nFileSize > 0 )
1185 osl::MutexGuard aGuard(m_aMutex);
1187 rtl::Reference< UpdateCheckConfig > aModel(UpdateCheckConfig::get(m_xContext));
1188 aModel->storeLocalFileName(rLocalFileName, nFileSize);
1190 // Bring-up release note for position 1 ..
1191 const rtl::OUString aURL(getReleaseNote(m_aUpdateInfo, 1, aModel->isAutoDownloadEnabled()));
1192 if( aURL.getLength() > 0 )
1193 showReleaseNote(aURL);
1197 //------------------------------------------------------------------------------
1199 void
1200 UpdateCheck::downloadFinished(const rtl::OUString& rLocalFileName)
1202 osl::ClearableMutexGuard aGuard(m_aMutex);
1204 // no more retries
1205 m_pThread->terminate();
1207 m_aImageName = getImageFromFileName(rLocalFileName);
1208 UpdateInfo aUpdateInfo(m_aUpdateInfo);
1210 aGuard.clear();
1211 setUIState(UPDATESTATE_DOWNLOAD_AVAIL);
1213 // Bring-up release note for position 2 ..
1214 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get( m_xContext );
1215 const rtl::OUString aURL(getReleaseNote(aUpdateInfo, 2, rModel->isAutoDownloadEnabled()));
1216 if( aURL.getLength() > 0 )
1217 showReleaseNote(aURL);
1220 //------------------------------------------------------------------------------
1222 void
1223 UpdateCheck::cancelDownload()
1225 shutdownThread(true);
1227 osl::MutexGuard aGuard(m_aMutex);
1228 enableDownload(false);
1230 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext);
1232 rtl::OUString aLocalFile(rModel->getLocalFileName());
1233 rModel->clearLocalFileName();
1234 rModel->storeDownloadPaused(false);
1236 if( isObsoleteUpdateInfo(rModel->getUpdateEntryVersion()) )
1238 rModel->clearUpdateFound(); // This wasn't done during init yet ..
1239 m_aUpdateInfo = UpdateInfo();
1242 /*oslFileError rc =*/ osl_removeFile(aLocalFile.pData);
1243 // FIXME: error handling ..
1247 //------------------------------------------------------------------------------
1249 void
1250 UpdateCheck::showDialog(bool forceCheck)
1252 osl::ResettableMutexGuard aGuard(m_aMutex);
1254 bool update_found = m_aUpdateInfo.BuildId.getLength() > 0;
1255 bool bSetUIState = ! m_aUpdateHandler.is();
1257 UpdateState eDialogState = UPDATESTATES_COUNT;
1259 switch( m_eState )
1261 case DISABLED:
1262 case CHECK_SCHEDULED:
1263 if( forceCheck || ! update_found ) // Run check when forced or if we did not find an update yet
1265 eDialogState = UPDATESTATE_CHECKING;
1266 bSetUIState = true;
1268 else if(m_aUpdateInfo.Sources[0].IsDirect)
1269 eDialogState = UPDATESTATE_UPDATE_AVAIL;
1270 else
1271 eDialogState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
1272 break;
1274 case DOWNLOADING:
1275 eDialogState = UPDATESTATE_DOWNLOADING;
1276 break;
1278 case DOWNLOAD_PAUSED:
1279 eDialogState = UPDATESTATE_DOWNLOAD_PAUSED;
1280 break;
1282 case NOT_INITIALIZED:
1283 OSL_ASSERT( false );
1284 break;
1287 if( bSetUIState )
1289 aGuard.clear();
1290 setUIState(eDialogState, true); // suppress bubble as Dialog will be visible soon
1291 aGuard.reset();
1294 getUpdateHandler()->setVisible(true);
1296 // Run check in separate thread ..
1297 if( UPDATESTATE_CHECKING == eDialogState )
1299 if( DISABLED == m_eState )
1301 // destructs itself when done, not cancellable for now ..
1302 new ManualUpdateCheckThread(m_aCondition, m_xContext);
1305 m_aCondition.set();
1309 //------------------------------------------------------------------------------
1311 void
1312 UpdateCheck::setUpdateInfo(const UpdateInfo& aInfo)
1314 osl::ClearableMutexGuard aGuard(m_aMutex);
1316 bool bSuppressBubble = (sal_True == aInfo.BuildId.equals(m_aUpdateInfo.BuildId));
1317 m_aUpdateInfo = aInfo;
1319 OSL_ASSERT(DISABLED == m_eState || CHECK_SCHEDULED == m_eState);
1321 // Ignore leading non direct download if we get direct ones
1322 std::vector< DownloadSource >::iterator iter = m_aUpdateInfo.Sources.begin();
1323 while( iter != m_aUpdateInfo.Sources.end() )
1325 if( iter->IsDirect )
1326 break;
1328 ++iter;
1331 if( (iter != m_aUpdateInfo.Sources.begin()) &&
1332 (iter != m_aUpdateInfo.Sources.end()) &&
1333 iter->IsDirect )
1335 m_aUpdateInfo.Sources.erase(m_aUpdateInfo.Sources.begin(), --iter);
1338 rtl::Reference< UpdateCheckConfig > rModel = UpdateCheckConfig::get(m_xContext, *this);
1339 OSL_ASSERT( rModel.is() );
1341 // Decide whether to use alternate release note pos ..
1342 bool autoDownloadEnabled = rModel->isAutoDownloadEnabled();
1344 std::vector< ReleaseNote >::iterator iter2 = m_aUpdateInfo.ReleaseNotes.begin();
1345 while( iter2 != m_aUpdateInfo.ReleaseNotes.end() )
1347 if( ((1 == iter2->Pos) || (2 == iter2->Pos)) && autoDownloadEnabled && (iter2->URL2.getLength() > 0))
1349 iter2->URL = iter2->URL2;
1350 iter2->URL2 = rtl::OUString();
1351 iter2->Pos = iter2->Pos2;
1352 iter2->Pos2 = 0;
1355 ++iter2;
1358 // do not move below store/clear ..
1359 rModel->updateLastChecked();
1361 UpdateState eUIState;
1362 if( m_aUpdateInfo.Sources.size() > 0 )
1364 rModel->storeUpdateFound(aInfo, getBuildId());
1366 if( m_aUpdateInfo.Sources[0].IsDirect )
1368 eUIState = UPDATESTATE_UPDATE_AVAIL;
1370 if( rModel->isAutoDownloadEnabled() )
1372 shutdownThread(false);
1373 eUIState = UPDATESTATE_DOWNLOADING;
1374 enableDownload(true);
1377 else
1378 eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
1380 else
1382 eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
1383 rModel->clearUpdateFound();
1386 aGuard.clear();
1387 setUIState(eUIState, bSuppressBubble);
1390 //------------------------------------------------------------------------------
1392 void
1393 UpdateCheck::setCheckFailedState()
1395 setUIState(UPDATESTATE_ERROR_CHECKING);
1398 //------------------------------------------------------------------------------
1399 void UpdateCheck::handleMenuBarUI( rtl::Reference< UpdateHandler > rUpdateHandler,
1400 UpdateState& eState,
1401 bool suppressBubble )
1403 uno::Reference<beans::XPropertySet> xMenuBarUI( m_xMenuBarUI );
1405 if ( ( UPDATESTATE_NO_UPDATE_AVAIL == eState ) && m_bHasExtensionUpdate )
1406 eState = UPDATESTATE_EXT_UPD_AVAIL;
1408 if ( UPDATESTATE_EXT_UPD_AVAIL == eState )
1409 m_bShowExtUpdDlg = true;
1410 else
1411 m_bShowExtUpdDlg = false;
1413 if( xMenuBarUI.is() )
1415 if( UPDATESTATE_NO_UPDATE_AVAIL == eState )
1417 xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_False) );
1419 else
1421 xMenuBarUI->setPropertyValue( PROPERTY_TITLE, uno::makeAny(rUpdateHandler->getBubbleTitle(eState)) );
1422 xMenuBarUI->setPropertyValue( PROPERTY_TEXT, uno::makeAny(rUpdateHandler->getBubbleText(eState)) );
1424 if( ! suppressBubble && ( ! rUpdateHandler->isVisible() || rUpdateHandler->isMinimized() ) )
1425 xMenuBarUI->setPropertyValue( PROPERTY_SHOW_BUBBLE, uno::makeAny( sal_True ) );
1427 if( UPDATESTATE_CHECKING != eState )
1428 xMenuBarUI->setPropertyValue( PROPERTY_SHOW_MENUICON, uno::makeAny(sal_True) );
1433 //------------------------------------------------------------------------------
1434 void UpdateCheck::setUIState(UpdateState eState, bool suppressBubble)
1436 osl::ClearableMutexGuard aGuard(m_aMutex);
1438 if( ! m_xMenuBarUI.is() &&
1439 (DISABLED != m_eState) &&
1440 ( m_bHasExtensionUpdate || (UPDATESTATE_NO_UPDATE_AVAIL != eState)) &&
1441 (UPDATESTATE_CHECKING != eState) &&
1442 (UPDATESTATE_ERROR_CHECKING != eState)
1445 m_xMenuBarUI = createMenuBarUI(m_xContext, new MenuBarButtonJob(this));
1448 // Show bubble only when the status has changed
1449 if ( eState == m_eUpdateState )
1450 suppressBubble = true;
1451 else
1452 m_eUpdateState = eState;
1454 rtl::Reference<UpdateHandler> aUpdateHandler(getUpdateHandler());
1455 OSL_ASSERT( aUpdateHandler.is() );
1457 UpdateInfo aUpdateInfo(m_aUpdateInfo);
1458 rtl::OUString aImageName(m_aImageName);
1460 aGuard.clear();
1462 handleMenuBarUI( aUpdateHandler, eState, suppressBubble );
1464 if( (UPDATESTATE_UPDATE_AVAIL == eState)
1465 || (UPDATESTATE_DOWNLOAD_PAUSED == eState)
1466 || (UPDATESTATE_DOWNLOADING == eState) )
1468 uno::Reference< uno::XComponentContext > xContext(m_xContext);
1470 rtl::OUString aDownloadDestination =
1471 UpdateCheckConfig::get(xContext, this)->getDownloadDestination();
1473 osl_getSystemPathFromFileURL(aDownloadDestination.pData, &aDownloadDestination.pData);
1475 aUpdateHandler->setDownloadPath(aDownloadDestination);
1477 else if( UPDATESTATE_DOWNLOAD_AVAIL == eState )
1479 aUpdateHandler->setDownloadFile(aImageName);
1482 aUpdateHandler->setDescription(aUpdateInfo.Description);
1483 aUpdateHandler->setNextVersion(aUpdateInfo.Version);
1484 aUpdateHandler->setState(eState);
1487 //------------------------------------------------------------------------------
1489 UpdateState
1490 UpdateCheck::getUIState(const UpdateInfo& rInfo)
1492 UpdateState eUIState = UPDATESTATE_NO_UPDATE_AVAIL;
1494 if( rInfo.BuildId.getLength() > 0 )
1496 if( rInfo.Sources[0].IsDirect )
1497 eUIState = UPDATESTATE_UPDATE_AVAIL;
1498 else
1499 eUIState = UPDATESTATE_UPDATE_NO_DOWNLOAD;
1502 return eUIState;
1505 //------------------------------------------------------------------------------
1507 void
1508 UpdateCheck::showReleaseNote(const rtl::OUString& rURL) const
1510 const uno::Reference< c3s::XSystemShellExecute > xShellExecute(
1511 createService( UNISTRING( "com.sun.star.system.SystemShellExecute" ), m_xContext ),
1512 uno::UNO_QUERY );
1514 try {
1516 if( xShellExecute.is() )
1517 xShellExecute->execute(rURL, rtl::OUString(), c3s::SystemShellExecuteFlags::DEFAULTS);
1518 } catch(c3s::SystemShellExecuteException&) {
1522 //------------------------------------------------------------------------------
1524 bool
1525 UpdateCheck::storeReleaseNote(sal_Int8 nNum, const rtl::OUString &rURL)
1527 osl::FileBase::RC rc;
1528 rtl::OUString aTargetDir( UpdateCheckConfig::getAllUsersDirectory() + UNISTRING( "/sun" ) );
1530 rc = osl::Directory::createPath( aTargetDir );
1532 rtl::OUString aFileName = UNISTRING("releasenote") +
1533 rtl::OUString::valueOf( (sal_Int32) nNum ) +
1534 UNISTRING(".url");
1536 rtl::OUString aFilePath;
1537 rc = osl::FileBase::getAbsoluteFileURL( aTargetDir, aFileName, aFilePath );
1538 if ( rc != osl::FileBase::E_None ) return false;
1540 rc = osl::File::remove( aFilePath );
1542 // don't store empty release notes, but delete old ones
1543 if ( rURL.getLength() == 0 )
1544 return true;
1546 osl::File aFile( aFilePath );
1547 rc = aFile.open( OpenFlag_Write | OpenFlag_Create );
1549 if ( rc != osl::FileBase::E_None ) return false;
1551 rtl::OString aLineBuf("[InternetShortcut]\r\n");
1552 sal_uInt64 nWritten = 0;
1554 rtl::OUString aURL( rURL );
1555 #ifdef WNT
1556 rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten );
1557 if ( rc != osl::FileBase::E_None ) return false;
1558 aURL = UNISTRING("URL=") + rURL;
1559 #endif
1560 aLineBuf = rtl::OUStringToOString( aURL, RTL_TEXTENCODING_UTF8 );
1561 rc = aFile.write( aLineBuf.getStr(), aLineBuf.getLength(), nWritten );
1562 if ( rc != osl::FileBase::E_None ) return false;
1564 aFile.close();
1565 return true;
1568 //------------------------------------------------------------------------------
1569 void UpdateCheck::showExtensionDialog()
1571 rtl::OUString sServiceName = UNISTRING("com.sun.star.deployment.ui.PackageManagerDialog");
1572 rtl::OUString sArguments = UNISTRING("SHOW_UPDATE_DIALOG");
1573 uno::Reference< uno::XInterface > xService;
1575 if( ! m_xContext.is() )
1576 throw uno::RuntimeException(
1577 UNISTRING( "UpdateCheck::showExtensionDialog(): empty component context" ), uno::Reference< uno::XInterface > () );
1579 uno::Reference< lang::XMultiComponentFactory > xServiceManager( m_xContext->getServiceManager() );
1580 if( !xServiceManager.is() )
1581 throw uno::RuntimeException(
1582 UNISTRING( "UpdateCheck::showExtensionDialog(): unable to obtain service manager from component context" ), uno::Reference< uno::XInterface > () );
1584 xService = xServiceManager->createInstanceWithContext( sServiceName, m_xContext );
1585 uno::Reference< task::XJobExecutor > xExecuteable( xService, uno::UNO_QUERY );
1586 if ( xExecuteable.is() )
1587 xExecuteable->trigger( sArguments );
1590 //------------------------------------------------------------------------------
1592 rtl::Reference<UpdateHandler>
1593 UpdateCheck::getUpdateHandler()
1595 osl::MutexGuard aGuard(m_aMutex);
1597 if( ! m_aUpdateHandler.is() )
1598 m_aUpdateHandler = new UpdateHandler(m_xContext, this);
1600 return m_aUpdateHandler;
1603 //------------------------------------------------------------------------------
1605 uno::Reference< task::XInteractionHandler >
1606 UpdateCheck::getInteractionHandler() const
1608 osl::MutexGuard aGuard(m_aMutex);
1610 uno::Reference< task::XInteractionHandler > xHandler;
1612 if( m_aUpdateHandler.is() && m_aUpdateHandler->isVisible() )
1613 xHandler = m_aUpdateHandler.get();
1615 return xHandler;
1618 //------------------------------------------------------------------------------
1620 uno::Reference< uno::XInterface >
1621 UpdateCheck::createService(const rtl::OUString& rServiceName,
1622 const uno::Reference<uno::XComponentContext>& xContext)
1624 if( !xContext.is() )
1625 throw uno::RuntimeException(
1626 UNISTRING( "UpdateCheckConfig: empty component context" ),
1627 uno::Reference< uno::XInterface >() );
1629 const uno::Reference< lang::XMultiComponentFactory > xServiceManager(xContext->getServiceManager());
1631 if( !xServiceManager.is() )
1632 throw uno::RuntimeException(
1633 UNISTRING( "UpdateCheckConfig: unable to obtain service manager from component context" ),
1634 uno::Reference< uno::XInterface >() );
1636 return xServiceManager->createInstanceWithContext(rServiceName, xContext);
1639 //------------------------------------------------------------------------------
1641 bool
1642 UpdateCheck::isDialogShowing() const
1644 osl::MutexGuard aGuard(m_aMutex);
1645 return sal_True == m_aUpdateHandler.is() && m_aUpdateHandler->isVisible();
1648 //------------------------------------------------------------------------------
1650 void
1651 UpdateCheck::autoCheckStatusChanged(bool enabled)
1653 osl::ClearableMutexGuard aGuard(m_aMutex);
1655 if( (CHECK_SCHEDULED == m_eState) && !enabled )
1656 shutdownThread(false);
1658 if( (DISABLED == m_eState) || (CHECK_SCHEDULED == m_eState) )
1660 enableAutoCheck(enabled);
1661 UpdateState eState = getUIState(m_aUpdateInfo);
1662 aGuard.clear();
1663 setUIState(eState);
1667 //------------------------------------------------------------------------------
1669 void
1670 UpdateCheck::autoCheckIntervalChanged()
1672 // just wake-up
1673 m_aCondition.set();
1676 //------------------------------------------------------------------------------
1678 oslInterlockedCount SAL_CALL
1679 UpdateCheck::acquire() SAL_THROW(())
1681 return ReferenceObject::acquire();
1684 //------------------------------------------------------------------------------
1686 oslInterlockedCount SAL_CALL
1687 UpdateCheck::release() SAL_THROW(())
1689 return ReferenceObject::release();