LibreOffice Module desktop (master) 1
dp_update.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 <config_folders.h>
21
22#include <dp_update.hxx>
23#include <dp_version.hxx>
24#include <dp_identifier.hxx>
26
27#include <com/sun/star/ucb/CommandAbortedException.hpp>
28#include <com/sun/star/ucb/CommandFailedException.hpp>
29#include <osl/diagnose.h>
30#include <rtl/bootstrap.hxx>
31#include <sal/log.hxx>
32
33using namespace ::com::sun::star;
34using namespace ::com::sun::star::uno;
35
36
37namespace dp_misc {
38namespace {
39
40int determineHighestVersion(
41 OUString const & userVersion,
42 OUString const & sharedVersion,
43 OUString const & bundledVersion,
44 std::u16string_view onlineVersion)
45{
46 int index = 0;
47 OUString greatest = userVersion;
48 if (dp_misc::compareVersions(sharedVersion, greatest) == dp_misc::GREATER)
49 {
50 index = 1;
51 greatest = sharedVersion;
52 }
53 if (dp_misc::compareVersions(bundledVersion, greatest) == dp_misc::GREATER)
54 {
55 index = 2;
56 greatest = bundledVersion;
57 }
58 if (dp_misc::compareVersions(onlineVersion, greatest) == dp_misc::GREATER)
59 {
60 index = 3;
61 }
62 return index;
63}
64
65Sequence< Reference< xml::dom::XElement > >
66getUpdateInformation( Reference<deployment::XUpdateInformationProvider > const & updateInformation,
67 Sequence< OUString > const & urls,
68 OUString const & identifier,
69 uno::Any & out_error)
70{
71 try {
72 return updateInformation->getUpdateInformation(urls, identifier);
73 } catch (const uno::RuntimeException &) {
74 throw;
75 } catch (const ucb::CommandFailedException & e) {
76 out_error = e.Reason;
77 } catch (const ucb::CommandAbortedException &) {
78 } catch (const uno::Exception & e) {
79 out_error <<= e;
80 }
81 return
82 Sequence<Reference< xml::dom::XElement > >();
83}
84
85void getOwnUpdateInfos(
86 Reference<uno::XComponentContext> const & xContext,
87 Reference<deployment::XUpdateInformationProvider > const & updateInformation,
88 UpdateInfoMap& inout_map, std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors,
89 bool & out_allFound)
90{
91 bool bAllHaveOwnUpdateInformation = true;
92 for (auto & inout : inout_map)
93 {
94 OSL_ASSERT(inout.second.extension.is());
95 Sequence<OUString> urls(inout.second.extension->getUpdateInformationURLs());
96 if (urls.hasElements())
97 {
98 const OUString search_id = dp_misc::getIdentifier(inout.second.extension);
99 SAL_INFO( "extensions.update", "Searching update for " << search_id );
100 uno::Any anyError;
101 //It is unclear from the idl if there can be a null reference returned.
102 //However all valid information should be the same
103 const Sequence<Reference< xml::dom::XElement > >
104 infos(getUpdateInformation(updateInformation, urls, search_id, anyError));
105 if (anyError.hasValue())
106 out_errors.emplace_back(inout.second.extension, anyError);
107
108 for (const Reference< xml::dom::XElement >& element : infos)
109 {
111 xContext,
112 Reference< xml::dom::XNode >(element, UNO_QUERY_THROW));
113 if (!infoset.hasDescription())
114 continue;
115 std::optional< OUString > result_id(infoset.getIdentifier());
116 if (!result_id)
117 continue;
118 SAL_INFO( "extensions.update", " found version "
119 << infoset.getVersion() << " for " << *result_id );
120 if (*result_id != search_id)
121 continue;
122 inout.second.version = infoset.getVersion();
123 inout.second.info.set(element, UNO_QUERY_THROW);
124 break;
125 }
126 }
127 else
128 {
129 bAllHaveOwnUpdateInformation = false;
130 }
131 }
132 out_allFound = bAllHaveOwnUpdateInformation;
133}
134
135void getDefaultUpdateInfos(
136 Reference<uno::XComponentContext> const & xContext,
137 Reference<deployment::XUpdateInformationProvider > const & updateInformation,
138 UpdateInfoMap& inout_map,
139 std::vector<std::pair<Reference<deployment::XPackage>, uno::Any> > & out_errors)
140{
141 const OUString sDefaultURL(dp_misc::getExtensionDefaultUpdateURL());
142 OSL_ASSERT(!sDefaultURL.isEmpty());
143
144 Any anyError;
145 const Sequence< Reference< xml::dom::XElement > >
146 infos(
147 getUpdateInformation(
148 updateInformation,
149 Sequence< OUString >(&sDefaultURL, 1), OUString(), anyError));
150 if (anyError.hasValue())
151 out_errors.emplace_back(Reference<deployment::XPackage>(), anyError);
152 for (const Reference< xml::dom::XElement >& element : infos)
153 {
154 Reference< xml::dom::XNode > node(element, UNO_QUERY_THROW);
156 std::optional< OUString > id(infoset.getIdentifier());
157 if (!id) {
158 continue;
159 }
160 UpdateInfoMap::iterator j = inout_map.find(*id);
161 if (j != inout_map.end())
162 {
163 //skip those extension which provide its own update urls
164 if (j->second.extension->getUpdateInformationURLs().getLength())
165 continue;
166 OUString v(infoset.getVersion());
167 //look for the highest version in the online repository
168 if (dp_misc::compareVersions(v, j->second.version) ==
170 {
171 j->second.version = v;
172 j->second.info = node;
173 }
174 }
175 }
176}
177
178bool containsBundledOnly(Sequence<Reference<deployment::XPackage> > const & sameIdExtensions)
179{
180 OSL_ASSERT(sameIdExtensions.getLength() == 3);
181 return !sameIdExtensions[0].is() && !sameIdExtensions[1].is() && sameIdExtensions[2].is();
182}
183
188bool onlyBundledExtensions(
189 Reference<deployment::XExtensionManager> const & xExtMgr,
190 std::vector< Reference<deployment::XPackage > > const * extensionList)
191{
192 OSL_ASSERT(xExtMgr.is());
193 bool bOnlyBundled = true;
194 if (extensionList)
195 {
196 for (auto const& elem : *extensionList)
197 {
198 Sequence<Reference<deployment::XPackage> > seqExt = xExtMgr->getExtensionsWithSameIdentifier(
199 dp_misc::getIdentifier(elem), elem->getName(), Reference<ucb::XCommandEnvironment>());
200
201 bOnlyBundled = containsBundledOnly(seqExt);
202 if (!bOnlyBundled)
203 break;
204 }
205 }
206 else
207 {
209 xExtMgr->getAllExtensions(Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
210
211 for (int pos(0), nLen(seqAllExt.getLength()); bOnlyBundled && pos != nLen; ++pos)
212 {
213 bOnlyBundled = containsBundledOnly(seqAllExt[pos]);
214 }
215 }
216 return bOnlyBundled;
217}
218
219} // anon namespace
220
221
223{
224 OUString sUrl(
225 "${$BRAND_BASE_DIR/" LIBO_ETC_FOLDER "/" SAL_CONFIGFILE("version")
226 ":Version:ExtensionUpdateURL}");
227 ::rtl::Bootstrap::expandMacros(sUrl);
228 return sUrl;
229}
230
231/* returns the index of the greatest version, starting with 0
232
233 */
235 bool bReadOnlyShared,
236 OUString const & userVersion,
237 OUString const & sharedVersion,
238 OUString const & bundledVersion,
239 std::u16string_view onlineVersion)
240{
242 if (bReadOnlyShared)
243 {
244 if (!userVersion.isEmpty())
245 {
246 int index = determineHighestVersion(
247 userVersion, sharedVersion, bundledVersion, onlineVersion);
248 if (index == 1)
249 retVal = UPDATE_SOURCE_SHARED;
250 else if (index == 2)
251 retVal = UPDATE_SOURCE_BUNDLED;
252 else if (index == 3)
253 retVal = UPDATE_SOURCE_ONLINE;
254 }
255 else if (!sharedVersion.isEmpty())
256 {
257 int index = determineHighestVersion(
258 OUString(), sharedVersion, bundledVersion, onlineVersion);
259 if (index == 2)
260 retVal = UPDATE_SOURCE_BUNDLED;
261 else if (index == 3)
262 retVal = UPDATE_SOURCE_ONLINE;
263
264 }
265 }
266 else
267 {
268 if (!userVersion.isEmpty())
269 {
270 int index = determineHighestVersion(
271 userVersion, sharedVersion, bundledVersion, onlineVersion);
272 if (index == 1)
273 retVal = UPDATE_SOURCE_SHARED;
274 else if (index == 2)
275 retVal = UPDATE_SOURCE_BUNDLED;
276 else if (index == 3)
277 retVal = UPDATE_SOURCE_ONLINE;
278 }
279 }
280
281 return retVal;
282}
283
285 bool bReadOnlyShared,
286 OUString const & sharedVersion,
287 OUString const & bundledVersion,
288 std::u16string_view onlineVersion)
289{
290 if (bReadOnlyShared)
291 return UPDATE_SOURCE_NONE;
293
294 if (!sharedVersion.isEmpty())
295 {
296 int index = determineHighestVersion(
297 OUString(), sharedVersion, bundledVersion, onlineVersion);
298 if (index == 2)
299 retVal = UPDATE_SOURCE_BUNDLED;
300 else if (index == 3)
301 retVal = UPDATE_SOURCE_ONLINE;
302 }
303 return retVal;
304}
305
306Reference<deployment::XPackage>
308 Sequence<Reference<deployment::XPackage> > const & seqExt)
309{
310 if (!seqExt.hasElements())
311 return Reference<deployment::XPackage>();
312
313 Reference<deployment::XPackage> greatest;
314 sal_Int32 len = seqExt.getLength();
315
316 for (sal_Int32 i = 0; i < len; i++)
317 {
318 if (!greatest.is())
319 {
320 greatest = seqExt[i];
321 continue;
322 }
323 Reference<deployment::XPackage> const & current = seqExt[i];
324 //greatest has a value
325 if (! current.is())
326 continue;
327
328 if (dp_misc::compareVersions(current->getVersion(), greatest->getVersion()) == dp_misc::GREATER)
329 greatest = current;
330 }
331 return greatest;
332}
333
334UpdateInfo::UpdateInfo( Reference< deployment::XPackage> const & ext):
335extension(ext)
336{
337}
338
339
341 Reference<uno::XComponentContext> const &xContext,
342 Reference<deployment::XExtensionManager> const & xExtMgr,
343 Reference<deployment::XUpdateInformationProvider > const & updateInformation,
344 std::vector<Reference<deployment::XPackage > > const * extensionList,
345 std::vector<std::pair< Reference<deployment::XPackage>, uno::Any> > & out_errors)
346{
347 OSL_ASSERT(xExtMgr.is());
348 UpdateInfoMap infoMap;
349 if (!xExtMgr.is() || onlyBundledExtensions(xExtMgr, extensionList))
350 return infoMap;
351
352 if (!extensionList)
353 {
354 const uno::Sequence< uno::Sequence< Reference<deployment::XPackage > > > seqAllExt = xExtMgr->getAllExtensions(
355 Reference<task::XAbortChannel>(), Reference<ucb::XCommandEnvironment>());
356
357 //fill the UpdateInfoMap. key = extension identifier, value = UpdateInfo
358 for (int pos = seqAllExt.getLength(); pos --; )
359 {
360 uno::Sequence<Reference<deployment::XPackage> > const & seqExt = seqAllExt[pos];
361
362 Reference<deployment::XPackage> extension = getExtensionWithHighestVersion(seqExt);
363 OSL_ASSERT(extension.is());
364
365 std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.emplace(
366 dp_misc::getIdentifier(extension), UpdateInfo(extension));
367 OSL_ASSERT(insertRet.second);
368 }
369 }
370 else
371 {
372 for (auto const& elem : *extensionList)
373 {
374 OSL_ASSERT(elem.is());
375 std::pair<UpdateInfoMap::iterator, bool> insertRet = infoMap.emplace(
377 OSL_ASSERT(insertRet.second);
378 }
379 }
380
381 //Now find the update information for the extensions which provide their own
382 //URLs to update information.
383 bool bAllInfosObtained = false;
384 getOwnUpdateInfos(xContext, updateInformation, infoMap, out_errors, bAllInfosObtained);
385
386 if (!bAllInfosObtained)
387 getDefaultUpdateInfos(xContext, updateInformation, infoMap, out_errors);
388 return infoMap;
389}
391 OUString const & sharedVersion,
392 OUString const & bundledVersion,
393 OUString const & onlineVersion)
394{
395 int index = determineHighestVersion(OUString(), sharedVersion, bundledVersion, onlineVersion);
396 switch (index)
397 {
398 case 1: return sharedVersion;
399 case 2: return bundledVersion;
400 case 3: return onlineVersion;
401 default: OSL_ASSERT(false);
402 }
403
404 return OUString();
405}
406} //namespace dp_misc
407
408/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Access to the content of an XML description element.
#define SAL_CONFIGFILE(name)
float v
static uno::Reference< css::uno::XComponentContext > xContext
Definition: init.cxx:2642
#define SAL_INFO(area, stream)
std::map< OUString, UpdateInfo > UpdateInfoMap
Definition: dp_update.hxx:100
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getExtensionDefaultUpdateURL()
returns the default update URL (for the update information) which is used when an extension does not ...
Definition: dp_update.cxx:222
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getHighestVersion(OUString const &sharedVersion, OUString const &bundledVersion, OUString const &onlineVersion)
Definition: dp_update.cxx:390
@ UPDATE_SOURCE_SHARED
Definition: dp_update.hxx:45
@ UPDATE_SOURCE_ONLINE
Definition: dp_update.hxx:47
@ UPDATE_SOURCE_NONE
Definition: dp_update.hxx:44
@ UPDATE_SOURCE_BUNDLED
Definition: dp_update.hxx:46
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UPDATE_SOURCE isUpdateUserExtension(bool bReadOnlyShared, OUString const &userVersion, OUString const &sharedVersion, OUString const &bundledVersion, std::u16string_view onlineVersion)
Definition: dp_update.cxx:234
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UPDATE_SOURCE isUpdateSharedExtension(bool bReadOnlyShared, OUString const &sharedVersion, OUString const &bundledVersion, std::u16string_view onlineVersion)
Definition: dp_update.cxx:284
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC Order compareVersions(std::u16string_view version1, std::u16string_view version2)
Definition: dp_version.cxx:42
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC css::uno::Reference< css::deployment::XPackage > getExtensionWithHighestVersion(css::uno::Sequence< css::uno::Reference< css::deployment::XPackage > > const &seqExtensionsWithSameId)
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC OUString getIdentifier(css::uno::Reference< css::deployment::XPackage > const &package)
Gets the identifier of a package.
DESKTOP_DEPLOYMENTMISC_DLLPUBLIC UpdateInfoMap getOnlineUpdateInfos(css::uno::Reference< css::uno::XComponentContext > const &xContext, css::uno::Reference< css::deployment::XExtensionManager > const &xExtMgr, css::uno::Reference< css::deployment::XUpdateInformationProvider > const &updateInformation, std::vector< css::uno::Reference< css::deployment::XPackage > > const *extensionList, std::vector< std::pair< css::uno::Reference< css::deployment::XPackage >, css::uno::Any > > &out_errors)
int i
index
UpdateInfo(css::uno::Reference< css::deployment::XPackage > const &ext)
Definition: dp_update.cxx:334
bool hasValue()
size_t pos