1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <sal/config.h>
24 #include <com/sun/star/beans/NamedValue.hpp>
26 #include <com/sun/star/deployment/DependencyException.hpp>
27 #include <com/sun/star/deployment/LicenseException.hpp>
28 #include <com/sun/star/deployment/VersionException.hpp>
29 #include <com/sun/star/deployment/InstallException.hpp>
30 #include <com/sun/star/deployment/PlatformException.hpp>
32 #include <com/sun/star/deployment/ui/LicenseDialog.hpp>
33 #include <com/sun/star/deployment/DeploymentException.hpp>
34 #include <com/sun/star/deployment/UpdateInformationProvider.hpp>
35 #include <com/sun/star/deployment/XPackage.hpp>
37 #include <com/sun/star/task/InteractionHandler.hpp>
38 #include <com/sun/star/task/XAbortChannel.hpp>
39 #include <com/sun/star/task/XInteractionAbort.hpp>
40 #include <com/sun/star/task/XInteractionApprove.hpp>
42 #include <com/sun/star/ucb/CommandAbortedException.hpp>
43 #include <com/sun/star/ucb/CommandFailedException.hpp>
44 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
46 #include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp>
48 #include <com/sun/star/uno/Reference.hxx>
49 #include <com/sun/star/uno/RuntimeException.hpp>
50 #include <com/sun/star/uno/Sequence.hxx>
51 #include <com/sun/star/uno/XInterface.hpp>
52 #include <com/sun/star/uno/TypeClass.hpp>
53 #include <o3tl/any.hxx>
54 #include <osl/diagnose.h>
55 #include <osl/mutex.hxx>
56 #include <rtl/ref.hxx>
57 #include <rtl/ustring.h>
58 #include <rtl/ustring.hxx>
59 #include <sal/types.h>
60 #include <salhelper/thread.hxx>
61 #include <ucbhelper/content.hxx>
62 #include <cppuhelper/exc_hlp.hxx>
63 #include <cppuhelper/implbase.hxx>
64 #include <comphelper/anytostring.hxx>
65 #include <vcl/svapp.hxx>
66 #include <vcl/weld.hxx>
67 #include <toolkit/helper/vclunohelper.hxx>
70 #include "dp_gui_extensioncmdqueue.hxx"
71 #include "dp_gui_dependencydialog.hxx"
72 #include "dp_gui_dialog2.hxx"
73 #include <dp_shared.hxx>
74 #include <strings.hrc>
75 #include "dp_gui_theextmgr.hxx"
76 #include "dp_gui_updatedialog.hxx"
77 #include "dp_gui_updateinstalldialog.hxx"
78 #include <dp_dependencies.hxx>
79 #include <dp_identifier.hxx>
80 #include <dp_version.hxx>
86 #if !defined WIN32_LEAN_AND_MEAN
87 # define WIN32_LEAN_AND_MEAN
94 using namespace ::com::sun::star
;
98 OUString
getVersion( OUString
const & sVersion
)
100 return ( sVersion
.isEmpty() ) ? OUString( "0" ) : sVersion
;
103 OUString
getVersion( const uno::Reference
< deployment::XPackage
> &rPackage
)
105 return getVersion( rPackage
->getVersion());
114 : public ::cppu::WeakImplHelper
< ucb::XCommandEnvironment
,
115 task::XInteractionHandler
,
116 ucb::XProgressHandler
>
118 uno::Reference
< task::XInteractionHandler2
> m_xHandler
;
119 uno::Reference
< uno::XComponentContext
> m_xContext
;
121 DialogHelper
* m_pDialogHelper
;
124 sal_Int32 m_nCurrentProgress
;
126 void updateProgress();
128 /// @throws uno::RuntimeException
129 void update_( uno::Any
const & Status
);
132 /** When param bAskWhenInstalling = true, then the user is asked if he
133 agrees to install this extension. In case this extension is already installed
134 then the user is also notified and asked if he wants to replace that existing
135 extension. In first case an interaction request with an InstallException
136 will be handled and in the second case a VersionException will be handled.
139 ProgressCmdEnv( const uno::Reference
< uno::XComponentContext
>& rContext
,
140 DialogHelper
* pDialogHelper
,
141 const OUString
& rTitle
)
142 : m_xContext( rContext
)
143 , m_pDialogHelper( pDialogHelper
)
145 , m_bWarnUser( false )
146 , m_nCurrentProgress(0)
149 weld::Window
* activeDialog() { return m_pDialogHelper
? m_pDialogHelper
->getFrameWeld() : nullptr; }
151 void startProgress();
153 void progressSection( const OUString
&rText
,
154 const uno::Reference
< task::XAbortChannel
> &xAbortChannel
);
155 void setWarnUser( bool bNewVal
) { m_bWarnUser
= bNewVal
; }
157 // XCommandEnvironment
158 virtual uno::Reference
< task::XInteractionHandler
> SAL_CALL
getInteractionHandler() override
;
159 virtual uno::Reference
< ucb::XProgressHandler
> SAL_CALL
getProgressHandler() override
;
161 // XInteractionHandler
162 virtual void SAL_CALL
handle( uno::Reference
< task::XInteractionRequest
> const & xRequest
) override
;
165 virtual void SAL_CALL
push( uno::Any
const & Status
) override
;
166 virtual void SAL_CALL
update( uno::Any
const & Status
) override
;
167 virtual void SAL_CALL
pop() override
;
173 enum E_CMD_TYPE
{ ADD
, ENABLE
, DISABLE
, REMOVE
, CHECK_FOR_UPDATES
, ACCEPT_LICENSE
};
175 E_CMD_TYPE m_eCmdType
;
177 OUString m_sExtensionURL
;
178 OUString m_sRepository
;
179 uno::Reference
< deployment::XPackage
> m_xPackage
;
180 std::vector
< uno::Reference
< deployment::XPackage
> > m_vExtensionList
;
182 ExtensionCmd( const E_CMD_TYPE eCommand
,
183 const OUString
&rExtensionURL
,
184 const OUString
&rRepository
,
185 const bool bWarnUser
)
186 : m_eCmdType( eCommand
),
187 m_bWarnUser( bWarnUser
),
188 m_sExtensionURL( rExtensionURL
),
189 m_sRepository( rRepository
) {};
190 ExtensionCmd( const E_CMD_TYPE eCommand
,
191 const uno::Reference
< deployment::XPackage
> &rPackage
)
192 : m_eCmdType( eCommand
),
193 m_bWarnUser( false ),
194 m_xPackage( rPackage
) {};
195 ExtensionCmd( const E_CMD_TYPE eCommand
,
196 const std::vector
<uno::Reference
<deployment::XPackage
> > &vExtensionList
)
197 : m_eCmdType( eCommand
),
198 m_bWarnUser( false ),
199 m_vExtensionList( vExtensionList
) {};
202 typedef std::shared_ptr
< ExtensionCmd
> TExtensionCmd
;
205 class ExtensionCmdQueue::Thread
: public salhelper::Thread
208 Thread( DialogHelper
*pDialogHelper
,
209 TheExtensionManager
*pManager
,
210 const uno::Reference
< uno::XComponentContext
> & rContext
);
212 void addExtension( const OUString
&rExtensionURL
,
213 const OUString
&rRepository
,
214 const bool bWarnUser
);
215 void removeExtension( const uno::Reference
< deployment::XPackage
> &rPackage
);
216 void enableExtension( const uno::Reference
< deployment::XPackage
> &rPackage
,
217 const bool bEnable
);
218 void checkForUpdates( const std::vector
<uno::Reference
<deployment::XPackage
> > &vExtensionList
);
219 void acceptLicense( const uno::Reference
< deployment::XPackage
> &rPackage
);
224 virtual ~Thread() override
;
226 virtual void execute() override
;
228 void _insert(const TExtensionCmd
& rExtCmd
);
230 void _addExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
231 const OUString
&rPackageURL
,
232 const OUString
&rRepository
,
233 const bool bWarnUser
);
234 void _removeExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
235 const uno::Reference
< deployment::XPackage
> &xPackage
);
236 void _enableExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
237 const uno::Reference
< deployment::XPackage
> &xPackage
);
238 void _disableExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
239 const uno::Reference
< deployment::XPackage
> &xPackage
);
240 void _checkForUpdates( const std::vector
<uno::Reference
<deployment::XPackage
> > &vExtensionList
);
241 void _acceptLicense( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
242 const uno::Reference
< deployment::XPackage
> &xPackage
);
244 enum Input
{ NONE
, START
, STOP
};
246 uno::Reference
< uno::XComponentContext
> m_xContext
;
247 std::queue
< TExtensionCmd
> m_queue
;
249 DialogHelper
*m_pDialogHelper
;
250 TheExtensionManager
*m_pManager
;
252 const OUString m_sEnablingPackages
;
253 const OUString m_sDisablingPackages
;
254 const OUString m_sAddingPackages
;
255 const OUString m_sRemovingPackages
;
256 const OUString m_sDefaultCmd
;
257 const OUString m_sAcceptLicense
;
258 osl::Condition m_wakeup
;
266 void ProgressCmdEnv::startProgress()
268 m_nCurrentProgress
= 0;
270 if ( m_pDialogHelper
)
271 m_pDialogHelper
->showProgress( true );
275 void ProgressCmdEnv::stopProgress()
277 if ( m_pDialogHelper
)
278 m_pDialogHelper
->showProgress( false );
282 void ProgressCmdEnv::progressSection( const OUString
&rText
,
283 const uno::Reference
< task::XAbortChannel
> &xAbortChannel
)
285 m_nCurrentProgress
= 0;
286 if ( m_pDialogHelper
)
288 m_pDialogHelper
->updateProgress( rText
, xAbortChannel
);
289 m_pDialogHelper
->updateProgress( 5 );
294 void ProgressCmdEnv::updateProgress()
296 long nProgress
= ((m_nCurrentProgress
*5) % 100) + 5;
297 if ( m_pDialogHelper
)
298 m_pDialogHelper
->updateProgress( nProgress
);
301 // XCommandEnvironment
303 uno::Reference
< task::XInteractionHandler
> ProgressCmdEnv::getInteractionHandler()
309 uno::Reference
< ucb::XProgressHandler
> ProgressCmdEnv::getProgressHandler()
315 // XInteractionHandler
317 void ProgressCmdEnv::handle( uno::Reference
< task::XInteractionRequest
> const & xRequest
)
319 uno::Any
request( xRequest
->getRequest() );
320 OSL_ASSERT( request
.getValueTypeClass() == uno::TypeClass_EXCEPTION
);
321 dp_misc::TRACE( "[dp_gui_cmdenv.cxx] incoming request:\n"
322 + ::comphelper::anyToString(request
) + "\n");
324 lang::WrappedTargetException wtExc
;
325 deployment::DependencyException depExc
;
326 deployment::LicenseException licExc
;
327 deployment::VersionException verExc
;
328 deployment::InstallException instExc
;
329 deployment::PlatformException platExc
;
332 bool approve
= false;
335 if (request
>>= wtExc
) {
336 // handable deployment error signalled, e.g.
337 // bundle item registration failed, notify cause only:
339 deployment::DeploymentException dpExc
;
340 if (wtExc
.TargetException
>>= dpExc
)
343 ucb::CommandFailedException cfExc
;
344 if (wtExc
.TargetException
>>= cfExc
)
345 cause
= cfExc
.Reason
;
347 cause
= wtExc
.TargetException
;
351 // ignore intermediate errors of legacy packages, i.e.
352 // former pkgchk behaviour:
353 const uno::Reference
< deployment::XPackage
> xPackage( wtExc
.Context
, uno::UNO_QUERY
);
354 OSL_ASSERT( xPackage
.is() );
357 const uno::Reference
< deployment::XPackageTypeInfo
> xPackageType( xPackage
->getPackageType() );
358 OSL_ASSERT( xPackageType
.is() );
359 if (xPackageType
.is())
361 approve
= ( xPackage
->isBundle() &&
362 xPackageType
->getMediaType().match(
363 "application/vnd.sun.star.legacy-package-bundle" ));
368 else if (request
>>= depExc
)
370 std::vector
< OUString
> deps
;
371 deps
.reserve(depExc
.UnsatisfiedDependencies
.getLength());
372 for (sal_Int32 i
= 0; i
< depExc
.UnsatisfiedDependencies
.getLength(); ++i
)
375 dp_misc::Dependencies::getErrorText( depExc
.UnsatisfiedDependencies
[i
]) );
378 SolarMutexGuard guard
;
380 m_pDialogHelper
->incBusy();
381 DependencyDialog
aDlg(activeDialog(), deps
);
382 short n
= aDlg
.run();
384 m_pDialogHelper
->decBusy();
385 // Distinguish between closing the dialog and programmatically
386 // canceling the dialog (headless VCL):
387 approve
= n
== RET_OK
388 || (n
== RET_CANCEL
&& !Application::IsDialogCancelEnabled());
391 else if (request
>>= licExc
)
393 SolarMutexGuard guard
;
395 weld::Window
*pTopLevel
= activeDialog();
397 m_pDialogHelper
->incBusy();
398 uno::Reference
< ui::dialogs::XExecutableDialog
> xDialog(
399 deployment::ui::LicenseDialog::create(
400 m_xContext
, pTopLevel
? pTopLevel
->GetXWindow() : nullptr,
401 licExc
.ExtensionName
, licExc
.Text
) );
402 sal_Int16 res
= xDialog
->execute();
404 m_pDialogHelper
->decBusy();
405 if ( res
== ui::dialogs::ExecutableDialogResults::CANCEL
)
407 else if ( res
== ui::dialogs::ExecutableDialogResults::OK
)
414 else if (request
>>= verExc
)
417 switch (dp_misc::compareVersions(
418 verExc
.NewVersion
, verExc
.Deployed
->getVersion() ))
421 id
= RID_STR_WARNING_VERSION_LESS
;
424 id
= RID_STR_WARNING_VERSION_EQUAL
;
426 default: // dp_misc::GREATER
427 id
= RID_STR_WARNING_VERSION_GREATER
;
430 OSL_ASSERT( verExc
.Deployed
.is() );
431 bool bEqualNames
= verExc
.NewDisplayName
==
432 verExc
.Deployed
->getDisplayName();
434 SolarMutexGuard guard
;
437 m_pDialogHelper
->incBusy();
439 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(activeDialog(),
440 VclMessageType::Warning
, VclButtonsType::OkCancel
, DpResId(id
)));
444 s
= xBox
->get_primary_text();
446 else if (!strcmp(id
, RID_STR_WARNING_VERSION_EQUAL
))
448 //hypothetical: requires two instances of an extension with the same
449 //version to have different display names. Probably the developer forgot
450 //to change the version.
451 s
= DpResId(RID_STR_WARNINGBOX_VERSION_EQUAL_DIFFERENT_NAMES
);
453 else if (!strcmp(id
, RID_STR_WARNING_VERSION_LESS
))
455 s
= DpResId(RID_STR_WARNINGBOX_VERSION_LESS_DIFFERENT_NAMES
);
457 else if (!strcmp(id
, RID_STR_WARNING_VERSION_GREATER
))
459 s
= DpResId(RID_STR_WARNINGBOX_VERSION_GREATER_DIFFERENT_NAMES
);
461 s
= s
.replaceAll("$NAME", verExc
.NewDisplayName
);
462 s
= s
.replaceAll("$OLDNAME", verExc
.Deployed
->getDisplayName());
463 s
= s
.replaceAll("$NEW", getVersion(verExc
.NewVersion
));
464 s
= s
.replaceAll("$DEPLOYED", getVersion(verExc
.Deployed
));
465 xBox
->set_primary_text(s
);
466 approve
= xBox
->run() == RET_OK
;
468 m_pDialogHelper
->decBusy();
472 else if (request
>>= instExc
)
480 if ( m_pDialogHelper
)
482 SolarMutexGuard guard
;
484 approve
= m_pDialogHelper
->installExtensionWarn( instExc
.displayName
);
491 else if (request
>>= platExc
)
493 SolarMutexGuard guard
;
494 OUString
sMsg(DpResId(RID_STR_UNSUPPORTED_PLATFORM
));
495 sMsg
= sMsg
.replaceAll("%Name", platExc
.package
->getDisplayName());
497 m_pDialogHelper
->incBusy();
498 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(activeDialog(),
499 VclMessageType::Warning
, VclButtonsType::Ok
, sMsg
));
502 m_pDialogHelper
->decBusy();
506 if (!approve
&& !abort
)
508 // forward to UUI handler:
509 if (! m_xHandler
.is()) {
511 m_xHandler
= task::InteractionHandler::createWithParentAndContext(m_xContext
, nullptr, m_sTitle
);
513 m_xHandler
->handle( xRequest
);
518 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > conts(
519 xRequest
->getContinuations() );
520 uno::Reference
< task::XInteractionContinuation
> const * pConts
= conts
.getConstArray();
521 sal_Int32 len
= conts
.getLength();
522 for ( sal_Int32 pos
= 0; pos
< len
; ++pos
)
525 uno::Reference
< task::XInteractionApprove
> xInteractionApprove( pConts
[ pos
], uno::UNO_QUERY
);
526 if (xInteractionApprove
.is()) {
527 xInteractionApprove
->select();
528 // don't query again for ongoing continuations:
533 uno::Reference
< task::XInteractionAbort
> xInteractionAbort( pConts
[ pos
], uno::UNO_QUERY
);
534 if (xInteractionAbort
.is()) {
535 xInteractionAbort
->select();
536 // don't query again for ongoing continuations:
547 void ProgressCmdEnv::push( uno::Any
const & rStatus
)
553 void ProgressCmdEnv::update_( uno::Any
const & rStatus
)
556 if ( rStatus
.hasValue() && !( rStatus
>>= text
) )
558 if ( auto e
= o3tl::tryAccess
<uno::Exception
>(rStatus
) )
560 if ( text
.isEmpty() )
561 text
= ::comphelper::anyToString( rStatus
); // fallback
563 const SolarMutexGuard aGuard
;
565 m_pDialogHelper
->incBusy();
566 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(activeDialog(),
567 VclMessageType::Warning
, VclButtonsType::Ok
, text
));
570 m_pDialogHelper
->decBusy();
572 ++m_nCurrentProgress
;
577 void ProgressCmdEnv::update( uno::Any
const & rStatus
)
583 void ProgressCmdEnv::pop()
585 update_( uno::Any() ); // no message
589 ExtensionCmdQueue::Thread::Thread( DialogHelper
*pDialogHelper
,
590 TheExtensionManager
*pManager
,
591 const uno::Reference
< uno::XComponentContext
> & rContext
) :
592 salhelper::Thread( "dp_gui_extensioncmdqueue" ),
593 m_xContext( rContext
),
594 m_pDialogHelper( pDialogHelper
),
595 m_pManager( pManager
),
596 m_sEnablingPackages( DpResId( RID_STR_ENABLING_PACKAGES
) ),
597 m_sDisablingPackages( DpResId( RID_STR_DISABLING_PACKAGES
) ),
598 m_sAddingPackages( DpResId( RID_STR_ADDING_PACKAGES
) ),
599 m_sRemovingPackages( DpResId( RID_STR_REMOVING_PACKAGES
) ),
600 m_sDefaultCmd( DpResId( RID_STR_ADD_PACKAGES
) ),
601 m_sAcceptLicense( DpResId( RID_STR_ACCEPT_LICENSE
) ),
606 OSL_ASSERT( pDialogHelper
);
610 void ExtensionCmdQueue::Thread::addExtension( const OUString
&rExtensionURL
,
611 const OUString
&rRepository
,
612 const bool bWarnUser
)
614 if ( !rExtensionURL
.isEmpty() )
616 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::ADD
, rExtensionURL
, rRepository
, bWarnUser
) );
622 void ExtensionCmdQueue::Thread::removeExtension( const uno::Reference
< deployment::XPackage
> &rPackage
)
626 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::REMOVE
, rPackage
) );
632 void ExtensionCmdQueue::Thread::acceptLicense( const uno::Reference
< deployment::XPackage
> &rPackage
)
636 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::ACCEPT_LICENSE
, rPackage
) );
642 void ExtensionCmdQueue::Thread::enableExtension( const uno::Reference
< deployment::XPackage
> &rPackage
,
647 TExtensionCmd
pEntry( new ExtensionCmd( bEnable
? ExtensionCmd::ENABLE
:
648 ExtensionCmd::DISABLE
,
655 void ExtensionCmdQueue::Thread::checkForUpdates(
656 const std::vector
<uno::Reference
<deployment::XPackage
> > &vExtensionList
)
658 TExtensionCmd
pEntry( new ExtensionCmd( ExtensionCmd::CHECK_FOR_UPDATES
, vExtensionList
) );
663 //Stopping this thread will not abort the installation of extensions.
664 void ExtensionCmdQueue::Thread::stop()
666 osl::MutexGuard
aGuard( m_mutex
);
673 bool ExtensionCmdQueue::Thread::isBusy()
675 osl::MutexGuard
aGuard( m_mutex
);
680 ExtensionCmdQueue::Thread::~Thread() {}
683 void ExtensionCmdQueue::Thread::execute()
686 //Needed for use of the service "com.sun.star.system.SystemShellExecute" in
687 //DialogHelper::openWebBrowser
689 (void) CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED
);
693 if ( m_wakeup
.wait() != osl::Condition::result_ok
)
695 dp_misc::TRACE( "dp_gui::ExtensionCmdQueue::Thread::run: ignored "
696 "osl::Condition::wait failure\n" );
703 osl::MutexGuard
aGuard( m_mutex
);
706 nSize
= m_queue
.size();
710 // If this thread has been woken up by anything else except start, stop
711 // then input is NONE and we wait again.
712 // We only install the extension which are currently in the queue.
713 // The progressbar will be set to show the progress of the current number
714 // of extensions. If we allowed to add extensions now then the progressbar may
715 // have reached the end while we still install newly added extensions.
716 if ( ( eInput
== NONE
) || ( nSize
== 0 ) )
718 if ( eInput
== STOP
)
721 ::rtl::Reference
< ProgressCmdEnv
> currentCmdEnv( new ProgressCmdEnv( m_xContext
, m_pDialogHelper
, m_sDefaultCmd
) );
723 // Do not lock the following part with addExtension. addExtension may be called in the main thread.
724 // If the message box "Do you want to install the extension (or similar)" is shown and then
725 // addExtension is called, which then blocks the main thread, then we deadlock.
726 bool bStartProgress
= true;
728 while ( --nSize
>= 0 )
731 osl::MutexGuard
aGuard( m_mutex
);
737 TExtensionCmd pEntry
;
739 ::osl::MutexGuard
queueGuard( m_mutex
);
740 pEntry
= m_queue
.front();
744 if ( bStartProgress
&& ( pEntry
->m_eCmdType
!= ExtensionCmd::CHECK_FOR_UPDATES
) )
746 currentCmdEnv
->startProgress();
747 bStartProgress
= false;
750 switch ( pEntry
->m_eCmdType
) {
751 case ExtensionCmd::ADD
:
752 _addExtension( currentCmdEnv
, pEntry
->m_sExtensionURL
, pEntry
->m_sRepository
, pEntry
->m_bWarnUser
);
754 case ExtensionCmd::REMOVE
:
755 _removeExtension( currentCmdEnv
, pEntry
->m_xPackage
);
757 case ExtensionCmd::ENABLE
:
758 _enableExtension( currentCmdEnv
, pEntry
->m_xPackage
);
760 case ExtensionCmd::DISABLE
:
761 _disableExtension( currentCmdEnv
, pEntry
->m_xPackage
);
763 case ExtensionCmd::CHECK_FOR_UPDATES
:
764 _checkForUpdates( pEntry
->m_vExtensionList
);
766 case ExtensionCmd::ACCEPT_LICENSE
:
767 _acceptLicense( currentCmdEnv
, pEntry
->m_xPackage
);
771 catch ( const ucb::CommandAbortedException
& )
773 //This exception is thrown when the user clicks cancel on the progressbar.
774 //Then we cancel the installation of all extensions and remove them from
777 ::osl::MutexGuard
queueGuard2(m_mutex
);
778 while ( --nSize
>= 0 )
783 catch ( const ucb::CommandFailedException
& )
785 //This exception is thrown when a user clicked cancel in the messagebox which was
786 //started by the interaction handler. For example the user will be asked if he/she
787 //really wants to install the extension.
788 //These interaction are run for exactly one extension at a time. Therefore we continue
789 //with installing the remaining extensions.
792 catch ( const uno::Exception
& )
794 //Todo display the user an error
795 //see also DialogImpl::SyncPushButton::Click()
796 uno::Any
exc( ::cppu::getCaughtException() );
798 deployment::DeploymentException dpExc
;
801 if (auto e
= o3tl::tryAccess
<uno::Exception
>(dpExc
.Cause
))
803 // notify error cause only:
807 if (msg
.isEmpty()) // fallback for debugging purposes
808 msg
= ::comphelper::anyToString(exc
);
810 const SolarMutexGuard guard
;
812 m_pDialogHelper
->incBusy();
814 std::unique_ptr
<weld::MessageDialog
> xBox(Application::CreateMessageDialog(currentCmdEnv
->activeDialog(),
815 VclMessageType::Warning
, VclButtonsType::Ok
, msg
));
817 xBox
->set_title(m_pDialogHelper
->getFrameWeld()->get_title());
820 m_pDialogHelper
->decBusy();
821 //Continue with installation of the remaining extensions
824 osl::MutexGuard
aGuard( m_mutex
);
830 // when leaving the while loop with break, we should set working to false, too
831 osl::MutexGuard
aGuard( m_mutex
);
835 if ( !bStartProgress
)
836 currentCmdEnv
->stopProgress();
845 void ExtensionCmdQueue::Thread::_addExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
846 const OUString
&rPackageURL
,
847 const OUString
&rRepository
,
848 const bool bWarnUser
)
850 //check if we have a string in anyTitle. For example "unopkg gui \" caused anyTitle to be void
851 //and anyTitle.get<OUString> throws as RuntimeException.
855 anyTitle
= ::ucbhelper::Content( rPackageURL
, rCmdEnv
.get(), m_xContext
).getPropertyValue( "Title" );
857 catch ( const uno::Exception
& )
863 if ( ! (anyTitle
>>= sName
) )
865 OSL_FAIL("Could not get file name for extension.");
869 rCmdEnv
->setWarnUser( bWarnUser
);
870 uno::Reference
< deployment::XExtensionManager
> xExtMgr
= m_pManager
->getExtensionManager();
871 uno::Reference
< task::XAbortChannel
> xAbortChannel( xExtMgr
->createAbortChannel() );
873 m_sAddingPackages
.replaceAll("%EXTENSION_NAME", sName
));
874 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
878 xExtMgr
->addExtension(rPackageURL
, uno::Sequence
<beans::NamedValue
>(),
879 rRepository
, xAbortChannel
, rCmdEnv
.get() );
881 catch ( const ucb::CommandFailedException
& )
883 // When the extension is already installed we'll get a dialog asking if we want to overwrite. If we then press
884 // cancel this exception is thrown.
886 catch ( const ucb::CommandAbortedException
& )
888 // User clicked the cancel button
889 // TODO: handle cancel
891 rCmdEnv
->setWarnUser( false );
895 void ExtensionCmdQueue::Thread::_removeExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
896 const uno::Reference
< deployment::XPackage
> &xPackage
)
898 uno::Reference
< deployment::XExtensionManager
> xExtMgr
= m_pManager
->getExtensionManager();
899 uno::Reference
< task::XAbortChannel
> xAbortChannel( xExtMgr
->createAbortChannel() );
901 m_sRemovingPackages
.replaceAll("%EXTENSION_NAME",
902 xPackage
->getDisplayName()));
903 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
905 OUString
id( dp_misc::getIdentifier( xPackage
) );
908 xExtMgr
->removeExtension( id
, xPackage
->getName(), xPackage
->getRepositoryName(), xAbortChannel
, rCmdEnv
.get() );
910 catch ( const deployment::DeploymentException
& )
912 catch ( const ucb::CommandFailedException
& )
914 catch ( const ucb::CommandAbortedException
& )
917 // Check, if there are still updates to be notified via menu bar icon
918 uno::Sequence
< uno::Sequence
< OUString
> > aItemList
;
919 UpdateDialog::createNotifyJob( false, aItemList
);
923 void ExtensionCmdQueue::Thread::_checkForUpdates(
924 const std::vector
<uno::Reference
<deployment::XPackage
> > &vExtensionList
)
926 const SolarMutexGuard guard
;
929 m_pDialogHelper
->incBusy();
931 std::vector
< UpdateData
> vData
;
932 UpdateDialog
aUpdateDialog(m_xContext
, m_pDialogHelper
? m_pDialogHelper
->getFrameWeld() : nullptr, vExtensionList
, &vData
);
934 aUpdateDialog
.notifyMenubar( true, false ); // prepare the checking, if there updates to be notified via menu bar icon
936 bool bOk
= aUpdateDialog
.run() == RET_OK
;
938 m_pDialogHelper
->decBusy();
940 if (bOk
&& !vData
.empty())
942 // If there is at least one directly downloadable extension then we
943 // open the install dialog.
944 std::vector
< UpdateData
> dataDownload
;
946 for (auto const& data
: vData
)
948 if ( data
.sWebsiteURL
.isEmpty() )
949 dataDownload
.push_back(data
);
952 short nDialogResult
= RET_OK
;
953 if ( !dataDownload
.empty() )
956 m_pDialogHelper
->incBusy();
957 UpdateInstallDialog
aDlg(m_pDialogHelper
? m_pDialogHelper
->getFrameWeld() : nullptr, dataDownload
, m_xContext
);
958 nDialogResult
= aDlg
.run();
960 m_pDialogHelper
->decBusy();
961 aUpdateDialog
.notifyMenubar( false, true ); // Check, if there are still pending updates to be notified via menu bar icon
964 aUpdateDialog
.notifyMenubar( false, false ); // Check, if there are pending updates to be notified via menu bar icon
966 //Now start the webbrowser and navigate to the websites where we get the updates
967 if ( RET_OK
== nDialogResult
)
969 for (auto const& data
: vData
)
971 if ( m_pDialogHelper
&& ( !data
.sWebsiteURL
.isEmpty() ) )
972 m_pDialogHelper
->openWebBrowser( data
.sWebsiteURL
, m_pDialogHelper
->getFrameWeld()->get_title() );
977 aUpdateDialog
.notifyMenubar( false, false ); // check if there updates to be notified via menu bar icon
981 void ExtensionCmdQueue::Thread::_enableExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
982 const uno::Reference
< deployment::XPackage
> &xPackage
)
984 if ( !xPackage
.is() )
987 uno::Reference
< deployment::XExtensionManager
> xExtMgr
= m_pManager
->getExtensionManager();
988 uno::Reference
< task::XAbortChannel
> xAbortChannel( xExtMgr
->createAbortChannel() );
990 m_sEnablingPackages
.replaceAll("%EXTENSION_NAME",
991 xPackage
->getDisplayName()));
992 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
996 xExtMgr
->enableExtension( xPackage
, xAbortChannel
, rCmdEnv
.get() );
997 if ( m_pDialogHelper
)
998 m_pDialogHelper
->updatePackageInfo( xPackage
);
1000 catch ( const ::ucb::CommandAbortedException
& )
1005 void ExtensionCmdQueue::Thread::_disableExtension( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
1006 const uno::Reference
< deployment::XPackage
> &xPackage
)
1008 if ( !xPackage
.is() )
1011 uno::Reference
< deployment::XExtensionManager
> xExtMgr
= m_pManager
->getExtensionManager();
1012 uno::Reference
< task::XAbortChannel
> xAbortChannel( xExtMgr
->createAbortChannel() );
1014 m_sDisablingPackages
.replaceAll("%EXTENSION_NAME",
1015 xPackage
->getDisplayName()));
1016 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
1020 xExtMgr
->disableExtension( xPackage
, xAbortChannel
, rCmdEnv
.get() );
1021 if ( m_pDialogHelper
)
1022 m_pDialogHelper
->updatePackageInfo( xPackage
);
1024 catch ( const ::ucb::CommandAbortedException
& )
1029 void ExtensionCmdQueue::Thread::_acceptLicense( ::rtl::Reference
< ProgressCmdEnv
> const &rCmdEnv
,
1030 const uno::Reference
< deployment::XPackage
> &xPackage
)
1032 if ( !xPackage
.is() )
1035 uno::Reference
< deployment::XExtensionManager
> xExtMgr
= m_pManager
->getExtensionManager();
1036 uno::Reference
< task::XAbortChannel
> xAbortChannel( xExtMgr
->createAbortChannel() );
1038 m_sAcceptLicense
.replaceAll("%EXTENSION_NAME",
1039 xPackage
->getDisplayName()));
1040 rCmdEnv
->progressSection( sTitle
, xAbortChannel
);
1044 xExtMgr
->checkPrerequisitesAndEnable( xPackage
, xAbortChannel
, rCmdEnv
.get() );
1045 if ( m_pDialogHelper
)
1046 m_pDialogHelper
->updatePackageInfo( xPackage
);
1048 catch ( const ::ucb::CommandAbortedException
& )
1052 void ExtensionCmdQueue::Thread::_insert(const TExtensionCmd
& rExtCmd
)
1054 ::osl::MutexGuard
aGuard( m_mutex
);
1056 // If someone called stop then we do not process the command -> game over!
1060 m_queue
.push( rExtCmd
);
1066 ExtensionCmdQueue::ExtensionCmdQueue( DialogHelper
* pDialogHelper
,
1067 TheExtensionManager
*pManager
,
1068 const uno::Reference
< uno::XComponentContext
> &rContext
)
1069 : m_thread( new Thread( pDialogHelper
, pManager
, rContext
) )
1074 ExtensionCmdQueue::~ExtensionCmdQueue() {
1078 void ExtensionCmdQueue::addExtension( const OUString
& extensionURL
,
1079 const OUString
& repository
,
1080 const bool bWarnUser
)
1082 m_thread
->addExtension( extensionURL
, repository
, bWarnUser
);
1085 void ExtensionCmdQueue::removeExtension( const uno::Reference
< deployment::XPackage
> &rPackage
)
1087 m_thread
->removeExtension( rPackage
);
1090 void ExtensionCmdQueue::enableExtension( const uno::Reference
< deployment::XPackage
> &rPackage
,
1091 const bool bEnable
)
1093 m_thread
->enableExtension( rPackage
, bEnable
);
1096 void ExtensionCmdQueue::checkForUpdates( const std::vector
<uno::Reference
<deployment::XPackage
> > &vExtensionList
)
1098 m_thread
->checkForUpdates( vExtensionList
);
1101 void ExtensionCmdQueue::acceptLicense( const uno::Reference
< deployment::XPackage
> &rPackage
)
1103 m_thread
->acceptLicense( rPackage
);
1106 void ExtensionCmdQueue::syncRepositories( const uno::Reference
< uno::XComponentContext
> &xContext
)
1108 dp_misc::syncRepositories( false, new ProgressCmdEnv( xContext
, nullptr, "Extension Manager" ) );
1111 void ExtensionCmdQueue::stop()
1116 bool ExtensionCmdQueue::isBusy()
1118 return m_thread
->isBusy();
1121 void handleInteractionRequest( const uno::Reference
< uno::XComponentContext
> & xContext
,
1122 const uno::Reference
< task::XInteractionRequest
> & xRequest
)
1124 ::rtl::Reference
< ProgressCmdEnv
> xCmdEnv( new ProgressCmdEnv( xContext
, nullptr, "Extension Manager" ) );
1125 xCmdEnv
->handle( xRequest
);
1128 } //namespace dp_gui
1130 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */