Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / desktop / source / deployment / gui / dp_gui_theextmgr.cxx
blob54bd5e4b5d9e61606d1bb27806f7dd4a726c7aad
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <vcl/svapp.hxx>
22 #include <toolkit/helper/vclunohelper.hxx>
24 #include <com/sun/star/beans/XPropertySet.hpp>
25 #include <com/sun/star/configuration/theDefaultProvider.hpp>
26 #include <com/sun/star/deployment/DeploymentException.hpp>
27 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
28 #include <com/sun/star/frame/Desktop.hpp>
29 #include <com/sun/star/frame/TerminationVetoException.hpp>
30 #include <com/sun/star/ucb/CommandAbortedException.hpp>
31 #include <com/sun/star/ucb/CommandFailedException.hpp>
32 #include <comphelper/propertysequence.hxx>
33 #include <cppuhelper/exc_hlp.hxx>
34 #include <sal/log.hxx>
35 #include <osl/diagnose.h>
36 #include <tools/diagnose_ex.h>
38 #include "dp_gui_dialog2.hxx"
39 #include "dp_gui_extensioncmdqueue.hxx"
40 #include "dp_gui_theextmgr.hxx"
41 #include <dp_identifier.hxx>
42 #include <dp_update.hxx>
44 #define USER_PACKAGE_MANAGER "user"
45 #define SHARED_PACKAGE_MANAGER "shared"
47 using namespace ::com::sun::star;
49 namespace dp_gui {
52 ::rtl::Reference< TheExtensionManager > TheExtensionManager::s_ExtMgr;
55 // TheExtensionManager
58 TheExtensionManager::TheExtensionManager( const uno::Reference< awt::XWindow > &xParent,
59 const uno::Reference< uno::XComponentContext > &xContext ) :
60 m_xContext( xContext ),
61 m_xParent( xParent ),
62 m_bModified(false),
63 m_bExtMgrDialogExecuting(false)
65 m_xExtensionManager = deployment::ExtensionManager::get( xContext );
66 m_xExtensionManager->addModifyListener( this );
68 uno::Reference< lang::XMultiServiceFactory > xConfig(
69 configuration::theDefaultProvider::get(xContext));
70 uno::Sequence<uno::Any> args(comphelper::InitAnyPropertySequence(
72 {"nodepath", uno::Any(OUString("/org.openoffice.Office.OptionsDialog/Nodes"))}
73 }));
74 m_xNameAccessNodes.set(
75 xConfig->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", args),
76 uno::UNO_QUERY_THROW);
78 // get the 'get more extensions here' url
79 uno::Sequence<uno::Any> args2(comphelper::InitAnyPropertySequence(
81 {"nodepath", uno::Any(OUString("/org.openoffice.Office.ExtensionManager/ExtensionRepositories"))}
82 }));
83 uno::Reference< container::XNameAccess > xNameAccessRepositories;
84 xNameAccessRepositories.set(
85 xConfig->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", args2),
86 uno::UNO_QUERY_THROW);
87 try
88 { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
89 uno::Any value = xNameAccessRepositories->getByName("WebsiteLink");
90 m_sGetExtensionsURL = value.get< OUString > ();
92 catch ( const uno::Exception& )
95 if ( dp_misc::office_is_running() )
97 // the registration should be done after the construction has been ended
98 // otherwise an exception prevents object creation, but it is registered as a listener
99 m_xDesktop.set( frame::Desktop::create(xContext), uno::UNO_SET_THROW );
100 m_xDesktop->addTerminateListener( this );
104 TheExtensionManager::~TheExtensionManager()
106 if (m_xUpdReqDialog)
107 m_xUpdReqDialog->response(RET_CANCEL);
108 assert(!m_xUpdReqDialog);
109 if (m_xExtMgrDialog)
111 if (m_bExtMgrDialogExecuting)
112 m_xExtMgrDialog->response(RET_CANCEL);
113 else
115 m_xExtMgrDialog->Close();
116 m_xExtMgrDialog.reset();
119 assert(!m_xExtMgrDialog);
122 void TheExtensionManager::createDialog( const bool bCreateUpdDlg )
124 const SolarMutexGuard guard;
126 if ( bCreateUpdDlg )
128 if ( !m_xUpdReqDialog )
130 m_xUpdReqDialog.reset(new UpdateRequiredDialog(Application::GetFrameWeld(m_xParent), this));
131 m_xExecuteCmdQueue.reset( new ExtensionCmdQueue( m_xUpdReqDialog.get(), this, m_xContext ) );
132 createPackageList();
135 else if ( !m_xExtMgrDialog )
137 m_xExtMgrDialog.reset(new ExtMgrDialog(Application::GetFrameWeld(m_xParent), this));
138 m_xExecuteCmdQueue.reset( new ExtensionCmdQueue( m_xExtMgrDialog.get(), this, m_xContext ) );
139 m_xExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL );
140 createPackageList();
144 void TheExtensionManager::Show()
146 const SolarMutexGuard guard;
148 m_bExtMgrDialogExecuting = true;
150 weld::DialogController::runAsync(m_xExtMgrDialog, [this](sal_Int32 /*nResult*/) {
151 m_bExtMgrDialogExecuting = false;
152 auto xExtMgrDialog = m_xExtMgrDialog;
153 m_xExtMgrDialog.reset();
154 xExtMgrDialog->Close();
158 void TheExtensionManager::SetText( const OUString &rTitle )
160 const SolarMutexGuard guard;
162 getDialog()->set_title( rTitle );
166 void TheExtensionManager::ToTop()
168 const SolarMutexGuard guard;
170 getDialog()->present();
173 void TheExtensionManager::Close()
175 if (m_xExtMgrDialog)
177 if (m_bExtMgrDialogExecuting)
178 m_xExtMgrDialog->response(RET_CANCEL);
179 else
180 m_xExtMgrDialog->Close();
182 else if (m_xUpdReqDialog)
183 m_xUpdReqDialog->response(RET_CANCEL);
186 sal_Int16 TheExtensionManager::execute()
188 sal_Int16 nRet = 0;
190 if ( m_xUpdReqDialog )
192 nRet = m_xUpdReqDialog->run();
193 m_xUpdReqDialog.reset();
196 return nRet;
199 bool TheExtensionManager::isVisible()
201 weld::Window* pDialog = getDialog();
202 return pDialog && pDialog->get_visible();
205 void TheExtensionManager::checkUpdates()
207 std::vector< uno::Reference< deployment::XPackage > > vEntries;
208 uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
210 try {
211 xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
212 uno::Reference< ucb::XCommandEnvironment >() );
213 } catch ( const deployment::DeploymentException & ) {
214 return;
215 } catch ( const ucb::CommandFailedException & ) {
216 return;
217 } catch ( const ucb::CommandAbortedException & ) {
218 return;
219 } catch ( const lang::IllegalArgumentException & e ) {
220 css::uno::Any anyEx = cppu::getCaughtException();
221 throw css::lang::WrappedTargetRuntimeException( e.Message,
222 e.Context, anyEx );
225 for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
227 uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]);
228 OSL_ASSERT(xPackage.is());
229 if ( xPackage.is() )
231 vEntries.push_back( xPackage );
235 m_xExecuteCmdQueue->checkForUpdates( vEntries );
239 bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser )
241 if ( rPackageURL.isEmpty() )
242 return false;
244 createDialog( false );
246 bool bInstall = true;
247 bool bInstallForAll = false;
249 // DV! missing function is read only repository from extension manager
250 if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) )
251 bInstall = getDialogHelper()->installForAllUsers( bInstallForAll );
253 if ( !bInstall )
254 return false;
256 if ( bInstallForAll )
257 m_xExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false );
258 else
259 m_xExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser );
261 return true;
265 void TheExtensionManager::terminateDialog()
267 if ( ! dp_misc::office_is_running() )
269 const SolarMutexGuard guard;
270 if (m_xExtMgrDialog)
272 if (m_bExtMgrDialogExecuting)
273 m_xExtMgrDialog->response(RET_CANCEL);
274 else
276 m_xExtMgrDialog->Close();
277 m_xExtMgrDialog.reset();
280 assert(!m_xExtMgrDialog);
281 if (m_xUpdReqDialog)
282 m_xUpdReqDialog->response(RET_CANCEL);
283 assert(!m_xUpdReqDialog);
284 Application::Quit();
289 void TheExtensionManager::createPackageList()
291 uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
293 try {
294 xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
295 uno::Reference< ucb::XCommandEnvironment >() );
296 } catch ( const deployment::DeploymentException & ) {
297 return;
298 } catch ( const ucb::CommandFailedException & ) {
299 return;
300 } catch ( const ucb::CommandAbortedException & ) {
301 return;
302 } catch ( const lang::IllegalArgumentException & e ) {
303 css::uno::Any anyEx = cppu::getCaughtException();
304 throw css::lang::WrappedTargetRuntimeException( e.Message,
305 e.Context, anyEx );
308 for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
310 uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i];
312 for ( sal_Int32 j = 0; j < xPackageList.getLength(); ++j )
314 uno::Reference< deployment::XPackage > xPackage = xPackageList[j];
315 if ( xPackage.is() )
317 PackageState eState = getPackageState( xPackage );
318 getDialogHelper()->addPackageToList( xPackage );
319 // When the package is enabled, we can stop here, otherwise we have to look for
320 // another version of this package
321 if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) )
322 break;
327 uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER,
328 uno::Reference< ucb::XCommandEnvironment >() );
329 for ( sal_Int32 i = 0; i < xNoLicPackages.getLength(); ++i )
331 uno::Reference< deployment::XPackage > xPackage = xNoLicPackages[i];
332 if ( xPackage.is() )
334 getDialogHelper()->addPackageToList( xPackage, true );
340 PackageState TheExtensionManager::getPackageState( const uno::Reference< deployment::XPackage > &xPackage )
342 try {
343 beans::Optional< beans::Ambiguous< sal_Bool > > option(
344 xPackage->isRegistered( uno::Reference< task::XAbortChannel >(),
345 uno::Reference< ucb::XCommandEnvironment >() ) );
346 if ( option.IsPresent )
348 ::beans::Ambiguous< sal_Bool > const & reg = option.Value;
349 if ( reg.IsAmbiguous )
350 return AMBIGUOUS;
351 else
352 return reg.Value ? REGISTERED : NOT_REGISTERED;
354 else
355 return NOT_AVAILABLE;
357 catch ( const uno::RuntimeException & ) {
358 throw;
360 catch (const uno::Exception &) {
361 TOOLS_WARN_EXCEPTION( "desktop", "" );
362 return NOT_AVAILABLE;
367 bool TheExtensionManager::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const
369 if ( m_xExtensionManager.is() && xPackage.is() )
371 return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() );
373 else
374 return true;
378 // The function investigates if the extension supports options.
379 bool TheExtensionManager::supportsOptions( const uno::Reference< deployment::XPackage > &xPackage ) const
381 bool bOptions = false;
383 if ( ! xPackage->isBundle() )
384 return false;
386 beans::Optional< OUString > aId = xPackage->getIdentifier();
388 //a bundle must always have an id
389 OSL_ASSERT( aId.IsPresent );
391 //iterate over all available nodes
392 uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames();
394 for ( int i = 0; i < seqNames.getLength(); i++ )
396 uno::Any anyNode = m_xNameAccessNodes->getByName( seqNames[i] );
397 //If we have a node then it must contain the set of leaves. This is part of OptionsDialog.xcs
398 uno::Reference< XInterface> xIntNode = anyNode.get< uno::Reference< XInterface > >();
399 uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW );
401 uno::Any anyLeaves = xNode->getByName("Leaves");
402 uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >();
403 uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW );
405 //iterate over all available leaves
406 uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames();
407 for ( int j = 0; j < seqLeafNames.getLength(); j++ )
409 uno::Any anyLeaf = xLeaves->getByName( seqLeafNames[j] );
410 uno::Reference< XInterface > xIntLeaf = anyLeaf.get< uno::Reference< XInterface > >();
411 uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW );
412 //investigate the Id property if it matches the extension identifier which
413 //has been passed in.
414 uno::Any anyValue = xLeaf->getPropertyValue("Id");
416 OUString sId = anyValue.get< OUString >();
417 if ( sId == aId.Value )
419 bOptions = true;
420 break;
423 if ( bOptions )
424 break;
426 return bOptions;
430 // XEventListener
431 void TheExtensionManager::disposing( lang::EventObject const & rEvt )
433 bool shutDown = (rEvt.Source == m_xDesktop);
435 if ( shutDown && m_xDesktop.is() )
437 m_xDesktop->removeTerminateListener( this );
438 m_xDesktop.clear();
441 if ( shutDown )
443 if ( dp_misc::office_is_running() )
445 const SolarMutexGuard guard;
446 if (m_xExtMgrDialog)
448 if (m_bExtMgrDialogExecuting)
449 m_xExtMgrDialog->response(RET_CANCEL);
450 else
452 m_xExtMgrDialog->Close();
453 m_xExtMgrDialog.reset();
456 assert(!m_xExtMgrDialog);
457 if (m_xUpdReqDialog)
458 m_xUpdReqDialog->response(RET_CANCEL);
459 assert(!m_xUpdReqDialog);
461 s_ExtMgr.clear();
465 // XTerminateListener
466 void TheExtensionManager::queryTermination( ::lang::EventObject const & )
468 DialogHelper *pDialogHelper = getDialogHelper();
470 if ( m_xExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) )
472 ToTop();
473 throw frame::TerminationVetoException(
474 "The office cannot be closed while the Extension Manager is running",
475 static_cast<frame::XTerminateListener*>(this));
477 else
479 clearModified();
480 if (m_xExtMgrDialog)
482 if (m_bExtMgrDialogExecuting)
483 m_xExtMgrDialog->response(RET_CANCEL);
484 else
486 m_xExtMgrDialog->Close();
487 m_xExtMgrDialog.reset();
490 if (m_xUpdReqDialog)
491 m_xUpdReqDialog->response(RET_CANCEL);
495 void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt )
497 disposing( rEvt );
500 // XModifyListener
501 void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ )
503 m_bModified = true;
504 getDialogHelper()->prepareChecking();
505 createPackageList();
506 getDialogHelper()->checkEntries();
510 ::rtl::Reference< TheExtensionManager > TheExtensionManager::get( const uno::Reference< uno::XComponentContext > &xContext,
511 const uno::Reference< awt::XWindow > &xParent,
512 const OUString & extensionURL )
514 if ( s_ExtMgr.is() )
516 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
517 if ( !extensionURL.isEmpty() )
518 s_ExtMgr->installPackage( extensionURL, true );
519 return s_ExtMgr;
522 ::rtl::Reference<TheExtensionManager> that( new TheExtensionManager( xParent, xContext ) );
524 const SolarMutexGuard guard;
525 if ( ! s_ExtMgr.is() )
527 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
528 s_ExtMgr = that;
531 if ( !extensionURL.isEmpty() )
532 s_ExtMgr->installPackage( extensionURL, true );
534 return s_ExtMgr;
537 } //namespace dp_gui
539 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */