Version 6.4.0.3, tag libreoffice-6.4.0.3
[LibreOffice.git] / embeddedobj / source / commonembedding / miscobj.cxx
blob5947fef7aca0aa6bffc1a10deada7275ac789fb0
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <commonembobj.hxx>
21 #include <com/sun/star/embed/EmbedStates.hpp>
22 #include <com/sun/star/embed/EmbedVerbs.hpp>
23 #include <com/sun/star/embed/XStorage.hpp>
24 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
25 #include <com/sun/star/embed/XInplaceClient.hpp>
26 #include <com/sun/star/lang/DisposedException.hpp>
27 #include <com/sun/star/lang/NoSupportException.hpp>
28 #include <com/sun/star/beans/NamedValue.hpp>
30 #include <cppuhelper/queryinterface.hxx>
31 #include <cppuhelper/interfacecontainer.h>
32 #include <comphelper/mimeconfighelper.hxx>
34 #include <vcl/svapp.hxx>
36 #include "persistence.hxx"
38 using namespace ::com::sun::star;
41 OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< uno::XComponentContext >& rxContext,
42 const uno::Sequence< beans::NamedValue >& aObjProps )
43 : m_pInterfaceContainer( nullptr )
44 , m_bReadOnly( false )
45 , m_bDisposed( false )
46 , m_bClosed( false )
47 , m_nObjectState( -1 )
48 , m_nTargetState( -1 )
49 , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE )
50 , m_xContext( rxContext )
51 , m_nMiscStatus( 0 )
52 , m_bEmbeddedScriptSupport( true )
53 , m_bDocumentRecoverySupport( true )
54 , m_bWaitSaveCompleted( false )
55 , m_bIsLink( false )
56 , m_bLinkHasPassword( false )
57 , m_bHasClonedSize( false )
58 , m_nClonedMapUnit( 0 )
60 CommonInit_Impl( aObjProps );
64 OCommonEmbeddedObject::OCommonEmbeddedObject(
65 const uno::Reference< uno::XComponentContext >& rxContext,
66 const uno::Sequence< beans::NamedValue >& aObjProps,
67 const uno::Sequence< beans::PropertyValue >& aMediaDescr,
68 const uno::Sequence< beans::PropertyValue >& aObjectDescr )
69 : m_pInterfaceContainer( nullptr )
70 , m_bReadOnly( false )
71 , m_bDisposed( false )
72 , m_bClosed( false )
73 , m_nObjectState( embed::EmbedStates::LOADED )
74 , m_nTargetState( -1 )
75 , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE )
76 , m_xContext( rxContext )
77 , m_nMiscStatus( 0 )
78 , m_bEmbeddedScriptSupport( true )
79 , m_bDocumentRecoverySupport( true )
80 , m_bWaitSaveCompleted( false )
81 , m_bIsLink( true )
82 , m_bLinkHasPassword( false )
83 , m_bHasClonedSize( false )
84 , m_nClonedMapUnit( 0 )
86 // linked object has no own persistence so it is in loaded state starting from creation
87 LinkInit_Impl( aObjProps, aMediaDescr, aObjectDescr );
91 void OCommonEmbeddedObject::CommonInit_Impl( const uno::Sequence< beans::NamedValue >& aObjectProps )
93 OSL_ENSURE( m_xContext.is(), "No ServiceFactory is provided!" );
94 if ( !m_xContext.is() )
95 throw uno::RuntimeException();
97 m_xDocHolder = new DocumentHolder( m_xContext, this );
99 // parse configuration entries
100 // TODO/LATER: in future UI names can be also provided here
101 for ( sal_Int32 nInd = 0; nInd < aObjectProps.getLength(); nInd++ )
103 if ( aObjectProps[nInd].Name == "ClassID" )
104 aObjectProps[nInd].Value >>= m_aClassID;
105 else if ( aObjectProps[nInd].Name == "ObjectDocumentServiceName" )
106 aObjectProps[nInd].Value >>= m_aDocServiceName;
107 else if ( aObjectProps[nInd].Name == "ObjectDocumentFilterName" )
108 aObjectProps[nInd].Value >>= m_aPresetFilterName;
109 else if ( aObjectProps[nInd].Name == "ObjectMiscStatus" )
110 aObjectProps[nInd].Value >>= m_nMiscStatus;
111 else if ( aObjectProps[nInd].Name == "ObjectVerbs" )
112 aObjectProps[nInd].Value >>= m_aObjectVerbs;
115 if ( m_aClassID.getLength() != 16 /*|| !m_aDocServiceName.getLength()*/ )
116 throw uno::RuntimeException(); // something goes really wrong
118 // accepted states
119 m_aAcceptedStates.realloc( NUM_SUPPORTED_STATES );
121 m_aAcceptedStates[0] = embed::EmbedStates::LOADED;
122 m_aAcceptedStates[1] = embed::EmbedStates::RUNNING;
123 m_aAcceptedStates[2] = embed::EmbedStates::INPLACE_ACTIVE;
124 m_aAcceptedStates[3] = embed::EmbedStates::UI_ACTIVE;
125 m_aAcceptedStates[4] = embed::EmbedStates::ACTIVE;
128 // intermediate states
129 // In the following table the first index points to starting state,
130 // the second one to the target state, and the sequence referenced by
131 // first two indexes contains intermediate states, that should be
132 // passed by object to reach the target state.
133 // If the sequence is empty that means that indirect switch from start
134 // state to the target state is forbidden, only if direct switch is possible
135 // the state can be reached.
137 m_pIntermediateStatesSeqs[0][2].realloc( 1 );
138 m_pIntermediateStatesSeqs[0][2][0] = embed::EmbedStates::RUNNING;
140 m_pIntermediateStatesSeqs[0][3].realloc( 2 );
141 m_pIntermediateStatesSeqs[0][3][0] = embed::EmbedStates::RUNNING;
142 m_pIntermediateStatesSeqs[0][3][1] = embed::EmbedStates::INPLACE_ACTIVE;
144 m_pIntermediateStatesSeqs[0][4].realloc( 1 );
145 m_pIntermediateStatesSeqs[0][4][0] = embed::EmbedStates::RUNNING;
147 m_pIntermediateStatesSeqs[1][3].realloc( 1 );
148 m_pIntermediateStatesSeqs[1][3][0] = embed::EmbedStates::INPLACE_ACTIVE;
150 m_pIntermediateStatesSeqs[2][0].realloc( 1 );
151 m_pIntermediateStatesSeqs[2][0][0] = embed::EmbedStates::RUNNING;
153 m_pIntermediateStatesSeqs[3][0].realloc( 2 );
154 m_pIntermediateStatesSeqs[3][0][0] = embed::EmbedStates::INPLACE_ACTIVE;
155 m_pIntermediateStatesSeqs[3][0][1] = embed::EmbedStates::RUNNING;
157 m_pIntermediateStatesSeqs[3][1].realloc( 1 );
158 m_pIntermediateStatesSeqs[3][1][0] = embed::EmbedStates::INPLACE_ACTIVE;
160 m_pIntermediateStatesSeqs[4][0].realloc( 1 );
161 m_pIntermediateStatesSeqs[4][0][0] = embed::EmbedStates::RUNNING;
163 // verbs table
164 sal_Int32 nVerbTableSize = 0;
165 for ( sal_Int32 nVerbInd = 0; nVerbInd < m_aObjectVerbs.getLength(); nVerbInd++ )
167 if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_PRIMARY )
169 m_aVerbTable.realloc( ++nVerbTableSize );
170 m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
171 m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
172 m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::UI_ACTIVE;
174 else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_SHOW )
176 m_aVerbTable.realloc( ++nVerbTableSize );
177 m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
178 m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
179 m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::UI_ACTIVE;
181 else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_OPEN )
183 m_aVerbTable.realloc( ++nVerbTableSize );
184 m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
185 m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
186 m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::ACTIVE;
188 else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_IPACTIVATE )
190 m_aVerbTable.realloc( ++nVerbTableSize );
191 m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
192 m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
193 m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::INPLACE_ACTIVE;
195 else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_UIACTIVATE )
197 m_aVerbTable.realloc( ++nVerbTableSize );
198 m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
199 m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
200 m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::UI_ACTIVE;
202 else if ( m_aObjectVerbs[nVerbInd].VerbID == embed::EmbedVerbs::MS_OLEVERB_HIDE )
204 m_aVerbTable.realloc( ++nVerbTableSize );
205 m_aVerbTable[nVerbTableSize - 1].realloc( 2 );
206 m_aVerbTable[nVerbTableSize - 1][0] = m_aObjectVerbs[nVerbInd].VerbID;
207 m_aVerbTable[nVerbTableSize - 1][1] = embed::EmbedStates::RUNNING;
213 void OCommonEmbeddedObject::LinkInit_Impl(
214 const uno::Sequence< beans::NamedValue >& aObjectProps,
215 const uno::Sequence< beans::PropertyValue >& aMediaDescr,
216 const uno::Sequence< beans::PropertyValue >& aObjectDescr )
218 // setPersistance has no effect on own links, so the complete initialization must be done here
220 for ( sal_Int32 nInd = 0; nInd < aMediaDescr.getLength(); nInd++ )
221 if ( aMediaDescr[nInd].Name == "URL" )
222 aMediaDescr[nInd].Value >>= m_aLinkURL;
223 else if ( aMediaDescr[nInd].Name == "FilterName" )
224 aMediaDescr[nInd].Value >>= m_aLinkFilterName;
226 OSL_ENSURE( m_aLinkURL.getLength() && m_aLinkFilterName.getLength(), "Filter and URL must be provided!" );
228 m_bReadOnly = true;
229 if ( m_aLinkFilterName.getLength() )
231 ::comphelper::MimeConfigurationHelper aHelper( m_xContext );
232 OUString aExportFilterName = aHelper.GetExportFilterFromImportFilter( m_aLinkFilterName );
233 m_bReadOnly = aExportFilterName != m_aLinkFilterName;
236 m_aDocMediaDescriptor = GetValuableArgs_Impl( aMediaDescr, false );
238 uno::Reference< frame::XDispatchProviderInterceptor > xDispatchInterceptor;
239 for ( sal_Int32 nObjInd = 0; nObjInd < aObjectDescr.getLength(); nObjInd++ )
240 if ( aObjectDescr[nObjInd].Name == "OutplaceDispatchInterceptor" )
242 aObjectDescr[nObjInd].Value >>= xDispatchInterceptor;
243 break;
245 else if ( aObjectDescr[nObjInd].Name == "Parent" )
247 aObjectDescr[nObjInd].Value >>= m_xParent;
250 CommonInit_Impl( aObjectProps );
252 if ( xDispatchInterceptor.is() )
253 m_xDocHolder->SetOutplaceDispatchInterceptor( xDispatchInterceptor );
257 OCommonEmbeddedObject::~OCommonEmbeddedObject()
259 if ( m_pInterfaceContainer || m_xDocHolder.is() )
261 osl_atomic_increment(&m_refCount);
262 try {
263 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
265 if ( m_pInterfaceContainer )
267 m_pInterfaceContainer->disposeAndClear( aSource );
269 delete m_pInterfaceContainer;
270 m_pInterfaceContainer = nullptr;
272 } catch( const uno::Exception& ) {}
274 try {
275 if ( m_xDocHolder.is() )
277 m_xDocHolder->CloseFrame();
278 try {
279 m_xDocHolder->CloseDocument( true, true );
280 } catch ( const uno::Exception& ) {}
281 m_xDocHolder->FreeOffice();
283 m_xDocHolder.clear();
285 } catch( const uno::Exception& ) {}
290 void OCommonEmbeddedObject::requestPositioning( const awt::Rectangle& aRect )
292 // the method is called in case object is inplace active and the object window was resized
294 OSL_ENSURE( m_xClientSite.is(), "The client site must be set for inplace active object!" );
295 if ( m_xClientSite.is() )
297 uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, uno::UNO_QUERY );
299 OSL_ENSURE( xInplaceClient.is(), "The client site must support XInplaceClient to allow inplace activation!" );
300 if ( xInplaceClient.is() )
302 try {
303 xInplaceClient->changedPlacement( aRect );
305 catch( const uno::Exception& )
307 OSL_FAIL( "Exception on request to resize!" );
314 void OCommonEmbeddedObject::PostEvent_Impl( const OUString& aEventName )
316 if ( m_pInterfaceContainer )
318 ::cppu::OInterfaceContainerHelper* pIC = m_pInterfaceContainer->getContainer(
319 cppu::UnoType<document::XEventListener>::get());
320 if( pIC )
322 document::EventObject aEvent;
323 aEvent.EventName = aEventName;
324 aEvent.Source.set( static_cast< ::cppu::OWeakObject* >( this ) );
325 // For now all the events are sent as object events
326 // aEvent.Source = ( xSource.is() ? xSource
327 // : uno::Reference< uno::XInterface >( static_cast< ::cppu::OWeakObject* >( this ) ) );
328 ::cppu::OInterfaceIteratorHelper aIt( *pIC );
329 while( aIt.hasMoreElements() )
333 static_cast<document::XEventListener *>(aIt.next())->notifyEvent( aEvent );
335 catch( const uno::RuntimeException& )
337 aIt.remove();
340 // the listener could dispose the object.
341 if ( m_bDisposed )
342 return;
349 uno::Any SAL_CALL OCommonEmbeddedObject::queryInterface( const uno::Type& rType )
351 uno::Any aReturn;
353 if ( rType == cppu::UnoType<embed::XEmbeddedObject>::get() )
355 void * p = static_cast< embed::XEmbeddedObject * >( this );
356 return uno::Any( &p, rType );
358 else if (rType == cppu::UnoType<embed::XEmbedPersist2>::get())
360 void* p = static_cast<embed::XEmbedPersist2*>(this);
361 return uno::Any(&p, rType);
363 else
364 aReturn = ::cppu::queryInterface(
365 rType,
366 static_cast< embed::XInplaceObject* >( this ),
367 static_cast< embed::XVisualObject* >( this ),
368 static_cast< embed::XCommonEmbedPersist* >( static_cast< embed::XEmbedPersist* >( this ) ),
369 static_cast< embed::XEmbedPersist* >( this ),
370 static_cast< embed::XLinkageSupport* >( this ),
371 static_cast< embed::XStateChangeBroadcaster* >( this ),
372 static_cast< embed::XClassifiedObject* >( this ),
373 static_cast< embed::XComponentSupplier* >( this ),
374 static_cast< util::XCloseable* >( this ),
375 static_cast< container::XChild* >( this ),
376 static_cast< chart2::XDefaultSizeTransmitter* >( this ),
377 static_cast< document::XEventBroadcaster* >( this ) );
379 if ( aReturn.hasValue() )
380 return aReturn;
381 else
382 return ::cppu::OWeakObject::queryInterface( rType ) ;
387 void SAL_CALL OCommonEmbeddedObject::acquire()
388 throw()
390 ::cppu::OWeakObject::acquire() ;
394 void SAL_CALL OCommonEmbeddedObject::release()
395 throw()
397 ::cppu::OWeakObject::release() ;
401 uno::Sequence< sal_Int8 > SAL_CALL OCommonEmbeddedObject::getClassID()
403 if ( m_bDisposed )
404 throw lang::DisposedException();
406 return m_aClassID;
409 OUString SAL_CALL OCommonEmbeddedObject::getClassName()
411 if ( m_bDisposed )
412 throw lang::DisposedException();
414 return m_aClassName;
417 void SAL_CALL OCommonEmbeddedObject::setClassInfo(
418 const uno::Sequence< sal_Int8 >& /*aClassID*/, const OUString& /*aClassName*/ )
420 // the object class info can not be changed explicitly
421 throw lang::NoSupportException(); //TODO:
425 uno::Reference< util::XCloseable > SAL_CALL OCommonEmbeddedObject::getComponent()
427 SolarMutexGuard aGuard;
428 if ( m_bDisposed )
429 throw lang::DisposedException(); // TODO
431 // add an exception
432 if ( m_nObjectState == -1 )
434 // the object is still not loaded
435 throw uno::RuntimeException( "Can't store object without persistence!",
436 static_cast< ::cppu::OWeakObject* >(this) );
439 return m_xDocHolder->GetComponent();
443 void SAL_CALL OCommonEmbeddedObject::addStateChangeListener( const uno::Reference< embed::XStateChangeListener >& xListener )
445 SolarMutexGuard aGuard;
446 if ( m_bDisposed )
447 throw lang::DisposedException(); // TODO
449 if ( !m_pInterfaceContainer )
450 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper( m_aMutex );
452 m_pInterfaceContainer->addInterface( cppu::UnoType<embed::XStateChangeListener>::get(),
453 xListener );
457 void SAL_CALL OCommonEmbeddedObject::removeStateChangeListener(
458 const uno::Reference< embed::XStateChangeListener >& xListener )
460 SolarMutexGuard aGuard;
461 if ( m_pInterfaceContainer )
462 m_pInterfaceContainer->removeInterface( cppu::UnoType<embed::XStateChangeListener>::get(),
463 xListener );
467 void SAL_CALL OCommonEmbeddedObject::close( sal_Bool bDeliverOwnership )
469 SolarMutexGuard aGuard;
470 if ( m_bClosed )
471 throw lang::DisposedException(); // TODO
473 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
474 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
476 if ( m_pInterfaceContainer )
478 ::cppu::OInterfaceContainerHelper* pContainer =
479 m_pInterfaceContainer->getContainer( cppu::UnoType<util::XCloseListener>::get());
480 if ( pContainer != nullptr )
482 ::cppu::OInterfaceIteratorHelper pIterator(*pContainer);
483 while (pIterator.hasMoreElements())
487 static_cast<util::XCloseListener*>(pIterator.next())->queryClosing( aSource, bDeliverOwnership );
489 catch( const uno::RuntimeException& )
491 pIterator.remove();
496 pContainer = m_pInterfaceContainer->getContainer(
497 cppu::UnoType<util::XCloseListener>::get());
498 if ( pContainer != nullptr )
500 ::cppu::OInterfaceIteratorHelper pCloseIterator(*pContainer);
501 while (pCloseIterator.hasMoreElements())
505 static_cast<util::XCloseListener*>(pCloseIterator.next())->notifyClosing( aSource );
507 catch( const uno::RuntimeException& )
509 pCloseIterator.remove();
514 m_pInterfaceContainer->disposeAndClear( aSource );
517 m_bDisposed = true; // the object is disposed now for outside
519 // it is possible that the document can not be closed, in this case if the argument is false
520 // the exception will be thrown otherwise in addition to exception the object must register itself
521 // as termination listener and listen for document events
523 if ( m_xDocHolder.is() )
525 m_xDocHolder->CloseFrame();
527 try {
528 m_xDocHolder->CloseDocument( bDeliverOwnership, bDeliverOwnership );
530 catch( const uno::Exception& )
532 if ( bDeliverOwnership )
534 m_xDocHolder.clear();
535 m_bClosed = true;
538 throw;
541 m_xDocHolder->FreeOffice();
543 m_xDocHolder.clear();
546 // TODO: for now the storage will be disposed by the object, but after the document
547 // will use the storage, the storage will be disposed by the document and recreated by the object
548 if ( m_xObjectStorage.is() )
550 try {
551 m_xObjectStorage->dispose();
552 } catch ( const uno::Exception& ) {}
554 m_xObjectStorage.clear();
555 m_xRecoveryStorage.clear();
558 m_bClosed = true; // the closing succeeded
562 void SAL_CALL OCommonEmbeddedObject::addCloseListener( const uno::Reference< util::XCloseListener >& xListener )
564 SolarMutexGuard aGuard;
565 if ( m_bDisposed )
566 throw lang::DisposedException(); // TODO
568 if ( !m_pInterfaceContainer )
569 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper(m_aMutex);
571 m_pInterfaceContainer->addInterface( cppu::UnoType<util::XCloseListener>::get(), xListener );
575 void SAL_CALL OCommonEmbeddedObject::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
577 SolarMutexGuard aGuard;
578 if ( m_pInterfaceContainer )
579 m_pInterfaceContainer->removeInterface( cppu::UnoType<util::XCloseListener>::get(),
580 xListener );
584 void SAL_CALL OCommonEmbeddedObject::addEventListener( const uno::Reference< document::XEventListener >& xListener )
586 SolarMutexGuard aGuard;
587 if ( m_bDisposed )
588 throw lang::DisposedException(); // TODO
590 if ( !m_pInterfaceContainer )
591 m_pInterfaceContainer = new ::cppu::OMultiTypeInterfaceContainerHelper(m_aMutex);
593 m_pInterfaceContainer->addInterface( cppu::UnoType<document::XEventListener>::get(), xListener );
597 void SAL_CALL OCommonEmbeddedObject::removeEventListener( const uno::Reference< document::XEventListener >& xListener )
599 SolarMutexGuard aGuard;
600 if ( m_pInterfaceContainer )
601 m_pInterfaceContainer->removeInterface( cppu::UnoType<document::XEventListener>::get(),
602 xListener );
605 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */