LibreOffice Module desktop (master) 1
dp_gui_theextmgr.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <utility>
21#include <vcl/svapp.hxx>
22
23#include <com/sun/star/beans/XPropertySet.hpp>
24#include <com/sun/star/configuration/theDefaultProvider.hpp>
25#include <com/sun/star/deployment/DeploymentException.hpp>
26#include <com/sun/star/deployment/ExtensionManager.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>
34#include <osl/diagnose.h>
36
37#include "dp_gui_dialog2.hxx"
39#include "dp_gui_theextmgr.hxx"
40#include <dp_misc.h>
41#include <dp_update.hxx>
42
43constexpr OUStringLiteral USER_PACKAGE_MANAGER = u"user";
44constexpr OUStringLiteral SHARED_PACKAGE_MANAGER = u"shared";
45
46using namespace ::com::sun::star;
47
48namespace dp_gui {
49
50
52
53
54// TheExtensionManager
55
56
60 m_xParent(std::move( xParent )),
61 m_bModified(false),
62 m_bExtMgrDialogExecuting(false)
63{
64 m_xExtensionManager = deployment::ExtensionManager::get( xContext );
65 m_xExtensionManager->addModifyListener( this );
66
68 configuration::theDefaultProvider::get(xContext));
70 {
71 {"nodepath", uno::Any(OUString("/org.openoffice.Office.OptionsDialog/Nodes"))}
72 }));
74 xConfig->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", args),
75 uno::UNO_QUERY_THROW);
76
77 // get the 'get more extensions here' url
79 {
80 {"nodepath", uno::Any(OUString("/org.openoffice.Office.ExtensionManager/ExtensionRepositories"))}
81 }));
82 uno::Reference< container::XNameAccess > xNameAccessRepositories;
83 xNameAccessRepositories.set(
84 xConfig->createInstanceWithArguments( "com.sun.star.configuration.ConfigurationAccess", args2),
85 uno::UNO_QUERY_THROW);
86 try
87 { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
88 uno::Any value = xNameAccessRepositories->getByName("WebsiteLink");
89 m_sGetExtensionsURL = value.get< OUString > ();
90 }
91 catch ( const uno::Exception& )
92 {}
93
95 {
96 // the registration should be done after the construction has been ended
97 // otherwise an exception prevents object creation, but it is registered as a listener
98 m_xDesktop.set( frame::Desktop::create(xContext), uno::UNO_SET_THROW );
99 m_xDesktop->addTerminateListener( this );
100 }
101}
102
104{
105 if (m_xUpdReqDialog)
106 m_xUpdReqDialog->response(RET_CANCEL);
107 assert(!m_xUpdReqDialog);
108 if (m_xExtMgrDialog)
109 {
111 m_xExtMgrDialog->response(RET_CANCEL);
112 else
113 {
114 m_xExtMgrDialog->Close();
115 m_xExtMgrDialog.reset();
116 }
117 }
118 assert(!m_xExtMgrDialog);
119}
120
121void TheExtensionManager::createDialog( const bool bCreateUpdDlg )
122{
123 const SolarMutexGuard guard;
124
125 if ( bCreateUpdDlg )
126 {
127 if ( !m_xUpdReqDialog )
128 {
132 }
133 }
134 else if ( !m_xExtMgrDialog )
135 {
136 m_xExtMgrDialog = std::make_shared<ExtMgrDialog>(Application::GetFrameWeld(m_xParent), this);
138 m_xExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL );
140 }
141}
142
144{
145 const SolarMutexGuard guard;
146
148
149 weld::DialogController::runAsync(m_xExtMgrDialog, [this](sal_Int32 /*nResult*/) {
151 auto xExtMgrDialog = m_xExtMgrDialog;
152 m_xExtMgrDialog.reset();
153 xExtMgrDialog->Close();
154 });
155}
156
157void TheExtensionManager::SetText( const OUString &rTitle )
158{
159 const SolarMutexGuard guard;
160
161 getDialog()->set_title( rTitle );
162}
163
164
166{
167 const SolarMutexGuard guard;
168
169 getDialog()->present();
170}
171
173{
174 if (m_xExtMgrDialog)
175 {
177 m_xExtMgrDialog->response(RET_CANCEL);
178 else
179 m_xExtMgrDialog->Close();
180 }
181 else if (m_xUpdReqDialog)
182 m_xUpdReqDialog->response(RET_CANCEL);
183}
184
186{
187 sal_Int16 nRet = 0;
188
189 if ( m_xUpdReqDialog )
190 {
191 nRet = m_xUpdReqDialog->run();
192 m_xUpdReqDialog.reset();
193 }
194
195 return nRet;
196}
197
199{
200 weld::Window* pDialog = getDialog();
201 return pDialog && pDialog->get_visible();
202}
203
205{
206 std::vector< uno::Reference< deployment::XPackage > > vEntries;
208
209 try {
210 xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
212 } catch ( const deployment::DeploymentException & ) {
213 return;
214 } catch ( const ucb::CommandFailedException & ) {
215 return;
216 } catch ( const ucb::CommandAbortedException & ) {
217 return;
218 } catch ( const lang::IllegalArgumentException & e ) {
219 css::uno::Any anyEx = cppu::getCaughtException();
220 throw css::lang::WrappedTargetRuntimeException( e.Message,
221 e.Context, anyEx );
222 }
223
224 for ( auto const & i : std::as_const(xAllPackages) )
225 {
227 OSL_ASSERT(xPackage.is());
228 if ( xPackage.is() )
229 {
230 vEntries.push_back( xPackage );
231 }
232 }
233
234 m_xExecuteCmdQueue->checkForUpdates( std::move(vEntries) );
235}
236
237
238bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser )
239{
240 if ( rPackageURL.isEmpty() )
241 return false;
242
243 createDialog( false );
244
245 bool bInstall = true;
246 bool bInstallForAll = false;
247
248 // DV! missing function is read only repository from extension manager
249 if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) )
250 bInstall = getDialogHelper()->installForAllUsers( bInstallForAll );
251
252 if ( !bInstall )
253 return false;
254
255 if ( bInstallForAll )
256 m_xExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false );
257 else
258 m_xExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser );
259
260 return true;
261}
262
263
265{
267 return;
268
269 const SolarMutexGuard guard;
270 if (m_xExtMgrDialog)
271 {
273 m_xExtMgrDialog->response(RET_CANCEL);
274 else
275 {
276 m_xExtMgrDialog->Close();
277 m_xExtMgrDialog.reset();
278 }
279 }
280 assert(!m_xExtMgrDialog);
281 if (m_xUpdReqDialog)
282 m_xUpdReqDialog->response(RET_CANCEL);
283 assert(!m_xUpdReqDialog);
285}
286
287
289{
291
292 try {
293 xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
295 } catch ( const deployment::DeploymentException & ) {
296 return;
297 } catch ( const ucb::CommandFailedException & ) {
298 return;
299 } catch ( const ucb::CommandAbortedException & ) {
300 return;
301 } catch ( const lang::IllegalArgumentException & e ) {
302 css::uno::Any anyEx = cppu::getCaughtException();
303 throw css::lang::WrappedTargetRuntimeException( e.Message,
304 e.Context, anyEx );
305 }
306
307 for ( uno::Sequence< uno::Reference< deployment::XPackage > > const & xPackageList : std::as_const(xAllPackages) )
308 {
309 for ( uno::Reference< deployment::XPackage > const & xPackage : xPackageList )
310 {
311 if ( xPackage.is() )
312 {
313 PackageState eState = getPackageState( xPackage );
314 getDialogHelper()->addPackageToList( xPackage );
315 // When the package is enabled, we can stop here, otherwise we have to look for
316 // another version of this package
317 if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) )
318 break;
319 }
320 }
321 }
322
323 const uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER,
325 for ( uno::Reference< deployment::XPackage > const & xPackage : xNoLicPackages )
326 {
327 if ( xPackage.is() )
328 {
329 getDialogHelper()->addPackageToList( xPackage, true );
330 }
331 }
332}
333
334
336{
337 try {
338 beans::Optional< beans::Ambiguous< sal_Bool > > option(
339 xPackage->isRegistered( uno::Reference< task::XAbortChannel >(),
341 if ( option.IsPresent )
342 {
343 ::beans::Ambiguous< sal_Bool > const & reg = option.Value;
344 if ( reg.IsAmbiguous )
345 return AMBIGUOUS;
346 else
347 return reg.Value ? REGISTERED : NOT_REGISTERED;
348 }
349 else
350 return NOT_AVAILABLE;
351 }
352 catch ( const uno::RuntimeException & ) {
353 throw;
354 }
355 catch (const uno::Exception &) {
356 TOOLS_WARN_EXCEPTION( "desktop", "" );
357 return NOT_AVAILABLE;
358 }
359}
360
361
363{
364 if ( m_xExtensionManager.is() && xPackage.is() )
365 {
366 return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() );
367 }
368 else
369 return true;
370}
371
372
373// The function investigates if the extension supports options.
375{
376 bool bOptions = false;
377
378 if ( ! xPackage->isBundle() )
379 return false;
380
381 beans::Optional< OUString > aId = xPackage->getIdentifier();
382
383 //a bundle must always have an id
384 OSL_ASSERT( aId.IsPresent );
385
386 //iterate over all available nodes
387 const uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames();
388
389 for ( OUString const & nodeName : seqNames )
390 {
391 uno::Any anyNode = m_xNameAccessNodes->getByName( nodeName );
392 //If we have a node then it must contain the set of leaves. This is part of OptionsDialog.xcs
394 uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW );
395
396 uno::Any anyLeaves = xNode->getByName("Leaves");
397 uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >();
398 uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW );
399
400 //iterate over all available leaves
401 const uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames();
402 for ( OUString const & leafName : seqLeafNames )
403 {
404 uno::Any anyLeaf = xLeaves->getByName( leafName );
406 uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW );
407 //investigate the Id property if it matches the extension identifier which
408 //has been passed in.
409 uno::Any anyValue = xLeaf->getPropertyValue("Id");
410
411 OUString sId = anyValue.get< OUString >();
412 if ( sId == aId.Value )
413 {
414 bOptions = true;
415 break;
416 }
417 }
418 if ( bOptions )
419 break;
420 }
421 return bOptions;
422}
423
424
425// XEventListener
426void TheExtensionManager::disposing( lang::EventObject const & rEvt )
427{
428 bool shutDown = (rEvt.Source == m_xDesktop);
429
430 if ( shutDown && m_xDesktop.is() )
431 {
432 m_xDesktop->removeTerminateListener( this );
433 m_xDesktop.clear();
434 }
435
436 if ( !shutDown )
437 return;
438
440 {
441 const SolarMutexGuard guard;
442 if (m_xExtMgrDialog)
443 {
445 m_xExtMgrDialog->response(RET_CANCEL);
446 else
447 {
448 m_xExtMgrDialog->Close();
449 m_xExtMgrDialog.reset();
450 }
451 }
452 assert(!m_xExtMgrDialog);
453 if (m_xUpdReqDialog)
454 m_xUpdReqDialog->response(RET_CANCEL);
455 assert(!m_xUpdReqDialog);
456 }
457 s_ExtMgr.clear();
458}
459
460// XTerminateListener
461void TheExtensionManager::queryTermination( ::lang::EventObject const & )
462{
463 DialogHelper *pDialogHelper = getDialogHelper();
464
465 if ( m_xExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) )
466 {
467 ToTop();
468 throw frame::TerminationVetoException(
469 "The office cannot be closed while the Extension Manager is running",
470 static_cast<frame::XTerminateListener*>(this));
471 }
472 else
473 {
475 if (m_xExtMgrDialog)
476 {
478 m_xExtMgrDialog->response(RET_CANCEL);
479 else
480 {
481 m_xExtMgrDialog->Close();
482 m_xExtMgrDialog.reset();
483 }
484 }
485 if (m_xUpdReqDialog)
486 m_xUpdReqDialog->response(RET_CANCEL);
487 }
488}
489
490void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt )
491{
492 disposing( rEvt );
493}
494
495// XModifyListener
496void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ )
497{
498 m_bModified = true;
499 DialogHelper *pDialogHelper = getDialogHelper();
500 if (!pDialogHelper)
501 return;
502 pDialogHelper->prepareChecking();
504 pDialogHelper->checkEntries();
505}
506
507
509 const uno::Reference< awt::XWindow > &xParent,
510 const OUString & extensionURL )
511{
512 if ( s_ExtMgr.is() )
513 {
514 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
515 if ( !extensionURL.isEmpty() )
516 s_ExtMgr->installPackage( extensionURL, true );
517 return s_ExtMgr;
518 }
519
521
522 const SolarMutexGuard guard;
523 if ( ! s_ExtMgr.is() )
524 {
525 OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
526 s_ExtMgr = that;
527 }
528
529 if ( !extensionURL.isEmpty() )
530 s_ExtMgr->installPackage( extensionURL, true );
531
532 return s_ExtMgr;
533}
534
535} //namespace dp_gui
536
537/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
static weld::Window * GetFrameWeld(const css::uno::Reference< css::awt::XWindow > &rWindow)
static void Quit()
bool installForAllUsers(bool &bInstallForAll)
virtual void addPackageToList(const css::uno::Reference< css::deployment::XPackage > &xPackage, bool bLicenseMissing=false)=0
virtual void prepareChecking()=0
virtual void checkEntries()=0
Manages installing of extensions in the GUI mode.
css::uno::Reference< css::deployment::XExtensionManager > m_xExtensionManager
void SetText(const OUString &rTitle)
static ::rtl::Reference< TheExtensionManager > get(css::uno::Reference< css::uno::XComponentContext > const &xContext, css::uno::Reference< css::awt::XWindow > const &xParent=nullptr, OUString const &view=OUString())
css::uno::Reference< css::container::XNameAccess > m_xNameAccessNodes
bool installPackage(const OUString &rPackageURL, bool bWarnUser=false)
virtual void SAL_CALL notifyTermination(css::lang::EventObject const &evt) override
std::shared_ptr< ExtMgrDialog > m_xExtMgrDialog
static PackageState getPackageState(const css::uno::Reference< css::deployment::XPackage > &xPackage)
css::uno::Reference< css::awt::XWindow > m_xParent
static ::rtl::Reference< TheExtensionManager > s_ExtMgr
virtual void SAL_CALL queryTermination(css::lang::EventObject const &evt) override
std::unique_ptr< ExtensionCmdQueue > m_xExecuteCmdQueue
css::uno::Reference< css::uno::XComponentContext > m_xContext
bool isReadOnly(const css::uno::Reference< css::deployment::XPackage > &xPackage) const
std::unique_ptr< UpdateRequiredDialog > m_xUpdReqDialog
TheExtensionManager(css::uno::Reference< css::awt::XWindow > xParent, const css::uno::Reference< css::uno::XComponentContext > &xContext)
virtual void SAL_CALL disposing(css::lang::EventObject const &evt) override
bool supportsOptions(const css::uno::Reference< css::deployment::XPackage > &xPackage) const
virtual ~TheExtensionManager() override
void createDialog(const bool bCreateUpdDlg)
virtual void SAL_CALL modified(css::lang::EventObject const &evt) override
css::uno::Reference< css::frame::XDesktop2 > m_xDesktop
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
virtual bool get_visible() const=0
virtual void present()=0
virtual void set_title(const OUString &rTitle)=0
Any value
#define TOOLS_WARN_EXCEPTION(area, stream)
uno::Reference< uno::XComponentContext > m_xContext
constexpr OUStringLiteral SHARED_PACKAGE_MANAGER
constexpr OUStringLiteral USER_PACKAGE_MANAGER
float u
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2638
css::uno::Sequence< css::uno::Any > InitAnyPropertySequence(::std::initializer_list< ::std::pair< OUString, css::uno::Any > > vInit)
Any SAL_CALL getCaughtException()
Definition: dp_gui.h:22
PackageState
Definition: dp_gui.h:24
@ AMBIGUOUS
Definition: dp_gui.h:24
@ REGISTERED
Definition: dp_gui.h:24
@ NOT_REGISTERED
Definition: dp_gui.h:24
@ NOT_AVAILABLE
Definition: dp_gui.h:24
constexpr OUStringLiteral SHARED_PACKAGE_MANAGER
constexpr OUStringLiteral USER_PACKAGE_MANAGER
bool office_is_running()
Definition: dp_misc.cxx:332
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Reference< css::deployment::XPackage > getExtensionWithHighestVersion(css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > const &seqExtensionsWithSameId)
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)
int i
args
JCOPY_OPTION option
OUString sId
RET_CANCEL