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 <sal/config.h>
22 #include "updatecheck.hxx"
23 #include "updatecheckconfig.hxx"
24 #include "updatehdl.hxx"
25 #include "updateprotocol.hxx"
28 #include <cppuhelper/implbase.hxx>
29 #include <cppuhelper/implementationentry.hxx>
30 #include <cppuhelper/supportsservice.hxx>
31 #include <sal/log.hxx>
32 #include <tools/diagnose_ex.h>
34 #include <com/sun/star/frame/Desktop.hpp>
35 #include <com/sun/star/frame/XTerminateListener.hpp>
36 #include <com/sun/star/task/XJob.hpp>
38 namespace beans
= com::sun::star::beans
;
39 namespace frame
= com::sun::star::frame
;
40 namespace lang
= com::sun::star::lang
;
41 namespace task
= com::sun::star::task
;
42 namespace uno
= com::sun::star::uno
;
47 class InitUpdateCheckJobThread
: public osl::Thread
50 InitUpdateCheckJobThread( const uno::Reference
< uno::XComponentContext
> &xContext
,
51 const uno::Sequence
< beans::NamedValue
> &xParameters
,
54 virtual void SAL_CALL
run() override
;
56 void setTerminating();
59 osl::Condition m_aCondition
;
60 uno::Reference
<uno::XComponentContext
> m_xContext
;
61 uno::Sequence
<beans::NamedValue
> m_xParameters
;
66 class UpdateCheckJob
:
67 public ::cppu::WeakImplHelper
< task::XJob
, lang::XServiceInfo
, frame::XTerminateListener
>
69 virtual ~UpdateCheckJob() override
;
74 css::uno::Reference
<css::uno::XComponentContext
> const & context
,
75 css::uno::Reference
<css::frame::XDesktop2
> const & desktop
):
76 m_xContext(context
), m_xDesktop(desktop
)
79 static uno::Sequence
< OUString
> getServiceNames();
80 static OUString
getImplName();
83 virtual uno::Any SAL_CALL
execute(const uno::Sequence
<beans::NamedValue
>&) override
;
86 virtual OUString SAL_CALL
getImplementationName() override
;
87 virtual sal_Bool SAL_CALL
supportsService(OUString
const & serviceName
) override
;
88 virtual uno::Sequence
< OUString
> SAL_CALL
getSupportedServiceNames() override
;
91 virtual void SAL_CALL
disposing( css::lang::EventObject
const & evt
) override
;
94 virtual void SAL_CALL
queryTermination( lang::EventObject
const & evt
) override
;
95 virtual void SAL_CALL
notifyTermination( lang::EventObject
const & evt
) override
;
98 uno::Reference
<uno::XComponentContext
> m_xContext
;
99 uno::Reference
< frame::XDesktop2
> m_xDesktop
;
100 std::unique_ptr
< InitUpdateCheckJobThread
> m_pInitThread
;
102 void handleExtensionUpdates( const uno::Sequence
< beans::NamedValue
> &rListProp
);
103 void terminateAndJoinThread();
106 InitUpdateCheckJobThread::InitUpdateCheckJobThread(
107 const uno::Reference
< uno::XComponentContext
> &xContext
,
108 const uno::Sequence
< beans::NamedValue
> &xParameters
,
110 m_xContext( xContext
),
111 m_xParameters( xParameters
),
112 m_bShowDialog( bShowDialog
),
113 m_bTerminating( false )
119 void SAL_CALL
InitUpdateCheckJobThread::run()
121 osl_setThreadName("InitUpdateCheckJobThread");
123 if (!m_bShowDialog
) {
124 TimeValue tv
= { 25, 0 };
125 m_aCondition
.wait( &tv
);
126 if ( m_bTerminating
)
131 rtl::Reference
< UpdateCheck
> aController( UpdateCheck::get() );
132 aController
->initialize( m_xParameters
, m_xContext
);
135 aController
->showDialog( true );
136 } catch (const uno::Exception
&) {
137 css::uno::Any
ex( cppu::getCaughtException() );
138 // fdo#64962 - don't bring the app down on some unexpected exception.
139 SAL_WARN("extensions.update", "Caught init update exception, thread terminated. " << exceptionToString(ex
) );
143 void InitUpdateCheckJobThread::setTerminating() {
144 m_bTerminating
= true;
148 UpdateCheckJob::~UpdateCheckJob()
152 uno::Sequence
< OUString
>
153 UpdateCheckJob::getServiceNames()
155 uno::Sequence
< OUString
> aServiceList
{ "com.sun.star.setup.UpdateCheck" };
161 UpdateCheckJob::getImplName()
163 return OUString("vnd.sun.UpdateCheck");
168 UpdateCheckJob::execute(const uno::Sequence
<beans::NamedValue
>& namedValues
)
170 for ( sal_Int32 n
=namedValues
.getLength(); n
-- > 0; )
172 if ( namedValues
[ n
].Name
== "DynamicData" )
174 uno::Sequence
<beans::NamedValue
> aListProp
;
175 if ( namedValues
[n
].Value
>>= aListProp
)
177 for ( sal_Int32 i
=aListProp
.getLength(); i
-- > 0; )
179 if ( aListProp
[ i
].Name
== "updateList" )
181 handleExtensionUpdates( aListProp
);
189 uno::Sequence
<beans::NamedValue
> aConfig
=
190 getValue
< uno::Sequence
<beans::NamedValue
> > (namedValues
, "JobConfig");
192 /* Determine the way we got invoked here -
193 * see Developers Guide Chapter "4.7.2 Jobs" to understand the magic
196 uno::Sequence
<beans::NamedValue
> aEnvironment
=
197 getValue
< uno::Sequence
<beans::NamedValue
> > (namedValues
, "Environment");
199 OUString aEventName
= getValue
< OUString
> (aEnvironment
, "EventName");
202 new InitUpdateCheckJobThread(
204 aEventName
!= "onFirstVisibleTask"));
210 void UpdateCheckJob::handleExtensionUpdates( const uno::Sequence
< beans::NamedValue
> &rListProp
)
213 uno::Sequence
< uno::Sequence
< OUString
> > aList
=
214 getValue
< uno::Sequence
< uno::Sequence
< OUString
> > > ( rListProp
, "updateList" );
215 bool bPrepareOnly
= getValue
< bool > ( rListProp
, "prepareOnly" );
217 // we will first store any new found updates and then check, if there are any
219 storeExtensionUpdateInfos( m_xContext
, aList
);
224 bool bHasUpdates
= checkForPendingUpdates( m_xContext
);
226 rtl::Reference
<UpdateCheck
> aController( UpdateCheck::get() );
227 if ( ! aController
.is() )
230 aController
->setHasExtensionUpdates( bHasUpdates
);
232 if ( ! aController
->hasOfficeUpdate() )
235 aController
->setUIState( UPDATESTATE_EXT_UPD_AVAIL
, true );
237 aController
->setUIState( UPDATESTATE_NO_UPDATE_AVAIL
, true );
240 catch( const uno::Exception
& )
242 css::uno::Any
ex( cppu::getCaughtException() );
243 SAL_WARN("extensions.update", "Caught exception, thread terminated. " << exceptionToString(ex
));
249 UpdateCheckJob::getImplementationName()
251 return getImplName();
255 uno::Sequence
< OUString
> SAL_CALL
256 UpdateCheckJob::getSupportedServiceNames()
258 return getServiceNames();
262 UpdateCheckJob::supportsService( OUString
const & serviceName
)
264 return cppu::supportsService(this, serviceName
);
269 void SAL_CALL
UpdateCheckJob::disposing( lang::EventObject
const & rEvt
)
271 bool shutDown
= ( rEvt
.Source
== m_xDesktop
);
273 if ( shutDown
&& m_xDesktop
.is() )
275 terminateAndJoinThread();
276 m_xDesktop
->removeTerminateListener( this );
282 // XTerminateListener
283 void SAL_CALL
UpdateCheckJob::queryTermination( lang::EventObject
const & )
287 void UpdateCheckJob::terminateAndJoinThread()
289 if (m_pInitThread
!= nullptr)
291 m_pInitThread
->setTerminating();
292 m_pInitThread
->join();
293 m_pInitThread
.reset();
297 void SAL_CALL
UpdateCheckJob::notifyTermination( lang::EventObject
const & )
299 terminateAndJoinThread();
302 } // anonymous namespace
304 static uno::Reference
<uno::XInterface
>
305 createJobInstance(const uno::Reference
<uno::XComponentContext
>& xContext
)
307 css::uno::Reference
<css::frame::XDesktop2
> desktop(
308 css::frame::Desktop::create(xContext
));
309 rtl::Reference
<UpdateCheckJob
> job(new UpdateCheckJob(xContext
, desktop
));
310 desktop
->addTerminateListener(job
.get());
311 return static_cast<cppu::OWeakObject
*>(job
.get());
315 static uno::Reference
<uno::XInterface
>
316 createConfigInstance(const uno::Reference
<uno::XComponentContext
>& xContext
)
318 return *UpdateCheckConfig::get(xContext
, *UpdateCheck::get());
322 static const cppu::ImplementationEntry kImplementations_entries
[] =
326 UpdateCheckJob::getImplName
,
327 UpdateCheckJob::getServiceNames
,
328 cppu::createSingleComponentFactory
,
333 createConfigInstance
,
334 UpdateCheckConfig::getImplName
,
335 UpdateCheckConfig::getServiceNames
,
336 cppu::createSingleComponentFactory
,
340 { nullptr, nullptr, nullptr, nullptr, nullptr, 0 }
344 extern "C" SAL_DLLPUBLIC_EXPORT
void * updchk_component_getFactory(const sal_Char
*pszImplementationName
, void *pServiceManager
, void *pRegistryKey
)
346 return cppu::component_getFactoryHelper(
347 pszImplementationName
,
350 kImplementations_entries
) ;
353 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */