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>
24 #include <com/sun/star/embed/EmbedUpdateModes.hpp>
25 #include <com/sun/star/embed/EmbedStates.hpp>
26 #include <com/sun/star/embed/WrongStateException.hpp>
27 #include <com/sun/star/lang/NoSupportException.hpp>
28 #include <com/sun/star/lang/XComponent.hpp>
29 #include <com/sun/star/lang/DisposedException.hpp>
31 #include <comphelper/multicontainer2.hxx>
32 #include <comphelper/sequenceashashmap.hxx>
33 #include <cppuhelper/supportsservice.hxx>
34 #include <osl/diagnose.h>
36 #include <oleembobj.hxx>
38 #include "olepersist.hxx"
40 #include "ownview.hxx"
42 #include "olecomponent.hxx"
44 using namespace ::com::sun::star
;
47 OleEmbeddedObject::OleEmbeddedObject( uno::Reference
< uno::XComponentContext
> xContext
,
48 const uno::Sequence
< sal_Int8
>& aClassID
,
50 : m_bReadOnly( false )
51 , m_bDisposed( false )
52 , m_nObjectState( -1 )
53 , m_nTargetState( -1 )
54 , m_nUpdateMode ( embed::EmbedUpdateModes::ALWAYS_UPDATE
)
55 , m_xContext(std::move( xContext
))
56 , m_aClassID( aClassID
)
57 , m_aClassName(std::move( aClassName
))
58 , m_bWaitSaveCompleted( false )
59 , m_bNewVisReplInStream( true )
60 , m_bStoreLoaded( false )
61 , m_bVisReplInitialized( false )
62 , m_bVisReplInStream( false )
63 , m_bStoreVisRepl( false )
65 , m_bHasCachedSize( false )
66 , m_nCachedAspect( 0 )
67 , m_bHasSizeToSet( false )
69 , m_bGotStatus( false )
71 , m_nStatusAspect( 0 )
72 , m_bFromClipboard( false )
73 , m_bTriedConversion( false )
78 // In case of loading from persistent entry the classID of the object
79 // will be retrieved from the entry, during construction it is unknown
80 OleEmbeddedObject::OleEmbeddedObject( uno::Reference
< uno::XComponentContext
> xContext
, bool bLink
)
81 : m_bReadOnly( false )
82 , m_bDisposed( false )
83 , m_nObjectState( -1 )
84 , m_nTargetState( -1 )
85 , m_nUpdateMode( embed::EmbedUpdateModes::ALWAYS_UPDATE
)
86 , m_xContext(std::move( xContext
))
87 , m_bWaitSaveCompleted( false )
88 , m_bNewVisReplInStream( true )
89 , m_bStoreLoaded( false )
90 , m_bVisReplInitialized( false )
91 , m_bVisReplInStream( false )
92 , m_bStoreVisRepl( false )
94 , m_bHasCachedSize( false )
95 , m_nCachedAspect( 0 )
96 , m_bHasSizeToSet( false )
98 , m_bGotStatus( false )
100 , m_nStatusAspect( 0 )
101 , m_bFromClipboard( false )
102 , m_bTriedConversion( false )
107 // this constructor let object be initialized from clipboard
108 OleEmbeddedObject::OleEmbeddedObject( const uno::Reference
< uno::XComponentContext
>& xContext
)
109 : m_bReadOnly( false )
110 , m_bDisposed( false )
111 , m_nObjectState( -1 )
112 , m_nTargetState( -1 )
113 , m_nUpdateMode( embed::EmbedUpdateModes::ALWAYS_UPDATE
)
114 , m_xContext( xContext
)
115 , m_bWaitSaveCompleted( false )
116 , m_bNewVisReplInStream( true )
117 , m_bStoreLoaded( false )
118 , m_bVisReplInitialized( false )
119 , m_bVisReplInStream( false )
120 , m_bStoreVisRepl( false )
122 , m_bHasCachedSize( false )
123 , m_nCachedAspect( 0 )
124 , m_bHasSizeToSet( false )
125 , m_nAspectToSet( 0 )
126 , m_bGotStatus( false )
128 , m_nStatusAspect( 0 )
129 , m_bFromClipboard( true )
130 , m_bTriedConversion( false )
135 OleEmbeddedObject::~OleEmbeddedObject()
137 OSL_ENSURE( !m_pInterfaceContainer
&& !m_pOleComponent
&& !m_xObjectStream
.is(),
138 "The object is not closed! DISASTER is possible!" );
140 if ( m_pOleComponent
|| m_pInterfaceContainer
|| m_xObjectStream
.is() )
142 // the component must be cleaned during closing
143 osl_atomic_increment(&m_refCount
); // to avoid crash
146 } catch( const uno::Exception
& ) {}
149 if ( !m_aTempURL
.isEmpty() )
150 KillFile_Impl( m_aTempURL
, m_xContext
);
152 if ( !m_aTempDumpURL
.isEmpty() )
153 KillFile_Impl( m_aTempDumpURL
, m_xContext
);
157 void OleEmbeddedObject::MakeEventListenerNotification_Impl( const OUString
& aEventName
)
159 if ( !m_pInterfaceContainer
)
162 comphelper::OInterfaceContainerHelper2
* pContainer
=
163 m_pInterfaceContainer
->getContainer(
164 cppu::UnoType
<document::XEventListener
>::get());
165 if ( pContainer
== nullptr )
168 document::EventObject
aEvent( static_cast< ::cppu::OWeakObject
* >( this ), aEventName
);
169 comphelper::OInterfaceIteratorHelper2
pIterator(*pContainer
);
170 while (pIterator
.hasMoreElements())
174 static_cast<document::XEventListener
*>(pIterator
.next())->notifyEvent( aEvent
);
176 catch( const uno::RuntimeException
& )
183 void OleEmbeddedObject::StateChangeNotification_Impl( bool bBeforeChange
, sal_Int32 nOldState
, sal_Int32 nNewState
)
185 if ( m_pInterfaceContainer
)
187 comphelper::OInterfaceContainerHelper2
* pContainer
= m_pInterfaceContainer
->getContainer(
188 cppu::UnoType
<embed::XStateChangeListener
>::get());
189 if ( pContainer
!= nullptr )
191 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >( this ) );
192 comphelper::OInterfaceIteratorHelper2
pIterator(*pContainer
);
194 while (pIterator
.hasMoreElements())
200 static_cast<embed::XStateChangeListener
*>(pIterator
.next())->changingState( aSource
, nOldState
, nNewState
);
202 catch( const uno::Exception
& )
204 // even if the listener complains ignore it for now
211 static_cast<embed::XStateChangeListener
*>(pIterator
.next())->stateChanged( aSource
, nOldState
, nNewState
);
213 catch( const uno::Exception
& )
215 // if anything happened it is problem of listener, ignore it
224 void OleEmbeddedObject::GetRidOfComponent()
227 if ( m_pOleComponent
)
229 if ( m_nObjectState
!= -1 && m_nObjectState
!= embed::EmbedStates::LOADED
)
232 m_pOleComponent
->removeCloseListener( m_xClosePreventer
);
235 m_pOleComponent
->close( false );
237 catch( const uno::Exception
& )
239 // TODO: there should be a special listener to wait for component closing
240 // and to notify object, may be object itself can be such a listener
241 m_pOleComponent
->addCloseListener( m_xClosePreventer
);
245 m_pOleComponent
->disconnectEmbeddedObject();
246 m_pOleComponent
.clear();
252 void OleEmbeddedObject::Dispose()
254 if ( m_pInterfaceContainer
)
256 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >( this ) );
257 m_pInterfaceContainer
->disposeAndClear( aSource
);
258 m_pInterfaceContainer
.reset();
261 if ( m_xOwnView
.is() )
267 if ( m_pOleComponent
)
270 } catch( const uno::Exception
& )
273 throw; // TODO: there should be a special listener that will close object when
274 // component is finally closed
277 if ( m_xObjectStream
.is() )
279 uno::Reference
< lang::XComponent
> xComp( m_xObjectStream
, uno::UNO_QUERY
);
280 OSL_ENSURE( xComp
.is(), "Storage stream doesn't support XComponent!" );
286 } catch( const uno::Exception
& ) {}
288 m_xObjectStream
.clear();
291 m_xParentStorage
.clear();
297 uno::Sequence
< sal_Int8
> SAL_CALL
OleEmbeddedObject::getClassID()
299 // begin wrapping related part ====================
300 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
301 if ( xWrappedObject
.is() )
303 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
304 return xWrappedObject
->getClassID();
306 // end wrapping related part ====================
308 ::osl::MutexGuard
aGuard( m_aMutex
);
310 throw lang::DisposedException(); // TODO
316 OUString SAL_CALL
OleEmbeddedObject::getClassName()
318 // begin wrapping related part ====================
319 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
320 if ( xWrappedObject
.is() )
322 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
323 return xWrappedObject
->getClassName();
325 // end wrapping related part ====================
327 ::osl::MutexGuard
aGuard( m_aMutex
);
329 throw lang::DisposedException(); // TODO
335 void SAL_CALL
OleEmbeddedObject::setClassInfo(
336 const uno::Sequence
< sal_Int8
>& aClassID
, const OUString
& aClassName
)
338 // begin wrapping related part ====================
339 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
340 if ( xWrappedObject
.is() )
342 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
343 xWrappedObject
->setClassInfo( aClassID
, aClassName
);
346 // end wrapping related part ====================
348 // the object class info can not be changed explicitly
349 throw lang::NoSupportException(); //TODO:
353 uno::Reference
< util::XCloseable
> SAL_CALL
OleEmbeddedObject::getComponent()
355 // begin wrapping related part ====================
356 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
357 if ( xWrappedObject
.is() )
359 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
360 return xWrappedObject
->getComponent();
362 // end wrapping related part ====================
364 ::osl::MutexGuard
aGuard( m_aMutex
);
366 throw lang::DisposedException(); // TODO
368 if ( m_nObjectState
== -1 ) // || m_nObjectState == embed::EmbedStates::LOADED )
370 // the object is still not running
371 throw uno::RuntimeException( "The object is not loaded!",
372 static_cast< ::cppu::OWeakObject
* >(this) );
376 if (m_pOleComponent
.is())
378 return uno::Reference
< util::XCloseable
>( m_pOleComponent
);
382 assert(!m_pOleComponent
.is());
383 // TODO/LATER: Is it correct???
384 return uno::Reference
< util::XCloseable
>();
385 // throw uno::RuntimeException(); // TODO
389 void SAL_CALL
OleEmbeddedObject::addStateChangeListener( const uno::Reference
< embed::XStateChangeListener
>& xListener
)
391 // begin wrapping related part ====================
392 if ( m_xWrappedObject
.is() )
394 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
395 m_xWrappedObject
->addStateChangeListener( xListener
);
398 // end wrapping related part ====================
400 ::osl::MutexGuard
aGuard( m_aMutex
);
402 throw lang::DisposedException(); // TODO
404 if ( !m_pInterfaceContainer
)
405 m_pInterfaceContainer
.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex
));
407 m_pInterfaceContainer
->addInterface( cppu::UnoType
<embed::XStateChangeListener
>::get(),
412 void SAL_CALL
OleEmbeddedObject::removeStateChangeListener(
413 const uno::Reference
< embed::XStateChangeListener
>& xListener
)
415 // begin wrapping related part ====================
416 if ( m_xWrappedObject
.is() )
418 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
419 m_xWrappedObject
->removeStateChangeListener( xListener
);
422 // end wrapping related part ====================
424 ::osl::MutexGuard
aGuard( m_aMutex
);
425 if ( m_pInterfaceContainer
)
426 m_pInterfaceContainer
->removeInterface( cppu::UnoType
<embed::XStateChangeListener
>::get(),
431 void SAL_CALL
OleEmbeddedObject::close( sal_Bool bDeliverOwnership
)
433 // begin wrapping related part ====================
434 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
435 if ( xWrappedObject
.is() )
437 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
438 xWrappedObject
->close( bDeliverOwnership
);
441 // end wrapping related part ====================
443 ::osl::MutexGuard
aGuard( m_aMutex
);
445 throw lang::DisposedException(); // TODO
447 uno::Reference
< uno::XInterface
> xSelfHold( static_cast< ::cppu::OWeakObject
* >( this ) );
448 lang::EventObject
aSource( static_cast< ::cppu::OWeakObject
* >( this ) );
450 if ( m_pInterfaceContainer
)
452 comphelper::OInterfaceContainerHelper2
* pContainer
=
453 m_pInterfaceContainer
->getContainer( cppu::UnoType
<util::XCloseListener
>::get());
454 if ( pContainer
!= nullptr )
456 comphelper::OInterfaceIteratorHelper2
pIterator(*pContainer
);
457 while (pIterator
.hasMoreElements())
461 static_cast<util::XCloseListener
*>(pIterator
.next())->queryClosing( aSource
, bDeliverOwnership
);
463 catch( const uno::RuntimeException
& )
470 pContainer
= m_pInterfaceContainer
->getContainer(
471 cppu::UnoType
<util::XCloseListener
>::get());
472 if ( pContainer
!= nullptr )
474 comphelper::OInterfaceIteratorHelper2
pCloseIterator(*pContainer
);
475 while (pCloseIterator
.hasMoreElements())
479 static_cast<util::XCloseListener
*>(pCloseIterator
.next())->notifyClosing( aSource
);
481 catch( const uno::RuntimeException
& )
483 pCloseIterator
.remove();
493 void SAL_CALL
OleEmbeddedObject::addCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
495 // begin wrapping related part ====================
496 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
497 if ( xWrappedObject
.is() )
499 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
500 xWrappedObject
->addCloseListener( xListener
);
503 // end wrapping related part ====================
505 ::osl::MutexGuard
aGuard( m_aMutex
);
507 throw lang::DisposedException(); // TODO
509 if ( !m_pInterfaceContainer
)
510 m_pInterfaceContainer
.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex
));
512 m_pInterfaceContainer
->addInterface( cppu::UnoType
<util::XCloseListener
>::get(), xListener
);
516 void SAL_CALL
OleEmbeddedObject::removeCloseListener( const uno::Reference
< util::XCloseListener
>& xListener
)
518 // begin wrapping related part ====================
519 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
520 if ( xWrappedObject
.is() )
522 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
523 xWrappedObject
->removeCloseListener( xListener
);
526 // end wrapping related part ====================
528 ::osl::MutexGuard
aGuard( m_aMutex
);
530 throw lang::DisposedException(); // TODO
532 if ( m_pInterfaceContainer
)
533 m_pInterfaceContainer
->removeInterface( cppu::UnoType
<util::XCloseListener
>::get(),
538 void SAL_CALL
OleEmbeddedObject::addEventListener( const uno::Reference
< document::XEventListener
>& xListener
)
540 // begin wrapping related part ====================
541 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
542 if ( xWrappedObject
.is() )
544 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
545 xWrappedObject
->addEventListener( xListener
);
548 // end wrapping related part ====================
550 ::osl::MutexGuard
aGuard( m_aMutex
);
552 throw lang::DisposedException(); // TODO
554 if ( !m_pInterfaceContainer
)
555 m_pInterfaceContainer
.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex
));
557 m_pInterfaceContainer
->addInterface( cppu::UnoType
<document::XEventListener
>::get(), xListener
);
561 void SAL_CALL
OleEmbeddedObject::removeEventListener(
562 const uno::Reference
< document::XEventListener
>& xListener
)
564 // begin wrapping related part ====================
565 uno::Reference
< embed::XEmbeddedObject
> xWrappedObject
= m_xWrappedObject
;
566 if ( xWrappedObject
.is() )
568 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
569 xWrappedObject
->removeEventListener( xListener
);
572 // end wrapping related part ====================
574 ::osl::MutexGuard
aGuard( m_aMutex
);
576 throw lang::DisposedException(); // TODO
578 if ( m_pInterfaceContainer
)
579 m_pInterfaceContainer
->removeInterface( cppu::UnoType
<document::XEventListener
>::get(),
583 // XInplaceObject ( wrapper related implementation )
585 void SAL_CALL
OleEmbeddedObject::setObjectRectangles( const awt::Rectangle
& aPosRect
,
586 const awt::Rectangle
& aClipRect
)
588 // begin wrapping related part ====================
589 uno::Reference
< embed::XInplaceObject
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
590 if ( xWrappedObject
.is() )
592 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
593 xWrappedObject
->setObjectRectangles( aPosRect
, aClipRect
);
596 // end wrapping related part ====================
598 throw embed::WrongStateException();
602 void SAL_CALL
OleEmbeddedObject::enableModeless( sal_Bool bEnable
)
604 // begin wrapping related part ====================
605 uno::Reference
< embed::XInplaceObject
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
606 if ( xWrappedObject
.is() )
608 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
609 xWrappedObject
->enableModeless( bEnable
);
612 // end wrapping related part ====================
614 throw embed::WrongStateException();
618 void SAL_CALL
OleEmbeddedObject::translateAccelerators(
619 const uno::Sequence
< awt::KeyEvent
>& aKeys
)
621 // begin wrapping related part ====================
622 uno::Reference
< embed::XInplaceObject
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
623 if ( xWrappedObject
.is() )
625 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
626 xWrappedObject
->translateAccelerators( aKeys
);
629 // end wrapping related part ====================
635 css::uno::Reference
< css::uno::XInterface
> SAL_CALL
OleEmbeddedObject::getParent()
637 // begin wrapping related part ====================
638 uno::Reference
< container::XChild
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
639 if ( xWrappedObject
.is() )
641 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
642 return xWrappedObject
->getParent();
644 // end wrapping related part ====================
650 void SAL_CALL
OleEmbeddedObject::setParent( const css::uno::Reference
< css::uno::XInterface
>& xParent
)
652 // begin wrapping related part ====================
653 uno::Reference
< container::XChild
> xWrappedObject( m_xWrappedObject
, uno::UNO_QUERY
);
654 if ( xWrappedObject
.is() )
656 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
657 xWrappedObject
->setParent( xParent
);
660 // end wrapping related part ====================
665 void OleEmbeddedObject::setStream(const css::uno::Reference
<css::io::XStream
>& xStream
)
667 m_xObjectStream
= xStream
;
670 css::uno::Reference
<css::io::XStream
> OleEmbeddedObject::getStream()
672 return m_xObjectStream
;
675 void OleEmbeddedObject::initialize(const uno::Sequence
<uno::Any
>& rArguments
)
677 if (!rArguments
.hasElements())
680 comphelper::SequenceAsHashMap
aValues(rArguments
[0]);
681 auto it
= aValues
.find("StreamReadOnly");
682 if (it
!= aValues
.end())
683 it
->second
>>= m_bStreamReadOnly
;
686 OUString SAL_CALL
OleEmbeddedObject::getImplementationName()
688 return "com.sun.star.comp.embed.OleEmbeddedObject";
691 sal_Bool SAL_CALL
OleEmbeddedObject::supportsService(const OUString
& ServiceName
)
693 return cppu::supportsService(this, ServiceName
);
696 uno::Sequence
<OUString
> SAL_CALL
OleEmbeddedObject::getSupportedServiceNames()
698 return { "com.sun.star.comp.embed.OleEmbeddedObject" };
701 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */