1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include "osl/file.hxx"
21 #include "osl/mutex.hxx"
23 #include <rtl/bootstrap.hxx>
24 #include <rtl/ustring.hxx>
25 #include <rtl/logfile.hxx>
26 #include "cppuhelper/compbase3.hxx"
28 #include "vcl/wrkwin.hxx"
29 #include "vcl/timer.hxx"
31 #include <unotools/configmgr.hxx>
32 #include "toolkit/helper/vclunohelper.hxx"
34 #include <comphelper/processfactory.hxx>
35 #include <comphelper/sequence.hxx>
36 #include <cppuhelper/bootstrap.hxx>
37 #include <com/sun/star/ucb/XCommandEnvironment.hpp>
38 #include <com/sun/star/beans/XPropertySet.hpp>
39 #include <com/sun/star/beans/NamedValue.hpp>
40 #include <com/sun/star/configuration/theDefaultProvider.hpp>
41 #include "com/sun/star/deployment/XPackage.hpp"
42 #include "com/sun/star/deployment/ExtensionManager.hpp"
43 #include "com/sun/star/deployment/LicenseException.hpp"
44 #include "com/sun/star/deployment/ui/LicenseDialog.hpp"
45 #include <com/sun/star/task/OfficeRestartManager.hpp>
46 #include <com/sun/star/task/XJob.hpp>
47 #include <com/sun/star/task/XJobExecutor.hpp>
48 #include <com/sun/star/task/XInteractionApprove.hpp>
49 #include <com/sun/star/task/XInteractionAbort.hpp>
50 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
51 #include "com/sun/star/ui/dialogs/ExecutableDialogResults.hpp"
52 #include <com/sun/star/util/XChangesBatch.hpp>
56 #include "../deployment/inc/dp_misc.h"
58 using namespace desktop
;
59 using namespace com::sun::star
;
60 using namespace com::sun::star::lang
;
61 using namespace com::sun::star::task
;
62 using namespace com::sun::star::uno
;
66 //For use with XExtensionManager.synchronize
67 class SilentCommandEnv
68 : public ::cppu::WeakImplHelper3
< ucb::XCommandEnvironment
,
69 task::XInteractionHandler
,
70 ucb::XProgressHandler
>
72 uno::Reference
<uno::XComponentContext
> mxContext
;
79 uno::Reference
<uno::XComponentContext
> const & xContext
,
81 virtual ~SilentCommandEnv();
83 // XCommandEnvironment
84 virtual uno::Reference
<task::XInteractionHandler
> SAL_CALL
85 getInteractionHandler() throw (uno::RuntimeException
);
86 virtual uno::Reference
<ucb::XProgressHandler
>
87 SAL_CALL
getProgressHandler() throw (uno::RuntimeException
);
89 // XInteractionHandler
90 virtual void SAL_CALL
handle(
91 uno::Reference
<task::XInteractionRequest
> const & xRequest
)
92 throw (uno::RuntimeException
);
95 virtual void SAL_CALL
push( uno::Any
const & Status
)
96 throw (uno::RuntimeException
);
97 virtual void SAL_CALL
update( uno::Any
const & Status
)
98 throw (uno::RuntimeException
);
99 virtual void SAL_CALL
pop() throw (uno::RuntimeException
);
102 //-----------------------------------------------------------------------------
103 SilentCommandEnv::SilentCommandEnv(
104 uno::Reference
<uno::XComponentContext
> const & xContext
,
106 mxContext( xContext
),
107 mpDesktop( pDesktop
),
112 //-----------------------------------------------------------------------------
113 SilentCommandEnv::~SilentCommandEnv()
115 mpDesktop
->SetSplashScreenText( OUString() );
118 //-----------------------------------------------------------------------------
119 Reference
<task::XInteractionHandler
> SilentCommandEnv::getInteractionHandler()
120 throw (uno::RuntimeException
)
125 //-----------------------------------------------------------------------------
126 Reference
<ucb::XProgressHandler
> SilentCommandEnv::getProgressHandler()
127 throw (uno::RuntimeException
)
132 //-----------------------------------------------------------------------------
133 // XInteractionHandler
134 void SilentCommandEnv::handle( Reference
< task::XInteractionRequest
> const & xRequest
)
135 throw (uno::RuntimeException
)
137 deployment::LicenseException licExc
;
139 uno::Any
request( xRequest
->getRequest() );
140 bool bApprove
= true;
142 if ( request
>>= licExc
)
144 uno::Reference
< ui::dialogs::XExecutableDialog
> xDialog(
145 deployment::ui::LicenseDialog::create(
146 mxContext
, VCLUnoHelper::GetInterface( NULL
),
147 licExc
.ExtensionName
, licExc
.Text
) );
148 sal_Int16 res
= xDialog
->execute();
149 if ( res
== ui::dialogs::ExecutableDialogResults::CANCEL
)
151 else if ( res
== ui::dialogs::ExecutableDialogResults::OK
)
159 // We approve everything here
160 uno::Sequence
< Reference
< task::XInteractionContinuation
> > conts( xRequest
->getContinuations() );
161 Reference
< task::XInteractionContinuation
> const * pConts
= conts
.getConstArray();
162 sal_Int32 len
= conts
.getLength();
164 for ( sal_Int32 pos
= 0; pos
< len
; ++pos
)
168 uno::Reference
< task::XInteractionApprove
> xInteractionApprove( pConts
[ pos
], uno::UNO_QUERY
);
169 if ( xInteractionApprove
.is() )
170 xInteractionApprove
->select();
174 uno::Reference
< task::XInteractionAbort
> xInteractionAbort( pConts
[ pos
], uno::UNO_QUERY
);
175 if ( xInteractionAbort
.is() )
176 xInteractionAbort
->select();
181 //-----------------------------------------------------------------------------
183 void SilentCommandEnv::push( uno::Any
const & rStatus
)
184 throw (uno::RuntimeException
)
189 if ( rStatus
.hasValue() && ( rStatus
>>= sText
) )
192 mpDesktop
->SetSplashScreenText( sText
);
194 mpDesktop
->SetSplashScreenProgress( ++mnProgress
);
198 //-----------------------------------------------------------------------------
199 void SilentCommandEnv::update( uno::Any
const & rStatus
)
200 throw (uno::RuntimeException
)
203 if ( rStatus
.hasValue() && ( rStatus
>>= sText
) )
205 mpDesktop
->SetSplashScreenText( sText
);
209 //-----------------------------------------------------------------------------
210 void SilentCommandEnv::pop() throw (uno::RuntimeException
)
218 static const char aAccessSrvc
[] = "com.sun.star.configuration.ConfigurationUpdateAccess";
220 static sal_Int16
impl_showExtensionDialog( uno::Reference
< uno::XComponentContext
> &xContext
)
222 OUString sServiceName
= "com.sun.star.deployment.ui.UpdateRequiredDialog";
223 uno::Reference
< uno::XInterface
> xService
;
226 uno::Reference
< lang::XMultiComponentFactory
> xServiceManager( xContext
->getServiceManager() );
227 if( !xServiceManager
.is() )
228 throw uno::RuntimeException(
229 "impl_showExtensionDialog(): unable to obtain service manager from component context", uno::Reference
< uno::XInterface
> () );
231 xService
= xServiceManager
->createInstanceWithContext( sServiceName
, xContext
);
232 uno::Reference
< ui::dialogs::XExecutableDialog
> xExecuteable( xService
, uno::UNO_QUERY
);
233 if ( xExecuteable
.is() )
234 nRet
= xExecuteable
->execute();
239 //------------------------------------------------------------------------------
240 // Check dependencies of all packages
241 //------------------------------------------------------------------------------
242 static bool impl_checkDependencies( const uno::Reference
< uno::XComponentContext
> &xContext
)
244 uno::Sequence
< uno::Sequence
< uno::Reference
< deployment::XPackage
> > > xAllPackages
;
245 uno::Reference
< deployment::XExtensionManager
> xExtensionManager
= deployment::ExtensionManager::get( xContext
);
247 if ( !xExtensionManager
.is() )
249 OSL_FAIL( "Could not get the Extension Manager!" );
254 xAllPackages
= xExtensionManager
->getAllExtensions( uno::Reference
< task::XAbortChannel
>(),
255 uno::Reference
< ucb::XCommandEnvironment
>() );
257 catch ( const deployment::DeploymentException
& ) { return true; }
258 catch ( const ucb::CommandFailedException
& ) { return true; }
259 catch ( const ucb::CommandAbortedException
& ) { return true; }
260 catch ( const lang::IllegalArgumentException
& e
) {
261 throw uno::RuntimeException( e
.Message
, e
.Context
);
269 for ( sal_Int32 i
= 0; i
< xAllPackages
.getLength(); ++i
)
271 uno::Sequence
< uno::Reference
< deployment::XPackage
> > xPackageList
= xAllPackages
[i
];
273 for ( sal_Int32 j
= 0; (j
<nMax
) && (j
< xPackageList
.getLength()); ++j
)
275 uno::Reference
< deployment::XPackage
> xPackage
= xPackageList
[j
];
278 bool bRegistered
= false;
280 beans::Optional
< beans::Ambiguous
< sal_Bool
> > option( xPackage
->isRegistered( uno::Reference
< task::XAbortChannel
>(),
281 uno::Reference
< ucb::XCommandEnvironment
>() ) );
282 if ( option
.IsPresent
)
284 ::beans::Ambiguous
< sal_Bool
> const & reg
= option
.Value
;
285 if ( reg
.IsAmbiguous
)
288 bRegistered
= reg
.Value
? true : false;
293 catch ( const uno::RuntimeException
& ) { throw; }
294 catch (const uno::Exception
& exc
) {
296 OSL_FAIL( OUStringToOString( exc
.Message
, RTL_TEXTENCODING_UTF8
).getStr() );
301 bool bDependenciesValid
= false;
303 bDependenciesValid
= xPackage
->checkDependencies( uno::Reference
< ucb::XCommandEnvironment
>() );
305 catch ( const deployment::DeploymentException
& ) {}
306 if ( ! bDependenciesValid
)
317 //------------------------------------------------------------------------------
318 // resets the 'check needed' flag (needed, if aborted)
319 //------------------------------------------------------------------------------
320 static void impl_setNeedsCompatCheck()
323 Reference
< XMultiServiceFactory
> theConfigProvider(
324 configuration::theDefaultProvider::get(
325 comphelper::getProcessComponentContext() ) );
327 Sequence
< Any
> theArgs(1);
328 beans::NamedValue
v( OUString("nodepath"),
329 makeAny( OUString("org.openoffice.Setup/Office") ) );
331 Reference
< beans::XPropertySet
> pset
= Reference
< beans::XPropertySet
>(
332 theConfigProvider
->createInstanceWithArguments( OUString(aAccessSrvc
), theArgs
), UNO_QUERY_THROW
);
334 Any value
= makeAny( OUString("never") );
336 pset
->setPropertyValue( OUString("LastCompatibilityCheckID"), value
);
337 Reference
< util::XChangesBatch
>( pset
, UNO_QUERY_THROW
)->commitChanges();
339 catch (const Exception
&) {}
342 //------------------------------------------------------------------------------
343 // to check if we need checking the dependencies of the extensions again, we compare
344 // the build id of the office with the one of the last check
345 //------------------------------------------------------------------------------
346 static bool impl_needsCompatCheck()
348 bool bNeedsCheck
= false;
349 OUString aLastCheckBuildID
;
350 OUString
aCurrentBuildID( "${$BRAND_BASE_DIR/program/" SAL_CONFIGFILE("version") ":buildid}" );
351 rtl::Bootstrap::expandMacros( aCurrentBuildID
);
354 Reference
< XMultiServiceFactory
> theConfigProvider(
355 configuration::theDefaultProvider::get(
356 comphelper::getProcessComponentContext() ) );
358 Sequence
< Any
> theArgs(1);
359 beans::NamedValue
v( OUString("nodepath"),
360 makeAny( OUString("org.openoffice.Setup/Office") ) );
362 Reference
< beans::XPropertySet
> pset
= Reference
< beans::XPropertySet
>(
363 theConfigProvider
->createInstanceWithArguments( OUString(aAccessSrvc
), theArgs
), UNO_QUERY_THROW
);
365 Any result
= pset
->getPropertyValue( OUString("LastCompatibilityCheckID") );
367 result
>>= aLastCheckBuildID
;
368 if ( aLastCheckBuildID
!= aCurrentBuildID
)
371 result
<<= aCurrentBuildID
;
372 pset
->setPropertyValue( OUString("LastCompatibilityCheckID"), result
);
373 Reference
< util::XChangesBatch
>( pset
, UNO_QUERY_THROW
)->commitChanges();
379 catch (const com::sun::star::uno::Exception
&) {}
384 //------------------------------------------------------------------------------
385 // Do we need to check the dependencies of the extensions?
386 // When there are unresolved issues, we can't continue with startup
387 sal_Bool
Desktop::CheckExtensionDependencies()
389 if (!impl_needsCompatCheck())
394 uno::Reference
< uno::XComponentContext
> xContext
= comphelper_getProcessComponentContext();
396 bool bDependenciesValid
= impl_checkDependencies( xContext
);
400 if ( !bDependenciesValid
)
401 nRet
= impl_showExtensionDialog( xContext
);
405 impl_setNeedsCompatCheck();
412 void Desktop::SynchronizeExtensionRepositories()
414 RTL_LOGFILE_CONTEXT(aLog
,"desktop (jl) ::Desktop::SynchronizeExtensionRepositories");
415 uno::Reference
< uno::XComponentContext
> context(
416 comphelper_getProcessComponentContext());
417 uno::Reference
< ucb::XCommandEnvironment
> silent(
418 new SilentCommandEnv(context
, this));
419 if (m_bCleanedExtensionCache
) {
420 deployment::ExtensionManager::get(context
)->reinstallDeployedExtensions(
421 true, "user", Reference
<task::XAbortChannel
>(), silent
);
422 task::OfficeRestartManager::get(context
)->requestRestart(
423 silent
->getInteractionHandler());
425 // reinstallDeployedExtensions above already calls syncRepositories
427 dp_misc::syncRepositories(false, silent
);
431 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */