22#include <com/sun/star/beans/NamedValue.hpp>
24#include <com/sun/star/deployment/DependencyException.hpp>
25#include <com/sun/star/deployment/LicenseException.hpp>
26#include <com/sun/star/deployment/VersionException.hpp>
27#include <com/sun/star/deployment/InstallException.hpp>
28#include <com/sun/star/deployment/PlatformException.hpp>
30#include <com/sun/star/deployment/ui/LicenseDialog.hpp>
31#include <com/sun/star/deployment/DeploymentException.hpp>
32#include <com/sun/star/deployment/XPackage.hpp>
34#include <com/sun/star/task/InteractionHandler.hpp>
35#include <com/sun/star/task/XAbortChannel.hpp>
36#include <com/sun/star/task/XInteractionAbort.hpp>
37#include <com/sun/star/task/XInteractionApprove.hpp>
39#include <com/sun/star/ucb/CommandAbortedException.hpp>
40#include <com/sun/star/ucb/CommandFailedException.hpp>
41#include <com/sun/star/ucb/XCommandEnvironment.hpp>
43#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
45#include <com/sun/star/uno/Reference.hxx>
46#include <com/sun/star/uno/Sequence.hxx>
47#include <com/sun/star/uno/TypeClass.hpp>
49#include <osl/diagnose.h>
51#include <rtl/ustring.hxx>
75#include <condition_variable>
89OUString getVersion( OUString
const & sVersion )
91 return ( sVersion.isEmpty() ) ? OUString(
"0" ) : sVersion;
96 return getVersion( rPackage->getVersion());
106 :
public ::cppu::WeakImplHelper< ucb::XCommandEnvironment,
107 task::XInteractionHandler,
108 ucb::XProgressHandler >
118 void updateProgress();
132 DialogHelper* pDialogHelper,
143 void startProgress();
145 void progressSection(
const OUString &rText,
147 void setWarnUser(
bool bNewVal ) {
m_bWarnUser = bNewVal; }
159 virtual void SAL_CALL pop()
override;
165 enum E_CMD_TYPE {
ADD, ENABLE,
DISABLE, REMOVE, CHECK_FOR_UPDATES, ACCEPT_LICENSE };
174 ExtensionCmd(
const E_CMD_TYPE eCommand,
175 OUString aExtensionURL,
176 OUString aRepository,
177 const bool bWarnUser )
182 ExtensionCmd(
const E_CMD_TYPE eCommand,
187 ExtensionCmd(
const E_CMD_TYPE eCommand,
207 const OUString &rRepository,
208 const bool bWarnUser );
211 const bool bEnable );
220 virtual void execute()
override;
225 const OUString &rPackageURL,
226 const OUString &rRepository,
227 const bool bWarnUser );
260void ProgressCmdEnv::startProgress()
269void ProgressCmdEnv::stopProgress()
276void ProgressCmdEnv::progressSection(
const OUString &rText,
288void ProgressCmdEnv::updateProgress()
313 uno::Any request( xRequest->getRequest() );
314 OSL_ASSERT( request.getValueTypeClass() == uno::TypeClass_EXCEPTION );
316 + ::comphelper::anyToString(request) +
"\n");
318 lang::WrappedTargetException wtExc;
319 deployment::DependencyException depExc;
320 deployment::LicenseException licExc;
321 deployment::VersionException verExc;
322 deployment::InstallException instExc;
323 deployment::PlatformException platExc;
326 bool approve =
false;
329 if (request >>= wtExc) {
333 deployment::DeploymentException dpExc;
334 if (wtExc.TargetException >>= dpExc)
337 ucb::CommandFailedException cfExc;
338 if (wtExc.TargetException >>= cfExc)
339 cause = cfExc.Reason;
341 cause = wtExc.TargetException;
348 OSL_ASSERT( xPackage.is() );
352 OSL_ASSERT( xPackageType.is() );
353 if (xPackageType.is())
355 approve = ( xPackage->isBundle() &&
356 xPackageType->getMediaType().match(
357 "application/vnd.sun.star.legacy-package-bundle" ));
362 else if (request >>= depExc)
364 std::vector< OUString > deps;
365 deps.reserve(depExc.UnsatisfiedDependencies.getLength());
366 for (
auto const & i : std::as_const(depExc.UnsatisfiedDependencies))
374 DependencyDialog aDlg(activeDialog(), deps);
375 short n = aDlg.run();
384 else if (request >>= licExc)
394 licExc.ExtensionName, licExc.Text ) );
395 sal_Int16 res = xDialog->execute();
398 if ( res == ui::dialogs::ExecutableDialogResults::CANCEL )
400 else if ( res == ui::dialogs::ExecutableDialogResults::OK )
407 else if (request >>= verExc)
411 verExc.NewVersion, verExc.Deployed->getVersion() ))
414 id = RID_STR_WARNING_VERSION_LESS;
417 id = RID_STR_WARNING_VERSION_EQUAL;
420 id = RID_STR_WARNING_VERSION_GREATER;
423 OSL_ASSERT( verExc.Deployed.is() );
424 bool bEqualNames = verExc.NewDisplayName ==
425 verExc.Deployed->getDisplayName();
433 VclMessageType::Warning, VclButtonsType::OkCancel,
DpResId(
id)));
437 s = xBox->get_primary_text();
439 else if (
id != RID_STR_WARNING_VERSION_EQUAL)
444 s =
DpResId(RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES);
446 else if (
id != RID_STR_WARNING_VERSION_LESS)
448 s =
DpResId(RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES);
450 else if (
id != RID_STR_WARNING_VERSION_GREATER)
452 s =
DpResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES);
454 s = s.replaceAll(
"$NAME", verExc.NewDisplayName);
455 s = s.replaceAll(
"$OLDNAME", verExc.Deployed->getDisplayName());
456 s = s.replaceAll(
"$NEW", getVersion(verExc.NewVersion));
457 s = s.replaceAll(
"$DEPLOYED", getVersion(verExc.Deployed));
458 xBox->set_primary_text(s);
459 approve = xBox->run() ==
RET_OK;
465 else if (request >>= instExc)
484 else if (request >>= platExc)
487 OUString sMsg(
DpResId(RID_STR_UNSUPPORTED_PLATFORM));
488 sMsg = sMsg.replaceAll(
"%Name", platExc.package->getDisplayName());
492 VclMessageType::Warning, VclButtonsType::Ok, sMsg));
499 if (!approve && !abort)
512 xRequest->getContinuations() );
514 sal_Int32 len = conts.getLength();
515 for ( sal_Int32 pos = 0;
pos < len; ++
pos )
519 if (xInteractionApprove.is()) {
520 xInteractionApprove->select();
527 if (xInteractionAbort.is()) {
528 xInteractionAbort->select();
540void ProgressCmdEnv::push(
uno::Any const & rStatus )
546void ProgressCmdEnv::update_(
uno::Any const & rStatus )
549 if ( rStatus.
hasValue() && !( rStatus >>= text) )
551 if (
auto e = o3tl::tryAccess<uno::Exception>(rStatus) )
553 if (
text.isEmpty() )
554 text = ::comphelper::anyToString( rStatus );
560 VclMessageType::Warning, VclButtonsType::Ok, text));
576void ProgressCmdEnv::pop()
589 m_sEnablingPackages(
DpResId( RID_STR_ENABLING_PACKAGES ) ),
590 m_sDisablingPackages(
DpResId( RID_STR_DISABLING_PACKAGES ) ),
591 m_sAddingPackages(
DpResId( RID_STR_ADDING_PACKAGES ) ),
592 m_sRemovingPackages(
DpResId( RID_STR_REMOVING_PACKAGES ) ),
593 m_sDefaultCmd(
DpResId( RID_STR_ADD_PACKAGES ) ),
594 m_sAcceptLicense(
DpResId( RID_STR_ACCEPT_LICENSE ) ),
599 OSL_ASSERT( pDialogHelper );
604 const OUString &rRepository,
605 const bool bWarnUser )
607 if ( !rExtensionURL.isEmpty() )
609 TExtensionCmd pEntry = std::make_shared<ExtensionCmd>( ExtensionCmd::ADD, rExtensionURL, rRepository, bWarnUser );
619 TExtensionCmd pEntry = std::make_shared<ExtensionCmd>( ExtensionCmd::REMOVE, rPackage );
629 TExtensionCmd pEntry = std::make_shared<ExtensionCmd>( ExtensionCmd::ACCEPT_LICENSE, rPackage );
640 TExtensionCmd pEntry = std::make_shared<ExtensionCmd>( bEnable ? ExtensionCmd::ENABLE :
641 ExtensionCmd::DISABLE,
651 TExtensionCmd pEntry = std::make_shared<ExtensionCmd>( ExtensionCmd::CHECK_FOR_UPDATES, std::move(vExtensionList) );
659 std::scoped_lock aGuard(
m_mutex );
662 m_wakeup.notify_all();
668 std::scoped_lock aGuard(
m_mutex );
681 int nNbCallCoInitializeExForReinit = 0;
682 o3tl::safeCoInitializeEx(COINIT_APARTMENTTHREADED, nNbCallCoInitializeExForReinit);
689 std::unique_lock aGuard(
m_mutex );
690 while (m_eInput ==
NONE) {
691 m_wakeup.wait(aGuard);
695 nSize = m_queue.size();
700 if ( eInput ==
STOP )
715 bool bStartProgress =
true;
717 while ( --nSize >= 0 )
720 std::scoped_lock aGuard(
m_mutex );
728 std::scoped_lock queueGuard(
m_mutex );
729 pEntry = m_queue.front();
733 if ( bStartProgress && ( pEntry->m_eCmdType != ExtensionCmd::CHECK_FOR_UPDATES ) )
735 currentCmdEnv->startProgress();
736 bStartProgress =
false;
739 switch ( pEntry->m_eCmdType ) {
740 case ExtensionCmd::ADD :
741 _addExtension( currentCmdEnv, pEntry->m_sExtensionURL, pEntry->m_sRepository, pEntry->m_bWarnUser );
743 case ExtensionCmd::REMOVE :
744 _removeExtension( currentCmdEnv, pEntry->m_xPackage );
746 case ExtensionCmd::ENABLE :
747 _enableExtension( currentCmdEnv, pEntry->m_xPackage );
749 case ExtensionCmd::DISABLE :
750 _disableExtension( currentCmdEnv, pEntry->m_xPackage );
752 case ExtensionCmd::CHECK_FOR_UPDATES :
753 _checkForUpdates( std::vector(pEntry->m_vExtensionList) );
755 case ExtensionCmd::ACCEPT_LICENSE :
756 _acceptLicense( currentCmdEnv, pEntry->m_xPackage );
760 catch (
const ucb::CommandAbortedException & )
766 std::scoped_lock queueGuard2(
m_mutex);
767 while ( --nSize >= 0 )
772 catch (
const ucb::CommandFailedException & )
781 catch (
const uno::Exception & )
785 uno::Any exc( ::cppu::getCaughtException() );
787 deployment::DeploymentException dpExc;
790 if (
auto e = o3tl::tryAccess<uno::Exception>(dpExc.Cause))
797 msg = ::comphelper::anyToString(exc);
804 VclMessageType::Warning, VclButtonsType::Ok, msg));
813 std::scoped_lock aGuard(
m_mutex );
820 std::scoped_lock aGuard(
m_mutex );
824 if ( !bStartProgress )
825 currentCmdEnv->stopProgress();
829 o3tl::safeCoUninitializeReinit(COINIT_MULTITHREADED, nNbCallCoInitializeExForReinit);
835 const OUString &rPackageURL,
836 const OUString &rRepository,
837 const bool bWarnUser )
846 catch (
const uno::Exception & )
852 if ( ! (anyTitle >>=
sName) )
854 OSL_FAIL(
"Could not get file name for extension.");
858 rCmdEnv->setWarnUser( bWarnUser );
862 m_sAddingPackages.replaceAll(
"%EXTENSION_NAME",
sName));
863 rCmdEnv->progressSection( sTitle, xAbortChannel );
868 rRepository, xAbortChannel, rCmdEnv );
870 catch (
const ucb::CommandFailedException & )
875 catch (
const ucb::CommandAbortedException & )
880 rCmdEnv->setWarnUser(
false );
890 m_sRemovingPackages.replaceAll(
"%EXTENSION_NAME",
891 xPackage->getDisplayName()));
892 rCmdEnv->progressSection( sTitle, xAbortChannel );
897 xExtMgr->removeExtension(
id, xPackage->getName(), xPackage->getRepositoryName(), xAbortChannel, rCmdEnv );
899 catch (
const deployment::DeploymentException & )
901 catch (
const ucb::CommandFailedException & )
903 catch (
const ucb::CommandAbortedException & )
920 std::vector< UpdateData > vData;
925 bool bOk = aUpdateDialog.
run() ==
RET_OK;
929 if (bOk && !vData.empty())
933 std::vector< UpdateData > dataDownload;
935 for (
auto const& data : vData)
937 if ( data.sWebsiteURL.isEmpty() )
938 dataDownload.push_back(data);
941 short nDialogResult =
RET_OK;
942 if ( !dataDownload.empty() )
947 nDialogResult = aDlg.
run();
956 if (
RET_OK == nDialogResult )
958 for (
auto const& data : vData)
973 if ( !xPackage.is() )
979 m_sEnablingPackages.replaceAll(
"%EXTENSION_NAME",
980 xPackage->getDisplayName()));
981 rCmdEnv->progressSection( sTitle, xAbortChannel );
985 xExtMgr->enableExtension( xPackage, xAbortChannel, rCmdEnv );
989 catch ( const ::ucb::CommandAbortedException & )
997 if ( !xPackage.is() )
1003 m_sDisablingPackages.replaceAll(
"%EXTENSION_NAME",
1004 xPackage->getDisplayName()));
1005 rCmdEnv->progressSection( sTitle, xAbortChannel );
1009 xExtMgr->disableExtension( xPackage, xAbortChannel, rCmdEnv );
1013 catch ( const ::ucb::CommandAbortedException & )
1021 if ( !xPackage.is() )
1027 m_sAcceptLicense.replaceAll(
"%EXTENSION_NAME",
1028 xPackage->getDisplayName()));
1029 rCmdEnv->progressSection( sTitle, xAbortChannel );
1033 xExtMgr->checkPrerequisitesAndEnable( xPackage, xAbortChannel, rCmdEnv );
1037 catch ( const ::ucb::CommandAbortedException & )
1043 std::scoped_lock aGuard(
m_mutex );
1049 m_queue.push( rExtCmd );
1051 m_wakeup.notify_all();
1069 const OUString & repository,
1070 const bool bWarnUser )
1072 m_thread->addExtension( extensionURL, repository, bWarnUser );
1077 m_thread->removeExtension( rPackage );
1081 const bool bEnable )
1083 m_thread->enableExtension( rPackage, bEnable );
1088 m_thread->checkForUpdates( std::move(vExtensionList) );
1093 m_thread->acceptLicense( rPackage );
1110 xCmdEnv->handle( xRequest );
static bool IsDialogCancelEnabled()
static weld::MessageDialog * CreateMessageDialog(weld::Widget *pParent, VclMessageType eMessageType, VclButtonsType eButtonType, const OUString &rPrimaryMessage, const ILibreOfficeKitNotifier *pNotifier=nullptr)
virtual void updateProgress(const OUString &rText, const css::uno::Reference< css::task::XAbortChannel > &xAbortChannel)=0
virtual void showProgress(bool bStart)=0
bool installExtensionWarn(std::u16string_view rExtensionURL)
void _removeExtension(::rtl::Reference< ProgressCmdEnv > const &rCmdEnv, const uno::Reference< deployment::XPackage > &xPackage)
void removeExtension(const uno::Reference< deployment::XPackage > &rPackage)
const OUString m_sDisablingPackages
const OUString m_sAcceptLicense
Thread(DialogHelper *pDialogHelper, TheExtensionManager *pManager, uno::Reference< uno::XComponentContext > xContext)
void _addExtension(::rtl::Reference< ProgressCmdEnv > const &rCmdEnv, const OUString &rPackageURL, const OUString &rRepository, const bool bWarnUser)
DialogHelper * m_pDialogHelper
const OUString m_sEnablingPackages
const OUString m_sRemovingPackages
void _enableExtension(::rtl::Reference< ProgressCmdEnv > const &rCmdEnv, const uno::Reference< deployment::XPackage > &xPackage)
const OUString m_sAddingPackages
void enableExtension(const uno::Reference< deployment::XPackage > &rPackage, const bool bEnable)
void _acceptLicense(::rtl::Reference< ProgressCmdEnv > const &rCmdEnv, const uno::Reference< deployment::XPackage > &xPackage)
void acceptLicense(const uno::Reference< deployment::XPackage > &rPackage)
void _insert(const TExtensionCmd &rExtCmd)
void _checkForUpdates(std::vector< uno::Reference< deployment::XPackage > > &&vExtensionList)
uno::Reference< uno::XComponentContext > m_xContext
void _disableExtension(::rtl::Reference< ProgressCmdEnv > const &rCmdEnv, const uno::Reference< deployment::XPackage > &xPackage)
void checkForUpdates(std::vector< uno::Reference< deployment::XPackage > > &&vExtensionList)
const OUString m_sDefaultCmd
std::condition_variable m_wakeup
TheExtensionManager * m_pManager
virtual ~Thread() override
virtual void execute() override
void addExtension(const OUString &rExtensionURL, const OUString &rRepository, const bool bWarnUser)
std::queue< TExtensionCmd > m_queue
static void syncRepositories(const css::uno::Reference< css::uno::XComponentContext > &xContext)
void enableExtension(const css::uno::Reference< css::deployment::XPackage > &rPackage, const bool bEnable)
void acceptLicense(const css::uno::Reference< css::deployment::XPackage > &rPackage)
void addExtension(const OUString &rExtensionURL, const OUString &rRepository, const bool bWarnUser)
void checkForUpdates(std::vector< css::uno::Reference< css::deployment::XPackage > > &&vList)
ExtensionCmdQueue(DialogHelper *pDialogHelper, TheExtensionManager *pManager, const css::uno::Reference< css::uno::XComponentContext > &rContext)
Create an instance.
rtl::Reference< Thread > m_thread
void removeExtension(const css::uno::Reference< css::deployment::XPackage > &rPackage)
The modal “Check for Updates” dialog.
void notifyMenubar(bool bPrepareOnly, bool bRecheckOnly)
static void createNotifyJob(bool bPrepareOnly, css::uno::Sequence< css::uno::Sequence< OUString > > const &rItemList)
virtual short run() override
The modal “Download and Installation” dialog.
virtual short run() override
css::uno::Any getPropertyValue(const OUString &rPropertyName)
virtual css::uno::Reference< css::awt::XWindow > GetXWindow()=0
uno::Reference< task::XInteractionHandler2 > m_xHandler
DialogHelper * m_pDialogHelper
uno::Reference< uno::XComponentContext > m_xContext
sal_Int32 m_nCurrentProgress
uno::Reference< deployment::XPackage > m_xPackage
std::vector< uno::Reference< deployment::XPackage > > m_vExtensionList
OUString DpResId(TranslateId aId)
static uno::Reference< css::uno::XComponentContext > xContext
void handleInteractionRequest(const uno::Reference< uno::XComponentContext > &xContext, const uno::Reference< task::XInteractionRequest > &xRequest)
std::shared_ptr< ExtensionCmd > TExtensionCmd
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getErrorText(css::uno::Reference< css::xml::dom::XElement > const &dependency)
Obtain the (human-readable) error message of a failed dependency.
void syncRepositories(bool force, Reference< ucb::XCommandEnvironment > const &xCmdEnv)
void TRACE(OUString const &sText)
print the text to the console in a debug build.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(std::u16string_view version1, std::u16string_view version2)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
css::uno::Reference< css::deployment::XPackageRegistry > create(css::uno::Reference< css::deployment::XPackageRegistry > const &xRootRegistry, OUString const &context, OUString const &cachePath, css::uno::Reference< css::uno::XComponentContext > const &xComponentContext)