LibreOffice Module desktop (master) 1
dp_extensionmanager.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
23
25#include <rtl/bootstrap.hxx>
26#include <com/sun/star/deployment/DeploymentException.hpp>
27#include <com/sun/star/deployment/XExtensionManager.hpp>
28#include <com/sun/star/deployment/thePackageManagerFactory.hpp>
29#include <com/sun/star/deployment/XPackageManager.hpp>
30#include <com/sun/star/deployment/XPackage.hpp>
31#include <com/sun/star/deployment/InstallException.hpp>
32#include <com/sun/star/deployment/VersionException.hpp>
33#include <com/sun/star/lang/IllegalArgumentException.hpp>
34#include <com/sun/star/lang/XServiceInfo.hpp>
35#include <com/sun/star/beans/Optional.hpp>
36#include <com/sun/star/task/XInteractionApprove.hpp>
37#include <com/sun/star/beans/Ambiguous.hpp>
38#include <com/sun/star/ucb/CommandAbortedException.hpp>
39#include <com/sun/star/ucb/CommandFailedException.hpp>
40#include <com/sun/star/uno/XComponentContext.hpp>
41#include <com/sun/star/io/XInputStream.hpp>
42#include <com/sun/star/util/XModifyBroadcaster.hpp>
44#include <utility>
46#include <osl/diagnose.h>
47#include <dp_interact.h>
48#include <dp_misc.h>
49#include <dp_ucb.h>
50#include <dp_identifier.hxx>
54#include "dp_properties.hxx"
55
56#include <vector>
57#include <algorithm>
58#include <set>
59#include <string_view>
60
61namespace lang = com::sun::star::lang;
62namespace task = com::sun::star::task;
63namespace ucb = com::sun::star::ucb;
64namespace uno = com::sun::star::uno;
66namespace util = com::sun::star::util;
67
68using ::com::sun::star::uno::Reference;
69
70namespace {
71
72struct CompIdentifiers
73{
74 bool operator() (std::vector<Reference<css::deployment::XPackage> > const & a,
75 std::vector<Reference<css::deployment::XPackage> > const & b)
76 {
77 return getName(a).compareTo(getName(b)) < 0;
78 }
79
80 static OUString getName(std::vector<Reference<css::deployment::XPackage> > const & a);
81};
82
83OUString CompIdentifiers::getName(std::vector<Reference<css::deployment::XPackage> > const & a)
84{
85 OSL_ASSERT(a.size() == 3);
86 //get the first non-null reference
87 Reference<css::deployment::XPackage> extension;
88 for (auto const& elem : a)
89 {
90 if (elem.is())
91 {
92 extension = elem;
93 break;
94 }
95 }
96 OSL_ASSERT(extension.is());
97 return extension->getDisplayName();
98}
99
100void writeLastModified(OUString & url, Reference<ucb::XCommandEnvironment> const & xCmdEnv, Reference< uno::XComponentContext > const & xContext)
101{
102 //Write the lastmodified file
103 try {
104 ::rtl::Bootstrap::expandMacros(url);
105 ::ucbhelper::Content ucbStamp(url, xCmdEnv, xContext);
106 dp_misc::erase_path( url, xCmdEnv );
107 OString stamp("1" );
108 Reference<css::io::XInputStream> xData(
109 ::xmlscript::createInputStream(
110 reinterpret_cast<sal_Int8 const *>(stamp.getStr()),
111 stamp.getLength() ) );
112 ucbStamp.writeStream( xData, true /* replace existing */ );
113 }
114 catch(...)
115 {
116 uno::Any exc(::cppu::getCaughtException());
117 throw css::deployment::DeploymentException("Failed to update" + url, nullptr, exc);
118 }
119}
120
121class ExtensionRemoveGuard
122{
123 css::uno::Reference<css::deployment::XPackage> m_extension;
124 css::uno::Reference<css::deployment::XPackageManager> m_xPackageManager;
125
126public:
127 ExtensionRemoveGuard(){};
128 ExtensionRemoveGuard(
129 css::uno::Reference<css::deployment::XPackage> extension,
130 css::uno::Reference<css::deployment::XPackageManager> xPackageManager):
131 m_extension(std::move(extension)), m_xPackageManager(std::move(xPackageManager)) {}
132 ~ExtensionRemoveGuard();
133
134 void set(css::uno::Reference<css::deployment::XPackage> const & extension,
135 css::uno::Reference<css::deployment::XPackageManager> const & xPackageManager) {
136 m_extension = extension;
137 m_xPackageManager = xPackageManager;
138 }
139};
140
141ExtensionRemoveGuard::~ExtensionRemoveGuard()
142{
143 try {
144 OSL_ASSERT(!(m_extension.is() && !m_xPackageManager.is()));
145 if (m_xPackageManager.is() && m_extension.is())
146 m_xPackageManager->removePackage(
148 css::uno::Reference<css::task::XAbortChannel>(),
149 css::uno::Reference<css::ucb::XCommandEnvironment>());
150 } catch (...) {
151 OSL_ASSERT(false);
152 }
153}
154
155}
156
157namespace dp_manager {
158
159//ToDo: bundled extension
161 ::cppu::WeakComponentImplHelper< css::deployment::XExtensionManager, css::lang::XServiceInfo >(m_aMutex)
163{
164 m_xPackageManagerFactory = css::deployment::thePackageManagerFactory::get(m_xContext);
165 OSL_ASSERT(m_xPackageManagerFactory.is());
166
167 m_repositoryNames.emplace_back("user");
168 m_repositoryNames.emplace_back("shared");
169 m_repositoryNames.emplace_back("bundled");
170}
171
173{
174}
175
176// XServiceInfo
178{
179 return "com.sun.star.comp.deployment.ExtensionManager";
180}
181
182sal_Bool ExtensionManager::supportsService( const OUString& ServiceName )
183{
185}
186
187css::uno::Sequence< OUString > ExtensionManager::getSupportedServiceNames()
188{
189 // a private one:
190 return { "com.sun.star.comp.deployment.ExtensionManager" };
191}
192
193Reference<css::deployment::XPackageManager> ExtensionManager::getUserRepository()
194{
195 return m_xPackageManagerFactory->getPackageManager("user");
196}
197Reference<css::deployment::XPackageManager> ExtensionManager::getSharedRepository()
198{
199 return m_xPackageManagerFactory->getPackageManager("shared");
200}
201Reference<css::deployment::XPackageManager> ExtensionManager::getBundledRepository()
202{
203 return m_xPackageManagerFactory->getPackageManager("bundled");
204}
205Reference<css::deployment::XPackageManager> ExtensionManager::getTmpRepository()
206{
207 return m_xPackageManagerFactory->getPackageManager("tmp");
208}
209Reference<css::deployment::XPackageManager> ExtensionManager::getBakRepository()
210{
211 return m_xPackageManagerFactory->getPackageManager("bak");
212}
213
214Reference<task::XAbortChannel> ExtensionManager::createAbortChannel()
215{
216 return new dp_misc::AbortChannel;
217}
218
219css::uno::Reference<css::deployment::XPackageManager>
220ExtensionManager::getPackageManager(std::u16string_view repository)
221{
222 Reference<css::deployment::XPackageManager> xPackageManager;
223 if (repository == u"user")
224 xPackageManager = getUserRepository();
225 else if (repository == u"shared")
226 xPackageManager = getSharedRepository();
227 else if (repository == u"bundled")
228 xPackageManager = getBundledRepository();
229 else if (repository == u"tmp")
230 xPackageManager = getTmpRepository();
231 else if (repository == u"bak")
232 xPackageManager = getBakRepository();
233 else
234 throw lang::IllegalArgumentException(
235 "No valid repository name provided.",
236 static_cast<cppu::OWeakObject*>(this), 0);
237 return xPackageManager;
238}
239
240/*
241 Enters the XPackage objects into a map. They must be all from the
242 same repository. The value type of the map is a vector, where each vector
243 represents an extension with a particular identifier. The first member
244 represents the user extension, the second the shared extension and the
245 third the bundled extension.
246 */
248 id2extensions & mapExt,
249 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt,
250 std::u16string_view repository)
251{
252 //Determine the index in the vector where these extensions are to be
253 //added.
254 int index = 0;
255 for (auto const& repositoryName : m_repositoryNames)
256 {
257 if (repositoryName == repository)
258 break;
259 ++index;
260 }
261
262 for (const Reference<css::deployment::XPackage>& xExtension : seqExt)
263 {
264 OUString id = dp_misc::getIdentifier(xExtension);
265 id2extensions::iterator ivec = mapExt.find(id);
266 if (ivec == mapExt.end())
267 {
268 std::vector<Reference<css::deployment::XPackage> > vec(3);
269 vec[index] = xExtension;
270 mapExt[id] = vec;
271 }
272 else
273 {
274 ivec->second[index] = xExtension;
275 }
276 }
277}
278
279/*
280 returns a list containing extensions with the same identifier from
281 all repositories (user, shared, bundled). If one repository does not
282 have this extension, then the list contains an empty Reference. The list
283 is ordered according to the priority of the repositories:
284 1. user
285 2. shared
286 3. bundled
287
288 The number of elements is always three, unless the number of repository
289 changes.
290 */
291std::vector<Reference<css::deployment::XPackage> >
293 OUString const & identifier, OUString const & fileName)
294
295{
296 std::vector<Reference<css::deployment::XPackage> > extensionList;
297 Reference<css::deployment::XPackageManager> lRepos[] = {
299 for (std::size_t i(0); i != std::size(lRepos); ++i)
300 {
301 Reference<css::deployment::XPackage> xPackage;
302 try
303 {
304 xPackage = lRepos[i]->getDeployedPackage(
305 identifier, fileName, Reference<ucb::XCommandEnvironment>());
306 }
307 catch(const lang::IllegalArgumentException &)
308 {
309 // thrown if the extension does not exist in this repository
310 }
311 extensionList.push_back(xPackage);
312 }
313 OSL_ASSERT(extensionList.size() == 3);
314 return extensionList;
315}
316
319 OUString const & identifier,
320 OUString const & fileName,
321 Reference< ucb::XCommandEnvironment> const & /*xCmdEnv*/ )
322{
323 try
324 {
325 std::vector<Reference<css::deployment::XPackage> > listExtensions =
327 bool bHasExtension = false;
328
329 //throw an IllegalArgumentException if there is no extension at all.
330 for (auto const& extension : listExtensions)
331 bHasExtension |= extension.is();
332 if (!bHasExtension)
333 throw lang::IllegalArgumentException(
334 "Could not find extension: " + identifier + ", " + fileName,
335 static_cast<cppu::OWeakObject*>(this), -1);
336
337 return comphelper::containerToSequence(listExtensions);
338 }
339 catch ( const css::deployment::DeploymentException & )
340 {
341 throw;
342 }
343 catch ( const ucb::CommandFailedException & )
344 {
345 throw;
346 }
347 catch (css::uno::RuntimeException &)
348 {
349 throw;
350 }
351 catch (...)
352 {
353 uno::Any exc = ::cppu::getCaughtException();
354 throw css::deployment::DeploymentException(
355 "Extension Manager: exception during getExtensionsWithSameIdentifier",
356 static_cast<OWeakObject*>(this), exc);
357 }
358}
359
361 OUString const & identifier, OUString const & fileName)
362{
363 std::vector<Reference<css::deployment::XPackage> > listExtensions;
364
365 try {
366 listExtensions = getExtensionsWithSameId(identifier, fileName);
367 } catch ( const lang::IllegalArgumentException & ) {
368 }
369 OSL_ASSERT(listExtensions.size() == 3);
370
371 return isUserDisabled( ::comphelper::containerToSequence(listExtensions) );
372}
373
375 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExtSameId)
376{
377 OSL_ASSERT(seqExtSameId.getLength() == 3);
378 Reference<css::deployment::XPackage> const & userExtension = seqExtSameId[0];
379 if (userExtension.is())
380 {
381 beans::Optional<beans::Ambiguous<sal_Bool> > reg =
382 userExtension->isRegistered(Reference<task::XAbortChannel>(),
383 Reference<ucb::XCommandEnvironment>());
384 //If the value is ambiguous, then we assume that the extension
385 //is enabled, but something went wrong during enabling. We do not
386 //automatically disable user extensions.
387 if (reg.IsPresent &&
388 ! reg.Value.IsAmbiguous && ! reg.Value.Value)
389 return true;
390 }
391 return false;
392}
393
394/*
395 This method determines the active extension (XPackage.registerPackage) with a
396 particular identifier.
397
398 The parameter bUserDisabled determines if the user extension is disabled.
399
400 When the user repository contains an extension with the given identifier and
401 it is not disabled by the user, then it is always registered. Otherwise an
402 extension is only registered when there is no registered extension in one of
403 the repositories with a higher priority. That is, if the extension is from
404 the shared repository and an active extension with the same identifier is in
405 the user repository, then the extension is not registered. Similarly a
406 bundled extension is not registered if there is an active extension with the
407 same identifier in the shared or user repository.
408*/
410 OUString const & identifier, OUString const & fileName,
411 bool bUserDisabled,
412 bool bStartup,
413 Reference<task::XAbortChannel> const & xAbortChannel,
414 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
415{
416 std::vector<Reference<css::deployment::XPackage> > listExtensions;
417 try {
418 listExtensions = getExtensionsWithSameId(identifier, fileName);
419 } catch (const lang::IllegalArgumentException &) {
420 }
421 OSL_ASSERT(listExtensions.size() == 3);
422
424 ::comphelper::containerToSequence(listExtensions),
425 bUserDisabled, bStartup, xAbortChannel, xCmdEnv);
426
427 fireModified();
428}
429
431 uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt,
432 bool bUserDisabled,
433 bool bStartup,
434 Reference<task::XAbortChannel> const & xAbortChannel,
435 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
436{
437 bool bActive = false;
438 sal_Int32 len = seqExt.getLength();
439 for (sal_Int32 i = 0; i < len; i++)
440 {
441 Reference<css::deployment::XPackage> const & aExt = seqExt[i];
442 if (aExt.is())
443 {
444 //get the registration value of the current iteration
445 beans::Optional<beans::Ambiguous<sal_Bool> > optReg =
446 aExt->isRegistered(xAbortChannel, xCmdEnv);
447 //If nothing can be registered then break
448 if (!optReg.IsPresent)
449 break;
450
451 //Check if this is a disabled user extension,
452 if (i == 0 && bUserDisabled)
453 {
454 aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
455 continue;
456 }
457
458 //If we have already determined an active extension then we must
459 //make sure to unregister all extensions with the same id in
460 //repositories with a lower priority
461 if (bActive)
462 {
463 aExt->revokePackage(bStartup, xAbortChannel, xCmdEnv);
464 }
465 else
466 {
467 //This is the first extension in the ordered list, which becomes
468 //the active extension
469 bActive = true;
470 //Register if not already done.
471 //reregister if the value is ambiguous, which indicates that
472 //something went wrong during last registration.
473 aExt->registerPackage(bStartup, xAbortChannel, xCmdEnv);
474 }
475 }
476 }
477}
478
479Reference<css::deployment::XPackage> ExtensionManager::backupExtension(
480 OUString const & identifier, OUString const & fileName,
481 Reference<css::deployment::XPackageManager> const & xPackageManager,
482 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
483{
484 Reference<css::deployment::XPackage> xBackup;
485 Reference<ucb::XCommandEnvironment> tmpCmdEnv(
486 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
487 Reference<css::deployment::XPackage> xOldExtension = xPackageManager->getDeployedPackage(
488 identifier, fileName, tmpCmdEnv);
489
490 if (xOldExtension.is())
491 {
492 xBackup = getTmpRepository()->addPackage(
493 xOldExtension->getURL(), uno::Sequence<beans::NamedValue>(),
494 OUString(), Reference<task::XAbortChannel>(), tmpCmdEnv);
495
496 OSL_ENSURE(xBackup.is(), "Failed to backup extension");
497 }
498 return xBackup;
499}
500
501//The supported package types are actually determined by the registry. However
502//creating a registry
503//(desktop/source/deployment/registry/dp_registry.cxx:PackageRegistryImpl) will
504//create all the backends, so that the registry can obtain from them the package
505//types. Creating the registry will also set up the registry folder containing
506//all the subfolders for the respective backends.
507//Because all repositories support the same backends, we can just delegate this
508//call to one of the repositories.
511{
512 return getUserRepository()->getSupportedPackageTypes();
513}
514//Do some necessary checks and user interaction. This function does not
515//acquire the extension manager mutex and that mutex must not be acquired
516//when this function is called. doChecksForAddExtension does synchronous
517//user interactions which may require acquiring the solar mutex.
518//Returns true if the extension can be installed.
520 Reference<css::deployment::XPackageManager> const & xPackageMgr,
522 css::uno::Reference<css::deployment::XPackage> const & xTmpExtension,
523 Reference<task::XAbortChannel> const & xAbortChannel,
524 Reference<ucb::XCommandEnvironment> const & xCmdEnv,
525 Reference<css::deployment::XPackage> & out_existingExtension )
526{
527 try
528 {
529 Reference<css::deployment::XPackage> xOldExtension;
530 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
531 const OUString sFileName = xTmpExtension->getName();
532 const OUString sDisplayName = xTmpExtension->getDisplayName();
533 const OUString sVersion = xTmpExtension->getVersion();
534
535 try
536 {
537 xOldExtension = xPackageMgr->getDeployedPackage(
538 sIdentifier, sFileName, xCmdEnv);
539 out_existingExtension = xOldExtension;
540 }
541 catch (const lang::IllegalArgumentException &)
542 {
543 }
544 bool bCanInstall = false;
545
546 //This part is not guarded against other threads removing, adding, disabling ...
547 //etc. the same extension.
548 //checkInstall is safe because it notifies the user if the extension is not yet
549 //installed in the same repository. Because addExtension has its own guard
550 //(m_addMutex), another thread cannot add the extension in the meantime.
551 //checkUpdate is called if the same extension exists in the same
552 //repository. The user is asked if they want to replace it. Another
553 //thread
554 //could already remove the extension. So asking the user was not
555 //necessary. No harm is done. The other thread may also ask the user
556 //if he wants to remove the extension. This depends on the
557 //XCommandEnvironment which it passes to removeExtension.
558 if (xOldExtension.is())
559 {
560 //throws a CommandFailedException if the user cancels
561 //the action.
562 checkUpdate(sVersion, sDisplayName,xOldExtension, xCmdEnv);
563 }
564 else
565 {
566 //throws a CommandFailedException if the user cancels
567 //the action.
568 checkInstall(sDisplayName, xCmdEnv);
569 }
570 //Prevent showing the license if requested.
571 Reference<ucb::XCommandEnvironment> _xCmdEnv(xCmdEnv);
572 ExtensionProperties props(std::u16string_view(), properties, Reference<ucb::XCommandEnvironment>(), m_xContext);
573
574 dp_misc::DescriptionInfoset info(dp_misc::getDescriptionInfoset(xTmpExtension->getURL()));
575 const ::std::optional<dp_misc::SimpleLicenseAttributes> licenseAttributes =
577
578 if (licenseAttributes && licenseAttributes->suppressIfRequired
579 && props.isSuppressedLicense())
580 _xCmdEnv.set(new NoLicenseCommandEnv(xCmdEnv->getInteractionHandler()));
581
582 bCanInstall = xTmpExtension->checkPrerequisites(
583 xAbortChannel, _xCmdEnv, xOldExtension.is() || props.isExtensionUpdate()) == 0;
584
585 return bCanInstall;
586 }
587 catch ( const css::deployment::DeploymentException& ) {
588 throw;
589 } catch ( const ucb::CommandFailedException & ) {
590 throw;
591 } catch ( const ucb::CommandAbortedException & ) {
592 throw;
593 } catch (const lang::IllegalArgumentException &) {
594 throw;
595 } catch (const uno::RuntimeException &) {
596 throw;
597 } catch (const uno::Exception &) {
598 uno::Any excOccurred = ::cppu::getCaughtException();
599 css::deployment::DeploymentException exc(
600 "Extension Manager: exception in doChecksForAddExtension",
601 static_cast<OWeakObject*>(this), excOccurred);
602 throw exc;
603 } catch (...) {
604 throw uno::RuntimeException(
605 "Extension Manager: unexpected exception in doChecksForAddExtension",
606 static_cast<OWeakObject*>(this));
607 }
608}
609
610// Only add to shared and user repository
611Reference<css::deployment::XPackage> ExtensionManager::addExtension(
612 OUString const & url, uno::Sequence<beans::NamedValue> const & properties,
613 OUString const & repository,
614 Reference<task::XAbortChannel> const & xAbortChannel,
615 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
616{
617 Reference<css::deployment::XPackage> xNewExtension;
618 //Determine the repository to use
619 Reference<css::deployment::XPackageManager> xPackageManager;
620 if (repository == "user")
621 xPackageManager = getUserRepository();
622 else if (repository == "shared")
623 xPackageManager = getSharedRepository();
624 else
625 throw lang::IllegalArgumentException(
626 "No valid repository name provided.",
627 static_cast<cppu::OWeakObject*>(this), 0);
628 //We must make sure that the xTmpExtension is not create twice, because this
629 //would remove the first one.
630 std::unique_lock addGuard(m_addMutex);
631
632 Reference<css::deployment::XPackageManager> xTmpRepository(getTmpRepository());
633 // make sure xTmpRepository is alive as long as xTmpExtension is; as
634 // the "tmp" manager is only held weakly by m_xPackageManagerFactory, it
635 // could otherwise be disposed early, which would in turn dispose
636 // xTmpExtension's PackageRegistryBackend behind its back
637 Reference<css::deployment::XPackage> xTmpExtension(
638 xTmpRepository->addPackage(
639 url, uno::Sequence<beans::NamedValue>(), OUString(), xAbortChannel,
641 if (!xTmpExtension.is()) {
642 throw css::deployment::DeploymentException(
643 ("Extension Manager: Failed to create temporary XPackage for url: "
644 + url),
645 static_cast<OWeakObject*>(this), uno::Any());
646 }
647
648 //Make sure the extension is removed from the tmp repository in case
649 //of an exception
650 ExtensionRemoveGuard tmpExtensionRemoveGuard(xTmpExtension, getTmpRepository());
651 ExtensionRemoveGuard bakExtensionRemoveGuard;
652 const OUString sIdentifier = dp_misc::getIdentifier(xTmpExtension);
653 const OUString sFileName = xTmpExtension->getName();
654 Reference<css::deployment::XPackage> xOldExtension;
655 Reference<css::deployment::XPackage> xExtensionBackup;
656
657 uno::Any excOccurred2;
658 bool bCanInstall = doChecksForAddExtension(
659 xPackageManager,
661 xTmpExtension,
662 xAbortChannel,
663 xCmdEnv,
664 xOldExtension );
665
666 {
667 bool bUserDisabled = false;
668 // In this guarded section (getMutex) we must not use the argument xCmdEnv
669 // because it may bring up dialogs (XInteractionHandler::handle) this
670 // may potentially deadlock. See issue
671 // http://qa.openoffice.org/issues/show_bug.cgi?id=114933
672 // By not providing xCmdEnv the underlying APIs will throw an exception if
673 // the XInteractionRequest cannot be handled.
674 ::osl::MutexGuard guard(m_aMutex);
675
676 if (bCanInstall)
677 {
678 try
679 {
680 bUserDisabled = isUserDisabled(sIdentifier, sFileName);
681 if (xOldExtension.is())
682 {
683 try
684 {
685 xOldExtension->revokePackage(
686 false, xAbortChannel, Reference<ucb::XCommandEnvironment>());
687 //save the old user extension in case the user aborts
688 xExtensionBackup = getBakRepository()->importExtension(
689 xOldExtension, Reference<task::XAbortChannel>(),
690 Reference<ucb::XCommandEnvironment>());
691 bakExtensionRemoveGuard.set(xExtensionBackup, getBakRepository());
692 }
693 catch (const lang::DisposedException &)
694 {
695 //Another thread might have removed the extension meanwhile
696 }
697 }
698 //check again dependencies but prevent user interaction,
699 //We can disregard the license, because the user must have already
700 //accepted it, when we called checkPrerequisites the first time
703
704 sal_Int32 failedPrereq = xTmpExtension->checkPrerequisites(
705 xAbortChannel, pSilentCommandEnv, true);
706 if (failedPrereq == 0)
707 {
708 xNewExtension = xPackageManager->addPackage(
709 url, properties, OUString(), xAbortChannel,
710 Reference<ucb::XCommandEnvironment>());
711 //If we add a user extension and there is already one which was
712 //disabled by a user, then the newly installed one is enabled. If we
713 //add to another repository then the user extension remains
714 //disabled.
715 bool bUserDisabled2 = bUserDisabled;
716 if (repository == "user")
717 bUserDisabled2 = false;
718
719 // pass the two values via variables to workaround gcc-4.3.4 specific bug (bnc#655912)
720 OUString sNewExtensionIdentifier = dp_misc::getIdentifier(xNewExtension);
721 OUString sNewExtensionFileName = xNewExtension->getName();
722
724 sNewExtensionIdentifier, sNewExtensionFileName,
725 bUserDisabled2, false, xAbortChannel,
726 Reference<ucb::XCommandEnvironment>());
727
728 // if reached this section,
729 // this means that either the licensedialog.ui didn't popup,
730 // or user accepted the license agreement. otherwise
731 // no need to call fireModified() because user declined
732 // the license agreement therefore no change made.
733 try
734 {
735 fireModified();
736
737 }catch ( const css::deployment::DeploymentException& ) {
738 throw;
739 } catch ( const ucb::CommandFailedException & ) {
740 throw;
741 } catch ( const ucb::CommandAbortedException & ) {
742 throw;
743 } catch (const lang::IllegalArgumentException &) {
744 throw;
745 } catch (const uno::RuntimeException &) {
746 throw;
747 } catch (const uno::Exception &) {
748 uno::Any excOccurred = ::cppu::getCaughtException();
749 css::deployment::DeploymentException exc(
750 "Extension Manager: Exception on fireModified() "
751 "in the scope of 'if (failedPrereq == 0)'",
752 static_cast<OWeakObject*>(this), excOccurred);
753 throw exc;
754 } catch (...) {
755 throw uno::RuntimeException(
756 "Extension Manager: RuntimeException on fireModified() "
757 "in the scope of 'if (failedPrereq == 0)'",
758 static_cast<OWeakObject*>(this));
759 }
760 }
761 else
762 {
763 if (pSilentCommandEnv->m_Exception.hasValue())
764 ::cppu::throwException(pSilentCommandEnv->m_Exception);
765 else if ( pSilentCommandEnv->m_UnknownException.hasValue())
766 ::cppu::throwException(pSilentCommandEnv->m_UnknownException);
767 else
768 throw css::deployment::DeploymentException (
769 "Extension Manager: exception during addExtension, ckeckPrerequisites failed",
770 static_cast<OWeakObject*>(this), uno::Any());
771 }
772 }
773 catch ( const css::deployment::DeploymentException& ) {
774 excOccurred2 = ::cppu::getCaughtException();
775 } catch ( const ucb::CommandFailedException & ) {
776 excOccurred2 = ::cppu::getCaughtException();
777 } catch ( const ucb::CommandAbortedException & ) {
778 excOccurred2 = ::cppu::getCaughtException();
779 } catch (const lang::IllegalArgumentException &) {
780 excOccurred2 = ::cppu::getCaughtException();
781 } catch (const uno::RuntimeException &) {
782 excOccurred2 = ::cppu::getCaughtException();
783 } catch (...) {
784 excOccurred2 = ::cppu::getCaughtException();
785 css::deployment::DeploymentException exc(
786 "Extension Manager: exception during addExtension, url: "
787 + url, static_cast<OWeakObject*>(this), excOccurred2);
788 excOccurred2 <<= exc;
789 }
790 }
791
792 if (excOccurred2.hasValue())
793 {
794 //It does not matter what exception is thrown. We try to
795 //recover the original status.
796 //If the user aborted installation then a ucb::CommandAbortedException
797 //is thrown.
798 //Use a private AbortChannel so the user cannot interrupt.
799 try
800 {
801 if (xExtensionBackup.is())
802 {
803 xPackageManager->importExtension(
804 xExtensionBackup, Reference<task::XAbortChannel>(),
805 Reference<ucb::XCommandEnvironment>());
806 }
808 sIdentifier, sFileName, bUserDisabled, false,
809 Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
810 }
811 catch (...)
812 {
813 }
814 ::cppu::throwException(excOccurred2);
815 }
816 } // leaving the guarded section (getMutex())
817
818 return xNewExtension;
819}
820
822 OUString const & identifier, OUString const & fileName,
823 OUString const & repository,
824 Reference<task::XAbortChannel> const & xAbortChannel,
825 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
826{
827 uno::Any excOccurred1;
828 Reference<css::deployment::XPackage> xExtensionBackup;
829 Reference<css::deployment::XPackageManager> xPackageManager;
830 bool bUserDisabled = false;
831 ::osl::MutexGuard guard(m_aMutex);
832 try
833 {
834//Determine the repository to use
835 if (repository == "user")
836 xPackageManager = getUserRepository();
837 else if (repository == "shared")
838 xPackageManager = getSharedRepository();
839 else
840 throw lang::IllegalArgumentException(
841 "No valid repository name provided.",
842 static_cast<cppu::OWeakObject*>(this), 0);
843
844 bUserDisabled = isUserDisabled(identifier, fileName);
845 //Backup the extension, in case the user cancels the action
846 xExtensionBackup = backupExtension(
847 identifier, fileName, xPackageManager, xCmdEnv);
848
849 //revoke the extension if it is active
850 Reference<css::deployment::XPackage> xOldExtension =
851 xPackageManager->getDeployedPackage(
852 identifier, fileName, xCmdEnv);
853 xOldExtension->revokePackage(false, xAbortChannel, xCmdEnv);
854
855 xPackageManager->removePackage(
856 identifier, fileName, xAbortChannel, xCmdEnv);
857 activateExtension(identifier, fileName, bUserDisabled, false,
858 xAbortChannel, xCmdEnv);
859 fireModified();
860 }
861 catch ( const css::deployment::DeploymentException& ) {
862 excOccurred1 = ::cppu::getCaughtException();
863 } catch ( const ucb::CommandFailedException & ) {
864 excOccurred1 = ::cppu::getCaughtException();
865 } catch ( const ucb::CommandAbortedException & ) {
866 excOccurred1 = ::cppu::getCaughtException();
867 } catch (const lang::IllegalArgumentException &) {
868 excOccurred1 = ::cppu::getCaughtException();
869 } catch (const uno::RuntimeException &) {
870 excOccurred1 = ::cppu::getCaughtException();
871 } catch (...) {
872 excOccurred1 = ::cppu::getCaughtException();
873 css::deployment::DeploymentException exc(
874 "Extension Manager: exception during removeExtension",
875 static_cast<OWeakObject*>(this), excOccurred1);
876 excOccurred1 <<= exc;
877 }
878
879 if (excOccurred1.hasValue())
880 {
881 //User aborted installation, restore the previous situation.
882 //Use a private AbortChannel so the user cannot interrupt.
883 try
884 {
885 Reference<ucb::XCommandEnvironment> tmpCmdEnv(
886 new TmpRepositoryCommandEnv(xCmdEnv->getInteractionHandler()));
887 if (xExtensionBackup.is())
888 {
889 xPackageManager->importExtension(
890 xExtensionBackup, Reference<task::XAbortChannel>(),
891 tmpCmdEnv);
893 identifier, fileName, bUserDisabled, false,
894 Reference<task::XAbortChannel>(),
895 tmpCmdEnv);
896
897 getTmpRepository()->removePackage(
898 dp_misc::getIdentifier(xExtensionBackup),
899 xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
900 fireModified();
901 }
902 }
903 catch (...)
904 {
905 }
906 ::cppu::throwException(excOccurred1);
907 }
908
909 if (xExtensionBackup.is())
910 getTmpRepository()->removePackage(
911 dp_misc::getIdentifier(xExtensionBackup),
912 xExtensionBackup->getName(), xAbortChannel, xCmdEnv);
913}
914
915// Only enable extensions from shared and user repository
917 Reference<css::deployment::XPackage> const & extension,
918 Reference<task::XAbortChannel> const & xAbortChannel,
919 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
920{
921 ::osl::MutexGuard guard(m_aMutex);
922 bool bUserDisabled = false;
923 uno::Any excOccurred;
924 try
925 {
926 if (!extension.is())
927 return;
928 OUString repository = extension->getRepositoryName();
929 if (repository != "user")
930 throw lang::IllegalArgumentException(
931 "No valid repository name provided.",
932 static_cast<cppu::OWeakObject*>(this), 0);
933
934 bUserDisabled = isUserDisabled(dp_misc::getIdentifier(extension),
935 extension->getName());
936
938 extension->getName(), false, false,
939 xAbortChannel, xCmdEnv);
940 }
941 catch ( const css::deployment::DeploymentException& ) {
942 excOccurred = ::cppu::getCaughtException();
943 } catch ( const ucb::CommandFailedException & ) {
944 excOccurred = ::cppu::getCaughtException();
945 } catch ( const ucb::CommandAbortedException & ) {
946 excOccurred = ::cppu::getCaughtException();
947 } catch (const lang::IllegalArgumentException &) {
948 excOccurred = ::cppu::getCaughtException();
949 } catch (const uno::RuntimeException &) {
950 excOccurred = ::cppu::getCaughtException();
951 } catch (...) {
952 excOccurred = ::cppu::getCaughtException();
953 css::deployment::DeploymentException exc(
954 "Extension Manager: exception during enableExtension",
955 static_cast<OWeakObject*>(this), excOccurred);
956 excOccurred <<= exc;
957 }
958
959 if (!excOccurred.hasValue())
960 return;
961
962 try
963 {
965 extension->getName(), bUserDisabled, false,
966 xAbortChannel, xCmdEnv);
967 }
968 catch (...)
969 {
970 }
971 ::cppu::throwException(excOccurred);
972}
973
975 Reference<css::deployment::XPackage> const & extension,
976 Reference<task::XAbortChannel> const & xAbortChannel,
977 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
978{
979 try
980 {
981 if (!extension.is())
982 return 0;
983 ::osl::MutexGuard guard(m_aMutex);
984 sal_Int32 ret = 0;
985 Reference<css::deployment::XPackageManager> mgr =
986 getPackageManager(extension->getRepositoryName());
987 ret = mgr->checkPrerequisites(extension, xAbortChannel, xCmdEnv);
988 if (ret)
989 {
990 //There are some unfulfilled prerequisites, try to revoke
991 extension->revokePackage(false, xAbortChannel, xCmdEnv);
992 }
993 const OUString id(dp_misc::getIdentifier(extension));
994 activateExtension(id, extension->getName(),
995 isUserDisabled(id, extension->getName()), false,
996 xAbortChannel, xCmdEnv);
997 return ret;
998 }
999 catch ( const css::deployment::DeploymentException& ) {
1000 throw;
1001 } catch ( const ucb::CommandFailedException & ) {
1002 throw;
1003 } catch ( const ucb::CommandAbortedException & ) {
1004 throw;
1005 } catch (const lang::IllegalArgumentException &) {
1006 throw;
1007 } catch (const uno::RuntimeException &) {
1008 throw;
1009 } catch (...) {
1010 uno::Any excOccurred = ::cppu::getCaughtException();
1011 css::deployment::DeploymentException exc(
1012 "Extension Manager: exception during disableExtension",
1013 static_cast<OWeakObject*>(this), excOccurred);
1014 throw exc;
1015 }
1016}
1017
1019 Reference<css::deployment::XPackage> const & extension,
1020 Reference<task::XAbortChannel> const & xAbortChannel,
1021 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1022{
1023 ::osl::MutexGuard guard(m_aMutex);
1024 uno::Any excOccurred;
1025 bool bUserDisabled = false;
1026 try
1027 {
1028 if (!extension.is())
1029 return;
1030 const OUString repository( extension->getRepositoryName());
1031 if (repository != "user")
1032 throw lang::IllegalArgumentException(
1033 "No valid repository name provided.",
1034 static_cast<cppu::OWeakObject*>(this), 0);
1035
1036 const OUString id(dp_misc::getIdentifier(extension));
1037 bUserDisabled = isUserDisabled(id, extension->getName());
1038
1039 activateExtension(id, extension->getName(), true, false,
1040 xAbortChannel, xCmdEnv);
1041 }
1042 catch ( const css::deployment::DeploymentException& ) {
1043 excOccurred = ::cppu::getCaughtException();
1044 } catch ( const ucb::CommandFailedException & ) {
1045 excOccurred = ::cppu::getCaughtException();
1046 } catch ( const ucb::CommandAbortedException & ) {
1047 excOccurred = ::cppu::getCaughtException();
1048 } catch (const lang::IllegalArgumentException &) {
1049 excOccurred = ::cppu::getCaughtException();
1050 } catch (const uno::RuntimeException &) {
1051 excOccurred = ::cppu::getCaughtException();
1052 } catch (...) {
1053 excOccurred = ::cppu::getCaughtException();
1054 css::deployment::DeploymentException exc(
1055 "Extension Manager: exception during disableExtension",
1056 static_cast<OWeakObject*>(this), excOccurred);
1057 excOccurred <<= exc;
1058 }
1059
1060 if (!excOccurred.hasValue())
1061 return;
1062
1063 try
1064 {
1066 extension->getName(), bUserDisabled, false,
1067 xAbortChannel, xCmdEnv);
1068 }
1069 catch (...)
1070 {
1071 }
1072 ::cppu::throwException(excOccurred);
1073}
1074
1077 OUString const & repository,
1078 Reference<task::XAbortChannel> const &xAbort,
1079 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1080{
1081 return getPackageManager(repository)->getDeployedPackages(
1082 xAbort, xCmdEnv);
1083}
1084
1085Reference<css::deployment::XPackage>
1087 OUString const & repository,
1088 OUString const & identifier,
1089 OUString const & filename,
1090 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1091{
1092 return getPackageManager(repository)->getDeployedPackage(
1093 identifier, filename, xCmdEnv);
1094}
1095
1098 Reference<task::XAbortChannel> const & xAbort,
1099 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1100{
1101 try
1102 {
1103 id2extensions mapExt;
1104
1106 getUserRepository()->getDeployedPackages(xAbort, xCmdEnv);
1107 addExtensionsToMap(mapExt, userExt, u"user");
1109 getSharedRepository()->getDeployedPackages(xAbort, xCmdEnv);
1110 addExtensionsToMap(mapExt, sharedExt, u"shared");
1112 getBundledRepository()->getDeployedPackages(xAbort, xCmdEnv);
1113 addExtensionsToMap(mapExt, bundledExt, u"bundled");
1114
1115 // Create the tmp repository to trigger its clean up (deletion
1116 // of old temporary data.)
1118
1119 //copy the values of the map to a vector for sorting
1120 std::vector< std::vector<Reference<css::deployment::XPackage> > >
1121 vecExtensions;
1122 for (auto const& elem : mapExt)
1123 vecExtensions.push_back(elem.second);
1124
1125 //sort the element according to the identifier
1126 std::sort(vecExtensions.begin(), vecExtensions.end(), CompIdentifiers());
1127
1128 sal_Int32 j = 0;
1130 auto seqSeqRange = asNonConstRange(seqSeq);
1131 for (auto const& elem : vecExtensions)
1132 {
1133 seqSeqRange[j++] = comphelper::containerToSequence(elem);
1134 }
1135 return seqSeq;
1136
1137 } catch ( const css::deployment::DeploymentException& ) {
1138 throw;
1139 } catch ( const ucb::CommandFailedException & ) {
1140 throw;
1141 } catch ( const ucb::CommandAbortedException & ) {
1142 throw;
1143 } catch (const lang::IllegalArgumentException &) {
1144 throw;
1145 } catch (const uno::RuntimeException &) {
1146 throw;
1147 } catch (...) {
1148 uno::Any exc = ::cppu::getCaughtException();
1149 throw css::deployment::DeploymentException(
1150 "Extension Manager: exception during enableExtension",
1151 static_cast<OWeakObject*>(this), exc);
1152 }
1153}
1154
1155// Only to be called from unopkg or soffice bootstrap (with force=true in the
1156// latter case):
1158 sal_Bool force, OUString const & repository,
1159 Reference<task::XAbortChannel> const & xAbortChannel,
1160 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1161{
1162 try
1163 {
1164 Reference<css::deployment::XPackageManager>
1165 xPackageManager = getPackageManager(repository);
1166
1167 std::set< OUString > disabledExts;
1168 {
1170 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1171 for ( const Reference<css::deployment::XPackage>& package : extensions )
1172 {
1173 try
1174 {
1175 beans::Optional< beans::Ambiguous< sal_Bool > > registered(
1176 package->isRegistered(xAbortChannel, xCmdEnv));
1177 if (registered.IsPresent &&
1178 !(registered.Value.IsAmbiguous ||
1179 registered.Value.Value))
1180 {
1181 const OUString id = dp_misc::getIdentifier(package);
1182 OSL_ASSERT(!id.isEmpty());
1183 disabledExts.insert(id);
1184 }
1185 }
1186 catch (const lang::DisposedException &)
1187 {
1188 }
1189 }
1190 }
1191
1192 ::osl::MutexGuard guard(m_aMutex);
1193 xPackageManager->reinstallDeployedPackages(
1194 force, xAbortChannel, xCmdEnv);
1195 //We must sync here, otherwise we will get exceptions when extensions
1196 //are removed.
1197 dp_misc::syncRepositories(force, xCmdEnv);
1199 xPackageManager->getDeployedPackages(xAbortChannel, xCmdEnv));
1200
1201 for ( const Reference<css::deployment::XPackage>& package : extensions )
1202 {
1203 try
1204 {
1205 const OUString id = dp_misc::getIdentifier(package);
1206 const OUString fileName = package->getName();
1207 OSL_ASSERT(!id.isEmpty());
1209 id, fileName, disabledExts.find(id) != disabledExts.end(),
1210 true, xAbortChannel, xCmdEnv );
1211 }
1212 catch (const lang::DisposedException &)
1213 {
1214 }
1215 }
1216 } catch ( const css::deployment::DeploymentException& ) {
1217 throw;
1218 } catch ( const ucb::CommandFailedException & ) {
1219 throw;
1220 } catch ( const ucb::CommandAbortedException & ) {
1221 throw;
1222 } catch (const lang::IllegalArgumentException &) {
1223 throw;
1224 } catch (const uno::RuntimeException &) {
1225 throw;
1226 } catch (...) {
1227 uno::Any exc = ::cppu::getCaughtException();
1228 throw css::deployment::DeploymentException(
1229 "Extension Manager: exception during enableExtension",
1230 static_cast<OWeakObject*>(this), exc);
1231 }
1232}
1233
1235 Reference<task::XAbortChannel> const & xAbortChannel,
1236 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1237{
1238 try
1239 {
1240 ::osl::MutexGuard guard(m_aMutex);
1241 OUString sSynchronizingShared(StrSyncRepository());
1242 sSynchronizingShared = sSynchronizingShared.replaceAll("%NAME", "shared");
1243 dp_misc::ProgressLevel progressShared(xCmdEnv, sSynchronizingShared);
1244 bool bModified = getSharedRepository()->synchronize(xAbortChannel, xCmdEnv);
1245 progressShared.update("\n\n");
1246
1247 OUString sSynchronizingBundled(StrSyncRepository());
1248 sSynchronizingBundled = sSynchronizingBundled.replaceAll("%NAME", "bundled");
1249 dp_misc::ProgressLevel progressBundled(xCmdEnv, sSynchronizingBundled);
1250 bModified |= static_cast<bool>(getBundledRepository()->synchronize(xAbortChannel, xCmdEnv));
1251 progressBundled.update("\n\n");
1252
1253 //Always determine the active extension.
1254 //TODO: Is this still necessary? (It used to be necessary for the
1255 // first-start optimization: The setup created the registration data
1256 // for the bundled extensions (share/prereg/bundled) which was copied to
1257 // the user installation when a user started OOo for the first time
1258 // after running setup. All bundled extensions were registered at that
1259 // moment. However, extensions with the same identifier could be in the
1260 // shared or user repository, in which case the respective bundled
1261 // extensions had to be revoked.)
1262 try
1263 {
1265 seqSeqExt = getAllExtensions(xAbortChannel, xCmdEnv);
1266 for (uno::Sequence<Reference<css::deployment::XPackage> > const & seqExt : seqSeqExt)
1267 {
1268 activateExtension(seqExt, isUserDisabled(seqExt), true,
1269 xAbortChannel, xCmdEnv);
1270 }
1271 }
1272 catch (...)
1273 {
1274 //We catch the exception, so we can write the lastmodified file
1275 //so we will no repeat this every time OOo starts.
1276 OSL_FAIL("Extensions Manager: synchronize");
1277 }
1278 OUString lastSyncBundled("$BUNDLED_EXTENSIONS_USER/lastsynchronized");
1279 writeLastModified(lastSyncBundled, xCmdEnv, m_xContext);
1280 OUString lastSyncShared("$SHARED_EXTENSIONS_USER/lastsynchronized");
1281 writeLastModified(lastSyncShared, xCmdEnv, m_xContext);
1282 return bModified;
1283 } catch ( const css::deployment::DeploymentException& ) {
1284 throw;
1285 } catch ( const ucb::CommandFailedException & ) {
1286 throw;
1287 } catch ( const ucb::CommandAbortedException & ) {
1288 throw;
1289 } catch (const lang::IllegalArgumentException &) {
1290 throw;
1291 } catch (const uno::RuntimeException &) {
1292 throw;
1293 } catch (...) {
1294 uno::Any exc = ::cppu::getCaughtException();
1295 throw css::deployment::DeploymentException(
1296 "Extension Manager: exception in synchronize",
1297 static_cast<OWeakObject*>(this), exc);
1298 }
1299}
1300
1301// Notify the user when a new extension is to be installed. This is only the
1302// case when one uses the system integration to install an extension (double
1303// clicking on .oxt file etc.)). The function must only be called if there is no
1304// extension with the same identifier already deployed. Then the checkUpdate
1305// function will inform the user that the extension is about to be installed In
1306// case the user cancels the installation a CommandFailed exception is
1307// thrown.
1309 OUString const & displayName,
1310 Reference<ucb::XCommandEnvironment> const & cmdEnv)
1311{
1312 uno::Any request(
1313 css::deployment::InstallException(
1314 "Extension " + displayName +
1315 " is about to be installed.",
1316 static_cast<OWeakObject *>(this), displayName));
1317 bool approve = false, abort = false;
1320 cmdEnv, &approve, &abort ))
1321 {
1322 OSL_ASSERT( !approve && !abort );
1323 throw css::deployment::DeploymentException(
1324 DpResId(RID_STR_ERROR_WHILE_ADDING) + displayName,
1325 static_cast<OWeakObject *>(this), request );
1326 }
1327 if (abort || !approve)
1328 throw ucb::CommandFailedException(
1329 DpResId(RID_STR_ERROR_WHILE_ADDING) + displayName,
1330 static_cast<OWeakObject *>(this), request );
1331}
1332
1333/* The function will make the user interaction in case there is an extension
1334installed with the same id. This function may only be called if there is already
1335an extension.
1336*/
1338 OUString const & newVersion,
1339 OUString const & newDisplayName,
1340 Reference<css::deployment::XPackage> const & oldExtension,
1341 Reference<ucb::XCommandEnvironment> const & xCmdEnv )
1342{
1343 // package already deployed, interact --force:
1344 uno::Any request(
1345 (css::deployment::VersionException(
1346 DpResId(
1347 RID_STR_PACKAGE_ALREADY_ADDED ) + newDisplayName,
1348 static_cast<OWeakObject *>(this), newVersion, newDisplayName,
1349 oldExtension ) ) );
1350 bool replace = false, abort = false;
1353 xCmdEnv, &replace, &abort )) {
1354 OSL_ASSERT( !replace && !abort );
1355 throw css::deployment::DeploymentException(
1356 DpResId(
1357 RID_STR_ERROR_WHILE_ADDING) + newDisplayName,
1358 static_cast<OWeakObject *>(this), request );
1359 }
1360 if (abort || !replace)
1361 throw ucb::CommandFailedException(
1362 DpResId(
1363 RID_STR_PACKAGE_ALREADY_ADDED) + newDisplayName,
1364 static_cast<OWeakObject *>(this), request );
1365}
1366
1369 OUString const & repository,
1370 Reference<ucb::XCommandEnvironment> const & xCmdEnv)
1371{
1372 Reference<css::deployment::XPackageManager>
1373 xPackageManager = getPackageManager(repository);
1374 ::osl::MutexGuard guard(m_aMutex);
1375 return xPackageManager->getExtensionsWithUnacceptedLicenses(xCmdEnv);
1376}
1377
1379{
1380 return getPackageManager(repository)->isReadOnly();
1381}
1382
1383
1384// XModifyBroadcaster
1385
1387 Reference<util::XModifyListener> const & xListener )
1388{
1389 check();
1390 rBHelper.addListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
1391}
1392
1393
1395 Reference<util::XModifyListener> const & xListener )
1396{
1397 check();
1398 rBHelper.removeListener( cppu::UnoType<decltype(xListener)>::get(), xListener );
1399}
1400
1402{
1403 ::osl::MutexGuard guard( m_aMutex );
1404 if (rBHelper.bInDispose || rBHelper.bDisposed) {
1405 throw lang::DisposedException(
1406 "ExtensionManager instance has already been disposed!",
1407 static_cast<OWeakObject *>(this) );
1408 }
1409}
1410
1412{
1413 ::cppu::OInterfaceContainerHelper * pContainer = rBHelper.getContainer(
1415 if (pContainer != nullptr) {
1416 pContainer->forEach<util::XModifyListener>(
1417 [this] (uno::Reference<util::XModifyListener> const& xListener)
1418 { return xListener->modified(lang::EventObject(static_cast<OWeakObject *>(this))); });
1419 }
1420}
1421
1422} // namespace dp_manager
1423
1424
1425extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface*
1427 css::uno::XComponentContext* context, css::uno::Sequence<css::uno::Any> const& )
1428{
1429 return cppu::acquire(new dp_manager::ExtensionManager(context));
1430}
1431
1432/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
mutable::osl::Mutex m_aMutex
void forEach(FuncT const &func)
virtual css::uno::Sequence< css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > > SAL_CALL getAllExtensions(css::uno::Reference< css::task::XAbortChannel > const &, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual void SAL_CALL removeExtension(OUString const &identifier, OUString const &filename, OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual css::uno::Reference< css::task::XAbortChannel > SAL_CALL createAbortChannel() override
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > SAL_CALL getExtensionsWithSameIdentifier(OUString const &identifier, OUString const &filename, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual sal_Bool SAL_CALL synchronize(css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual css::uno::Reference< css::deployment::XPackage > SAL_CALL getDeployedExtension(OUString const &repository, OUString const &identifier, OUString const &filename, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override
css::uno::Reference< css::uno::XComponentContext > m_xContext
css::uno::Reference< css::deployment::XPackageManager > getTmpRepository()
virtual sal_Bool SAL_CALL isReadOnlyRepository(OUString const &repository) override
css::uno::Reference< css::deployment::XPackageManagerFactory > m_xPackageManagerFactory
css::uno::Reference< css::deployment::XPackageManager > getSharedRepository()
void checkUpdate(OUString const &newVersion, OUString const &newDisplayName, css::uno::Reference< css::deployment::XPackage > const &oldExtension, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv)
virtual void SAL_CALL disableExtension(css::uno::Reference< css::deployment::XPackage > const &extension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual OUString SAL_CALL getImplementationName() override
css::uno::Reference< css::deployment::XPackageManager > getBundledRepository()
void addExtensionsToMap(id2extensions &mapExt, css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > const &seqExt, std::u16string_view repository)
css::uno::Reference< css::deployment::XPackageManager > getUserRepository()
bool doChecksForAddExtension(css::uno::Reference< css::deployment::XPackageManager > const &xPackageMgr, css::uno::Sequence< css::beans::NamedValue > const &properties, css::uno::Reference< css::deployment::XPackage > const &xTmpExtension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, css::uno::Reference< css::deployment::XPackage > &out_existingExtension)
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > SAL_CALL getExtensionsWithUnacceptedLicenses(OUString const &repository, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
css::uno::Reference< css::deployment::XPackageManager > getBakRepository()
css::uno::Reference< css::deployment::XPackage > backupExtension(OUString const &identifier, OUString const &fileName, css::uno::Reference< css::deployment::XPackageManager > const &xPackageManager, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv)
std::vector< css::uno::Reference< css::deployment::XPackage > > getExtensionsWithSameId(OUString const &identifier, OUString const &fileName)
bool isUserDisabled(OUString const &identifier, OUString const &filename)
void activateExtension(OUString const &identifier, OUString const &fileName, bool bUserDisabled, bool bStartup, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv)
virtual void SAL_CALL addModifyListener(css::uno::Reference< css::util::XModifyListener > const &xListener) override
css::uno::Reference< css::deployment::XPackageManager > getPackageManager(std::u16string_view repository)
virtual void SAL_CALL enableExtension(css::uno::Reference< css::deployment::XPackage > const &extension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackageTypeInfo > > SAL_CALL getSupportedPackageTypes() override
virtual void SAL_CALL removeModifyListener(css::uno::Reference< css::util::XModifyListener > const &xListener) override
virtual css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > SAL_CALL getDeployedExtensions(OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
ExtensionManager(css::uno::Reference< css::uno::XComponentContext >const &xContext)
std::vector< OUString > m_repositoryNames
virtual sal_Int32 SAL_CALL checkPrerequisitesAndEnable(css::uno::Reference< css::deployment::XPackage > const &extension, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
void checkInstall(OUString const &displayName, css::uno::Reference< css::ucb::XCommandEnvironment > const &cmdEnv)
virtual css::uno::Reference< css::deployment::XPackage > SAL_CALL addExtension(OUString const &url, css::uno::Sequence< css::beans::NamedValue > const &properties, OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
virtual sal_Bool SAL_CALL supportsService(const OUString &ServiceName) override
virtual void SAL_CALL reinstallDeployedExtensions(sal_Bool force, OUString const &repository, css::uno::Reference< css::task::XAbortChannel > const &xAbortChannel, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv) override
this class is for use in XPackageManager::checkPrerequisites
Access to the content of an XML description element.
::std::optional< SimpleLicenseAttributes > getSimpleLicenseAttributes() const
returns the attributes of the simple-license element
void update(OUString const &status) const
Definition: dp_interact.h:80
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_deployment_ExtensionManager_get_implementation(css::uno::XComponentContext *context, css::uno::Sequence< css::uno::Any > const &)
uno::Reference< uno::XComponentContext > m_xContext
const uno::Reference< deployment::XPackage > m_extension
OUString DpResId(TranslateId aId)
Definition: dp_misc.cxx:555
float u
OUString sDisplayName
std::mutex m_aMutex
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2642
uno_Any a
void set(css::uno::UnoInterfaceReference const &value)
css::uno::Sequence< DstElementType > containerToSequence(const SrcType &i_Container)
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
std::unordered_map< OUString, std::vector< css::uno::Reference< css::deployment::XPackage > > > id2extensions
void syncRepositories(bool force, Reference< ucb::XCommandEnvironment > const &xCmdEnv)
Definition: dp_misc.cxx:491
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool interactContinuation(css::uno::Any const &request, css::uno::Type const &continuation, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool *pcont, bool *pabort)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC bool erase_path(OUString const &url, css::uno::Reference< css::ucb::XCommandEnvironment > const &xCmdEnv, bool throw_exc=true)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC DescriptionInfoset getDescriptionInfoset(std::u16string_view sExtensionFolderURL)
creates a DescriptionInfoset object.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
int i
index
dictionary props
::boost::spirit::classic::rule< ScannerT > identifier
bool hasValue()
unsigned char sal_Bool
signed char sal_Int8