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