Line data Source code
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 "vcl/svapp.hxx"
21 : #include "vcl/msgbox.hxx"
22 :
23 : #include "osl/mutex.hxx"
24 :
25 : #include <toolkit/helper/vclunohelper.hxx>
26 :
27 : #include "com/sun/star/beans/XPropertySet.hpp"
28 : #include "com/sun/star/configuration/theDefaultProvider.hpp"
29 :
30 : #include "dp_gui_dialog2.hxx"
31 : #include "dp_gui_extensioncmdqueue.hxx"
32 : #include "dp_gui_theextmgr.hxx"
33 : #include "dp_identifier.hxx"
34 : #include "dp_update.hxx"
35 :
36 : #define USER_PACKAGE_MANAGER OUString("user")
37 : #define SHARED_PACKAGE_MANAGER OUString("shared")
38 : #define BUNDLED_PACKAGE_MANAGER OUString("bundled")
39 :
40 : using namespace ::com::sun::star;
41 : using ::rtl::OUString;
42 :
43 : namespace dp_gui {
44 :
45 : //------------------------------------------------------------------------------
46 :
47 0 : ::rtl::Reference< TheExtensionManager > TheExtensionManager::s_ExtMgr;
48 :
49 : //------------------------------------------------------------------------------
50 : // TheExtensionManager
51 : //------------------------------------------------------------------------------
52 :
53 0 : TheExtensionManager::TheExtensionManager( Window *pParent,
54 : const uno::Reference< uno::XComponentContext > &xContext ) :
55 : m_xContext( xContext ),
56 : m_pParent( pParent ),
57 : m_pExtMgrDialog( NULL ),
58 : m_pUpdReqDialog( NULL ),
59 0 : m_pExecuteCmdQueue( NULL )
60 : {
61 0 : m_xExtensionManager = deployment::ExtensionManager::get( xContext );
62 0 : m_xExtensionManager->addModifyListener( this );
63 :
64 : uno::Reference< lang::XMultiServiceFactory > xConfig(
65 0 : configuration::theDefaultProvider::get(xContext));
66 0 : uno::Any args[1];
67 : beans::PropertyValue aValue( OUString("nodepath"), 0, uno::Any( OUString("/org.openoffice.Office.OptionsDialog/Nodes") ),
68 0 : beans::PropertyState_DIRECT_VALUE );
69 0 : args[0] <<= aValue;
70 : m_xNameAccessNodes = uno::Reference< container::XNameAccess >(
71 0 : xConfig->createInstanceWithArguments( OUString("com.sun.star.configuration.ConfigurationAccess"),
72 0 : uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW);
73 :
74 : // get the 'get more extensions here' url
75 0 : uno::Reference< container::XNameAccess > xNameAccessRepositories;
76 : beans::PropertyValue aValue2( OUString("nodepath"), 0, uno::Any( OUString("/org.openoffice.Office.ExtensionManager/ExtensionRepositories") ),
77 0 : beans::PropertyState_DIRECT_VALUE );
78 0 : args[0] <<= aValue2;
79 : xNameAccessRepositories = uno::Reference< container::XNameAccess > (
80 0 : xConfig->createInstanceWithArguments( OUString("com.sun.star.configuration.ConfigurationAccess"),
81 0 : uno::Sequence< uno::Any >( args, 1 )), uno::UNO_QUERY_THROW);
82 : try
83 : { //throws css::container::NoSuchElementException, css::lang::WrappedTargetException
84 0 : uno::Any value = xNameAccessRepositories->getByName( OUString( "WebsiteLink" ) );
85 0 : m_sGetExtensionsURL = value.get< OUString > ();
86 : }
87 0 : catch ( const uno::Exception& )
88 : {}
89 :
90 0 : if ( dp_misc::office_is_running() )
91 : {
92 : // the registration should be done after the construction has been ended
93 : // otherwise an exception prevents object creation, but it is registered as a listener
94 0 : m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext(
95 0 : OUString("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY );
96 0 : if ( m_xDesktop.is() )
97 0 : m_xDesktop->addTerminateListener( this );
98 0 : }
99 0 : }
100 :
101 : //------------------------------------------------------------------------------
102 0 : TheExtensionManager::~TheExtensionManager()
103 : {
104 0 : delete m_pUpdReqDialog;
105 0 : delete m_pExtMgrDialog;
106 0 : delete m_pExecuteCmdQueue;
107 0 : }
108 :
109 : //------------------------------------------------------------------------------
110 0 : void TheExtensionManager::createDialog( const bool bCreateUpdDlg )
111 : {
112 0 : const SolarMutexGuard guard;
113 :
114 0 : if ( bCreateUpdDlg )
115 : {
116 0 : if ( !m_pUpdReqDialog )
117 : {
118 0 : m_pUpdReqDialog = new UpdateRequiredDialog( NULL, this );
119 0 : delete m_pExecuteCmdQueue;
120 0 : m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pUpdReqDialog, this, m_xContext );
121 0 : createPackageList();
122 : }
123 : }
124 0 : else if ( !m_pExtMgrDialog )
125 : {
126 0 : m_pExtMgrDialog = new ExtMgrDialog( m_pParent, this );
127 0 : delete m_pExecuteCmdQueue;
128 0 : m_pExecuteCmdQueue = new ExtensionCmdQueue( (DialogHelper*) m_pExtMgrDialog, this, m_xContext );
129 0 : m_pExtMgrDialog->setGetExtensionsURL( m_sGetExtensionsURL );
130 0 : createPackageList();
131 0 : }
132 0 : }
133 :
134 : //------------------------------------------------------------------------------
135 0 : void TheExtensionManager::Show()
136 : {
137 0 : const SolarMutexGuard guard;
138 :
139 0 : getDialog()->Show();
140 0 : }
141 :
142 : //------------------------------------------------------------------------------
143 0 : void TheExtensionManager::SetText( const ::rtl::OUString &rTitle )
144 : {
145 0 : const SolarMutexGuard guard;
146 :
147 0 : getDialog()->SetText( rTitle );
148 0 : }
149 :
150 : //------------------------------------------------------------------------------
151 0 : void TheExtensionManager::ToTop( sal_uInt16 nFlags )
152 : {
153 0 : const SolarMutexGuard guard;
154 :
155 0 : getDialog()->ToTop( nFlags );
156 0 : }
157 :
158 : //------------------------------------------------------------------------------
159 0 : bool TheExtensionManager::Close()
160 : {
161 0 : if ( m_pExtMgrDialog )
162 0 : return m_pExtMgrDialog->Close();
163 0 : else if ( m_pUpdReqDialog )
164 0 : return m_pUpdReqDialog->Close();
165 : else
166 0 : return true;
167 : }
168 :
169 : //------------------------------------------------------------------------------
170 0 : sal_Int16 TheExtensionManager::execute()
171 : {
172 0 : sal_Int16 nRet = 0;
173 :
174 0 : if ( m_pUpdReqDialog )
175 : {
176 0 : nRet = m_pUpdReqDialog->Execute();
177 0 : delete m_pUpdReqDialog;
178 0 : m_pUpdReqDialog = NULL;
179 : }
180 :
181 0 : return nRet;
182 : }
183 :
184 : //------------------------------------------------------------------------------
185 0 : bool TheExtensionManager::isVisible()
186 : {
187 0 : return getDialog()->IsVisible();
188 : }
189 :
190 : //------------------------------------------------------------------------------
191 0 : bool TheExtensionManager::checkUpdates( bool /* bShowUpdateOnly */, bool /*bParentVisible*/ )
192 : {
193 0 : std::vector< uno::Reference< deployment::XPackage > > vEntries;
194 0 : uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
195 :
196 : try {
197 0 : xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
198 0 : uno::Reference< ucb::XCommandEnvironment >() );
199 0 : } catch ( const deployment::DeploymentException & ) {
200 0 : return false;
201 0 : } catch ( const ucb::CommandFailedException & ) {
202 0 : return false;
203 0 : } catch ( const ucb::CommandAbortedException & ) {
204 0 : return false;
205 0 : } catch ( const lang::IllegalArgumentException & e ) {
206 0 : throw uno::RuntimeException( e.Message, e.Context );
207 : }
208 :
209 0 : for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
210 : {
211 0 : uno::Reference< deployment::XPackage > xPackage = dp_misc::getExtensionWithHighestVersion(xAllPackages[i]);
212 : OSL_ASSERT(xPackage.is());
213 0 : if ( xPackage.is() )
214 : {
215 0 : vEntries.push_back( xPackage );
216 : }
217 0 : }
218 :
219 0 : m_pExecuteCmdQueue->checkForUpdates( vEntries );
220 0 : return true;
221 : }
222 :
223 : //------------------------------------------------------------------------------
224 0 : bool TheExtensionManager::installPackage( const OUString &rPackageURL, bool bWarnUser )
225 : {
226 0 : if ( rPackageURL.isEmpty() )
227 0 : return false;
228 :
229 0 : createDialog( false );
230 :
231 0 : bool bInstall = true;
232 0 : bool bInstallForAll = false;
233 :
234 : // DV! missing function is read only repository from extension manager
235 0 : if ( !bWarnUser && ! m_xExtensionManager->isReadOnlyRepository( SHARED_PACKAGE_MANAGER ) )
236 0 : bInstall = getDialogHelper()->installForAllUsers( bInstallForAll );
237 :
238 0 : if ( !bInstall )
239 0 : return false;
240 :
241 0 : if ( bInstallForAll )
242 0 : m_pExecuteCmdQueue->addExtension( rPackageURL, SHARED_PACKAGE_MANAGER, false );
243 : else
244 0 : m_pExecuteCmdQueue->addExtension( rPackageURL, USER_PACKAGE_MANAGER, bWarnUser );
245 :
246 0 : return true;
247 : }
248 :
249 : //------------------------------------------------------------------------------
250 0 : bool TheExtensionManager::queryTermination()
251 : {
252 0 : if ( dp_misc::office_is_running() )
253 0 : return true;
254 : // the standalone application unopkg must not close ( and quit ) the dialog
255 : // when there are still actions in the queue
256 0 : return true;
257 : }
258 :
259 : //------------------------------------------------------------------------------
260 0 : void TheExtensionManager::terminateDialog()
261 : {
262 0 : if ( ! dp_misc::office_is_running() )
263 : {
264 0 : const SolarMutexGuard guard;
265 0 : delete m_pExtMgrDialog;
266 0 : m_pExtMgrDialog = NULL;
267 0 : delete m_pUpdReqDialog;
268 0 : m_pUpdReqDialog = NULL;
269 0 : Application::Quit();
270 : }
271 0 : }
272 :
273 : //------------------------------------------------------------------------------
274 0 : void TheExtensionManager::createPackageList()
275 : {
276 0 : uno::Sequence< uno::Sequence< uno::Reference< deployment::XPackage > > > xAllPackages;
277 :
278 : try {
279 0 : xAllPackages = m_xExtensionManager->getAllExtensions( uno::Reference< task::XAbortChannel >(),
280 0 : uno::Reference< ucb::XCommandEnvironment >() );
281 0 : } catch ( const deployment::DeploymentException & ) {
282 : return;
283 0 : } catch ( const ucb::CommandFailedException & ) {
284 : return;
285 0 : } catch ( const ucb::CommandAbortedException & ) {
286 : return;
287 0 : } catch ( const lang::IllegalArgumentException & e ) {
288 0 : throw uno::RuntimeException( e.Message, e.Context );
289 : }
290 :
291 0 : for ( sal_Int32 i = 0; i < xAllPackages.getLength(); ++i )
292 : {
293 0 : uno::Sequence< uno::Reference< deployment::XPackage > > xPackageList = xAllPackages[i];
294 :
295 0 : for ( sal_Int32 j = 0; j < xPackageList.getLength(); ++j )
296 : {
297 0 : uno::Reference< deployment::XPackage > xPackage = xPackageList[j];
298 0 : if ( xPackage.is() )
299 : {
300 0 : PackageState eState = getPackageState( xPackage );
301 0 : getDialogHelper()->addPackageToList( xPackage );
302 : // When the package is enabled, we can stop here, otherwise we have to look for
303 : // another version of this package
304 0 : if ( ( eState == REGISTERED ) || ( eState == NOT_AVAILABLE ) )
305 : break;
306 : }
307 0 : }
308 0 : }
309 :
310 0 : uno::Sequence< uno::Reference< deployment::XPackage > > xNoLicPackages;
311 0 : xNoLicPackages = m_xExtensionManager->getExtensionsWithUnacceptedLicenses( SHARED_PACKAGE_MANAGER,
312 0 : uno::Reference< ucb::XCommandEnvironment >() );
313 0 : for ( sal_Int32 i = 0; i < xNoLicPackages.getLength(); ++i )
314 : {
315 0 : uno::Reference< deployment::XPackage > xPackage = xNoLicPackages[i];
316 0 : if ( xPackage.is() )
317 : {
318 0 : getDialogHelper()->addPackageToList( xPackage, true );
319 : }
320 0 : }
321 : }
322 :
323 : //------------------------------------------------------------------------------
324 0 : PackageState TheExtensionManager::getPackageState( const uno::Reference< deployment::XPackage > &xPackage ) const
325 : {
326 : try {
327 : beans::Optional< beans::Ambiguous< sal_Bool > > option(
328 0 : xPackage->isRegistered( uno::Reference< task::XAbortChannel >(),
329 0 : uno::Reference< ucb::XCommandEnvironment >() ) );
330 0 : if ( option.IsPresent )
331 : {
332 0 : ::beans::Ambiguous< sal_Bool > const & reg = option.Value;
333 0 : if ( reg.IsAmbiguous )
334 0 : return AMBIGUOUS;
335 : else
336 0 : return reg.Value ? REGISTERED : NOT_REGISTERED;
337 : }
338 : else
339 0 : return NOT_AVAILABLE;
340 : }
341 0 : catch ( const uno::RuntimeException & ) {
342 0 : throw;
343 : }
344 0 : catch (const uno::Exception & exc) {
345 : (void) exc;
346 : OSL_FAIL( ::rtl::OUStringToOString( exc.Message, RTL_TEXTENCODING_UTF8 ).getStr() );
347 0 : return NOT_AVAILABLE;
348 : }
349 : }
350 :
351 : //------------------------------------------------------------------------------
352 0 : bool TheExtensionManager::isReadOnly( const uno::Reference< deployment::XPackage > &xPackage ) const
353 : {
354 0 : if ( m_xExtensionManager.is() && xPackage.is() )
355 : {
356 0 : return m_xExtensionManager->isReadOnlyRepository( xPackage->getRepositoryName() );
357 : }
358 : else
359 0 : return true;
360 : }
361 :
362 : //------------------------------------------------------------------------------
363 : // The function investigates if the extension supports options.
364 0 : bool TheExtensionManager::supportsOptions( const uno::Reference< deployment::XPackage > &xPackage ) const
365 : {
366 0 : bool bOptions = false;
367 :
368 0 : if ( ! xPackage->isBundle() )
369 0 : return false;
370 :
371 0 : beans::Optional< OUString > aId = xPackage->getIdentifier();
372 :
373 : //a bundle must always have an id
374 : OSL_ASSERT( aId.IsPresent );
375 :
376 : //iterate over all available nodes
377 0 : uno::Sequence< OUString > seqNames = m_xNameAccessNodes->getElementNames();
378 :
379 0 : for ( int i = 0; i < seqNames.getLength(); i++ )
380 : {
381 0 : uno::Any anyNode = m_xNameAccessNodes->getByName( seqNames[i] );
382 : //If we have a node then then it must contain the set of leaves. This is part of OptionsDialog.xcs
383 0 : uno::Reference< XInterface> xIntNode = anyNode.get< uno::Reference< XInterface > >();
384 0 : uno::Reference< container::XNameAccess > xNode( xIntNode, uno::UNO_QUERY_THROW );
385 :
386 0 : uno::Any anyLeaves = xNode->getByName( OUString("Leaves") );
387 0 : uno::Reference< XInterface > xIntLeaves = anyLeaves.get< uno::Reference< XInterface > >();
388 0 : uno::Reference< container::XNameAccess > xLeaves( xIntLeaves, uno::UNO_QUERY_THROW );
389 :
390 : //iterate over all available leaves
391 0 : uno::Sequence< OUString > seqLeafNames = xLeaves->getElementNames();
392 0 : for ( int j = 0; j < seqLeafNames.getLength(); j++ )
393 : {
394 0 : uno::Any anyLeaf = xLeaves->getByName( seqLeafNames[j] );
395 0 : uno::Reference< XInterface > xIntLeaf = anyLeaf.get< uno::Reference< XInterface > >();
396 0 : uno::Reference< beans::XPropertySet > xLeaf( xIntLeaf, uno::UNO_QUERY_THROW );
397 : //investigate the Id property if it matches the extension identifier which
398 : //has been passed in.
399 0 : uno::Any anyValue = xLeaf->getPropertyValue( OUString("Id") );
400 :
401 0 : OUString sId = anyValue.get< OUString >();
402 0 : if ( sId == aId.Value )
403 : {
404 0 : bOptions = true;
405 : break;
406 : }
407 0 : }
408 0 : if ( bOptions )
409 : break;
410 0 : }
411 0 : return bOptions;
412 : }
413 :
414 : //------------------------------------------------------------------------------
415 : // XEventListener
416 0 : void TheExtensionManager::disposing( lang::EventObject const & rEvt )
417 : throw ( uno::RuntimeException )
418 : {
419 0 : bool shutDown = (rEvt.Source == m_xDesktop);
420 :
421 0 : if ( shutDown && m_xDesktop.is() )
422 : {
423 0 : m_xDesktop->removeTerminateListener( this );
424 0 : m_xDesktop.clear();
425 : }
426 :
427 0 : if ( shutDown )
428 : {
429 0 : if ( dp_misc::office_is_running() )
430 : {
431 0 : const SolarMutexGuard guard;
432 0 : delete m_pExtMgrDialog;
433 0 : m_pExtMgrDialog = NULL;
434 0 : delete m_pUpdReqDialog;
435 0 : m_pUpdReqDialog = NULL;
436 : }
437 0 : s_ExtMgr.clear();
438 : }
439 0 : }
440 :
441 : //------------------------------------------------------------------------------
442 : // XTerminateListener
443 0 : void TheExtensionManager::queryTermination( ::lang::EventObject const & )
444 : throw ( frame::TerminationVetoException, uno::RuntimeException )
445 : {
446 0 : DialogHelper *pDialogHelper = getDialogHelper();
447 :
448 0 : if ( m_pExecuteCmdQueue->isBusy() || ( pDialogHelper && pDialogHelper->isBusy() ) )
449 : {
450 0 : ToTop( TOTOP_RESTOREWHENMIN );
451 : throw frame::TerminationVetoException(
452 : OUString("The office cannot be closed while the Extension Manager is running"),
453 0 : uno::Reference<XInterface>(static_cast<frame::XTerminateListener*>(this), uno::UNO_QUERY));
454 : }
455 : else
456 : {
457 0 : if ( m_pExtMgrDialog )
458 0 : m_pExtMgrDialog->Close();
459 0 : if ( m_pUpdReqDialog )
460 0 : m_pUpdReqDialog->Close();
461 : }
462 0 : }
463 :
464 : //------------------------------------------------------------------------------
465 0 : void TheExtensionManager::notifyTermination( ::lang::EventObject const & rEvt )
466 : throw ( uno::RuntimeException )
467 : {
468 0 : disposing( rEvt );
469 0 : }
470 :
471 : //------------------------------------------------------------------------------
472 : // XModifyListener
473 0 : void TheExtensionManager::modified( ::lang::EventObject const & /*rEvt*/ )
474 : throw ( uno::RuntimeException )
475 : {
476 0 : getDialogHelper()->prepareChecking();
477 0 : createPackageList();
478 0 : getDialogHelper()->checkEntries();
479 0 : }
480 :
481 : //------------------------------------------------------------------------------
482 0 : ::rtl::Reference< TheExtensionManager > TheExtensionManager::get( const uno::Reference< uno::XComponentContext > &xContext,
483 : const uno::Reference< awt::XWindow > &xParent,
484 : const OUString & extensionURL )
485 : {
486 0 : if ( s_ExtMgr.is() )
487 : {
488 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
489 0 : if ( !extensionURL.isEmpty() )
490 0 : s_ExtMgr->installPackage( extensionURL, true );
491 0 : return s_ExtMgr;
492 : }
493 :
494 0 : Window* pParent = DIALOG_NO_PARENT;
495 0 : if (xParent.is())
496 0 : pParent = VCLUnoHelper::GetWindow(xParent);
497 :
498 0 : ::rtl::Reference<TheExtensionManager> that( new TheExtensionManager( pParent, xContext ) );
499 :
500 0 : const SolarMutexGuard guard;
501 0 : if ( ! s_ExtMgr.is() )
502 : {
503 : OSL_DOUBLE_CHECKED_LOCKING_MEMORY_BARRIER();
504 0 : s_ExtMgr = that;
505 : }
506 :
507 0 : if ( !extensionURL.isEmpty() )
508 0 : s_ExtMgr->installPackage( extensionURL, true );
509 :
510 0 : return s_ExtMgr;
511 : }
512 :
513 0 : } //namespace dp_gui
514 :
515 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|