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_extensions.hxx"
26
27 #include <memory>
28
29 #include "updatecheck.hxx"
30 #include "updatecheckconfig.hxx"
31 #include "updatehdl.hxx"
32 #include "updateprotocol.hxx"
33
34 #include <cppuhelper/implbase3.hxx>
35 #include <cppuhelper/implementationentry.hxx>
36
37 #include "com/sun/star/frame/XDesktop.hpp"
38 #include "com/sun/star/frame/XTerminateListener.hpp"
39 #include <com/sun/star/task/XJob.hpp>
40
41 namespace beans = com::sun::star::beans ;
42 namespace frame = com::sun::star::frame ;
43 namespace lang = com::sun::star::lang ;
44 namespace task = com::sun::star::task ;
45 namespace uno = com::sun::star::uno ;
46
47 #define UNISTRING(s) rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(s))
48
49 namespace
50 {
51
52 class InitUpdateCheckJobThread : public osl::Thread
53 {
54 public:
55 InitUpdateCheckJobThread( const uno::Reference< uno::XComponentContext > &xContext,
56 const uno::Sequence< beans::NamedValue > &xParameters,
57 bool bShowDialog );
58
59 virtual void SAL_CALL run();
60
61 void setTerminating();
62
63 private:
64 osl::Condition m_aCondition;
65 uno::Reference<uno::XComponentContext> m_xContext;
66 uno::Sequence<beans::NamedValue> m_xParameters;
67 bool m_bShowDialog;
68 bool m_bTerminating;
69 };
70
71 class UpdateCheckJob :
72 public ::cppu::WeakImplHelper3< task::XJob, lang::XServiceInfo, frame::XTerminateListener >
73 {
74 virtual ~UpdateCheckJob();
75
76 public:
77
78 UpdateCheckJob(const uno::Reference<uno::XComponentContext>& xContext);
79
80 static uno::Sequence< rtl::OUString > getServiceNames();
81 static rtl::OUString getImplName();
82
83 // Allows runtime exceptions to be thrown by const methods
operator uno::Reference<uno::XInterface>() const84 inline SAL_CALL operator uno::Reference< uno::XInterface > () const
85 { return const_cast< cppu::OWeakObject * > (static_cast< cppu::OWeakObject const * > (this)); };
86
87 // XJob
88 virtual uno::Any SAL_CALL execute(const uno::Sequence<beans::NamedValue>&)
89 throw (lang::IllegalArgumentException, uno::Exception);
90
91 // XServiceInfo
92 virtual rtl::OUString SAL_CALL getImplementationName()
93 throw (uno::RuntimeException);
94 virtual sal_Bool SAL_CALL supportsService(rtl::OUString const & serviceName)
95 throw (uno::RuntimeException);
96 virtual uno::Sequence< rtl::OUString > SAL_CALL getSupportedServiceNames()
97 throw (uno::RuntimeException);
98
99 // XEventListener
100 virtual void SAL_CALL disposing( ::com::sun::star::lang::EventObject const & evt )
101 throw (::com::sun::star::uno::RuntimeException);
102
103 // XTerminateListener
104 virtual void SAL_CALL queryTermination( lang::EventObject const & evt )
105 throw ( frame::TerminationVetoException, uno::RuntimeException );
106 virtual void SAL_CALL notifyTermination( lang::EventObject const & evt )
107 throw ( uno::RuntimeException );
108
109 private:
110 uno::Reference<uno::XComponentContext> m_xContext;
111 uno::Reference< frame::XDesktop > m_xDesktop;
112 std::auto_ptr< InitUpdateCheckJobThread > m_pInitThread;
113
114 void handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp );
115 };
116
117 //------------------------------------------------------------------------------
118 //------------------------------------------------------------------------------
119 //------------------------------------------------------------------------------
InitUpdateCheckJobThread(const uno::Reference<uno::XComponentContext> & xContext,const uno::Sequence<beans::NamedValue> & xParameters,bool bShowDialog)120 InitUpdateCheckJobThread::InitUpdateCheckJobThread(
121 const uno::Reference< uno::XComponentContext > &xContext,
122 const uno::Sequence< beans::NamedValue > &xParameters,
123 bool bShowDialog ) :
124 m_xContext( xContext ),
125 m_xParameters( xParameters ),
126 m_bShowDialog( bShowDialog ),
127 m_bTerminating( false )
128 {
129 create();
130 }
131
132 //------------------------------------------------------------------------------
run()133 void SAL_CALL InitUpdateCheckJobThread::run()
134 {
135 if (!m_bShowDialog) {
136 TimeValue tv = { 25, 0 };
137 m_aCondition.wait( &tv );
138 if ( m_bTerminating )
139 return;
140 }
141
142 rtl::Reference< UpdateCheck > aController( UpdateCheck::get() );
143 aController->initialize( m_xParameters, m_xContext );
144
145 if ( m_bShowDialog )
146 aController->showDialog( true );
147 }
148
setTerminating()149 void InitUpdateCheckJobThread::setTerminating() {
150 m_bTerminating = true;
151 m_aCondition.set();
152 }
153
154 //------------------------------------------------------------------------------
155 //------------------------------------------------------------------------------
156 //------------------------------------------------------------------------------
157
UpdateCheckJob(const uno::Reference<uno::XComponentContext> & xContext)158 UpdateCheckJob::UpdateCheckJob( const uno::Reference<uno::XComponentContext>& xContext ) :
159 m_xContext(xContext)
160 {
161 m_xDesktop.set( xContext->getServiceManager()->createInstanceWithContext( UNISTRING("com.sun.star.frame.Desktop"), xContext ), uno::UNO_QUERY );
162 if ( m_xDesktop.is() )
163 m_xDesktop->addTerminateListener( this );
164 }
165
166 //------------------------------------------------------------------------------
167
~UpdateCheckJob()168 UpdateCheckJob::~UpdateCheckJob()
169 {
170 }
171
172 //------------------------------------------------------------------------------
173
174 uno::Sequence< rtl::OUString >
getServiceNames()175 UpdateCheckJob::getServiceNames()
176 {
177 uno::Sequence< rtl::OUString > aServiceList(1);
178 aServiceList[0] = UNISTRING( "com.sun.star.setup.UpdateCheck");
179 return aServiceList;
180 };
181
182 //------------------------------------------------------------------------------
183
184 rtl::OUString
getImplName()185 UpdateCheckJob::getImplName()
186 {
187 return UNISTRING( "vnd.sun.UpdateCheck");
188 }
189
190
191 //------------------------------------------------------------------------------
192
193 uno::Any
execute(const uno::Sequence<beans::NamedValue> & namedValues)194 UpdateCheckJob::execute(const uno::Sequence<beans::NamedValue>& namedValues)
195 throw (lang::IllegalArgumentException, uno::Exception)
196 {
197 for ( sal_Int32 n=namedValues.getLength(); n-- > 0; )
198 {
199 if ( namedValues[ n ].Name.equalsAscii( "DynamicData" ) )
200 {
201 uno::Sequence<beans::NamedValue> aListProp;
202 if ( namedValues[n].Value >>= aListProp )
203 {
204 for ( sal_Int32 i=aListProp.getLength(); i-- > 0; )
205 {
206 if ( aListProp[ i ].Name.equalsAscii( "updateList" ) )
207 {
208 handleExtensionUpdates( aListProp );
209 return uno::Any();
210 }
211 }
212 }
213 }
214 }
215
216 uno::Sequence<beans::NamedValue> aConfig =
217 getValue< uno::Sequence<beans::NamedValue> > (namedValues, "JobConfig");
218
219 /* Determine the way we got invoked here -
220 * see Developers Guide Chapter "4.7.2 Jobs" to understand the magic
221 */
222
223 uno::Sequence<beans::NamedValue> aEnvironment =
224 getValue< uno::Sequence<beans::NamedValue> > (namedValues, "Environment");
225
226 rtl::OUString aEventName = getValue< rtl::OUString > (aEnvironment, "EventName");
227
228 m_pInitThread.reset(
229 new InitUpdateCheckJobThread(
230 m_xContext, aConfig,
231 !aEventName.equalsAscii("onFirstVisibleTask")));
232
233 return uno::Any();
234 }
235
236 //------------------------------------------------------------------------------
handleExtensionUpdates(const uno::Sequence<beans::NamedValue> & rListProp)237 void UpdateCheckJob::handleExtensionUpdates( const uno::Sequence< beans::NamedValue > &rListProp )
238 {
239 try {
240 uno::Sequence< uno::Sequence< rtl::OUString > > aList =
241 getValue< uno::Sequence< uno::Sequence< rtl::OUString > > > ( rListProp, "updateList" );
242 bool bPrepareOnly = getValue< bool > ( rListProp, "prepareOnly" );
243
244 // we will first store any new found updates and then check, if there are any
245 // pending updates.
246 storeExtensionUpdateInfos( m_xContext, aList );
247
248 if ( bPrepareOnly )
249 return;
250
251 bool bHasUpdates = checkForPendingUpdates( m_xContext );
252
253 rtl::Reference<UpdateCheck> aController( UpdateCheck::get() );
254 if ( ! aController.is() )
255 return;
256
257 aController->setHasExtensionUpdates( bHasUpdates );
258
259 if ( ! aController->hasOfficeUpdate() )
260 {
261 if ( bHasUpdates )
262 aController->setUIState( UPDATESTATE_EXT_UPD_AVAIL, true );
263 else
264 aController->setUIState( UPDATESTATE_NO_UPDATE_AVAIL, true );
265 }
266 }
267 catch( const uno::Exception& e )
268 {
269 OSL_TRACE( "Caught exception: %s\n thread terminated.\n",
270 rtl::OUStringToOString(e.Message, RTL_TEXTENCODING_UTF8).getStr());
271 }
272 }
273
274 //------------------------------------------------------------------------------
275
276 rtl::OUString SAL_CALL
getImplementationName()277 UpdateCheckJob::getImplementationName() throw (uno::RuntimeException)
278 {
279 return getImplName();
280 }
281
282 //------------------------------------------------------------------------------
283
284 uno::Sequence< rtl::OUString > SAL_CALL
getSupportedServiceNames()285 UpdateCheckJob::getSupportedServiceNames() throw (uno::RuntimeException)
286 {
287 return getServiceNames();
288 }
289
290 //------------------------------------------------------------------------------
291
292 sal_Bool SAL_CALL
supportsService(rtl::OUString const & serviceName)293 UpdateCheckJob::supportsService( rtl::OUString const & serviceName ) throw (uno::RuntimeException)
294 {
295 uno::Sequence< rtl::OUString > aServiceNameList = getServiceNames();
296
297 for( sal_Int32 n=0; n < aServiceNameList.getLength(); n++ )
298 if( aServiceNameList[n].equals(serviceName) )
299 return sal_True;
300
301 return sal_False;
302 }
303
304 //------------------------------------------------------------------------------
305 // XEventListener
disposing(lang::EventObject const & rEvt)306 void SAL_CALL UpdateCheckJob::disposing( lang::EventObject const & rEvt )
307 throw ( uno::RuntimeException )
308 {
309 bool shutDown = ( rEvt.Source == m_xDesktop );
310
311 if ( shutDown && m_xDesktop.is() )
312 {
313 m_xDesktop->removeTerminateListener( this );
314 m_xDesktop.clear();
315 }
316 }
317
318 //------------------------------------------------------------------------------
319 // XTerminateListener
queryTermination(lang::EventObject const &)320 void SAL_CALL UpdateCheckJob::queryTermination( lang::EventObject const & )
321 throw ( frame::TerminationVetoException, uno::RuntimeException )
322 {
323 }
324
325 //------------------------------------------------------------------------------
notifyTermination(lang::EventObject const &)326 void SAL_CALL UpdateCheckJob::notifyTermination( lang::EventObject const & )
327 throw ( uno::RuntimeException )
328 {
329 if ( m_pInitThread.get() != 0 )
330 {
331 m_pInitThread->setTerminating();
332 m_pInitThread->join();
333 }
334 }
335
336 } // anonymous namespace
337
338 //------------------------------------------------------------------------------
339
340 static uno::Reference<uno::XInterface> SAL_CALL
createJobInstance(const uno::Reference<uno::XComponentContext> & xContext)341 createJobInstance(const uno::Reference<uno::XComponentContext>& xContext)
342 {
343 return *new UpdateCheckJob(xContext);
344 }
345
346 //------------------------------------------------------------------------------
347
348 static uno::Reference<uno::XInterface> SAL_CALL
createConfigInstance(const uno::Reference<uno::XComponentContext> & xContext)349 createConfigInstance(const uno::Reference<uno::XComponentContext>& xContext)
350 {
351 return *UpdateCheckConfig::get(xContext, *UpdateCheck::get());
352 }
353
354 //------------------------------------------------------------------------------
355
356 static const cppu::ImplementationEntry kImplementations_entries[] =
357 {
358 {
359 createJobInstance,
360 UpdateCheckJob::getImplName,
361 UpdateCheckJob::getServiceNames,
362 cppu::createSingleComponentFactory,
363 NULL,
364 0
365 },
366 {
367 createConfigInstance,
368 UpdateCheckConfig::getImplName,
369 UpdateCheckConfig::getServiceNames,
370 cppu::createSingleComponentFactory,
371 NULL,
372 0
373 },
374 { NULL, NULL, NULL, NULL, NULL, 0 }
375 } ;
376
377 //------------------------------------------------------------------------------
378
379 extern "C" void SAL_CALL
component_getImplementationEnvironment(const sal_Char ** aEnvTypeName,uno_Environment **)380 component_getImplementationEnvironment( const sal_Char **aEnvTypeName, uno_Environment **)
381 {
382 *aEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ;
383 }
384
385 //------------------------------------------------------------------------------
386
387 extern "C" void *
component_getFactory(const sal_Char * pszImplementationName,void * pServiceManager,void * pRegistryKey)388 component_getFactory(const sal_Char *pszImplementationName, void *pServiceManager, void *pRegistryKey)
389 {
390 return cppu::component_getFactoryHelper(
391 pszImplementationName,
392 pServiceManager,
393 pRegistryKey,
394 kImplementations_entries) ;
395 }
396