remove assert looking for new compatibilityMode DOCX
[LibreOffice.git] / embeddedobj / source / msole / olemisc.cxx
blobe3159e99fd0fd7aa27b447b2f4d14f4f1b879b3f
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 <sal/config.h>
22 #include <cassert>
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>
37 #include <utility>
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,
49 OUString aClassName )
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 )
64 , m_bIsLink( false )
65 , m_bHasCachedSize( false )
66 , m_nCachedAspect( 0 )
67 , m_bHasSizeToSet( false )
68 , m_nAspectToSet( 0 )
69 , m_bGotStatus( false )
70 , m_nStatus( 0 )
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 )
93 , m_bIsLink( bLink )
94 , m_bHasCachedSize( false )
95 , m_nCachedAspect( 0 )
96 , m_bHasSizeToSet( false )
97 , m_nAspectToSet( 0 )
98 , m_bGotStatus( false )
99 , m_nStatus( 0 )
100 , m_nStatusAspect( 0 )
101 , m_bFromClipboard( false )
102 , m_bTriedConversion( false )
105 #ifdef _WIN32
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 )
121 , m_bIsLink( false )
122 , m_bHasCachedSize( false )
123 , m_nCachedAspect( 0 )
124 , m_bHasSizeToSet( false )
125 , m_nAspectToSet( 0 )
126 , m_bGotStatus( false )
127 , m_nStatus( 0 )
128 , m_nStatusAspect( 0 )
129 , m_bFromClipboard( true )
130 , m_bTriedConversion( false )
133 #endif
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
144 try {
145 Dispose();
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,
158 osl::ResettableMutexGuard& guard )
160 if ( !m_pInterfaceContainer )
161 return;
163 comphelper::OInterfaceContainerHelper2* pContainer =
164 m_pInterfaceContainer->getContainer(
165 cppu::UnoType<document::XEventListener>::get());
166 if ( pContainer == nullptr )
167 return;
169 auto proc = [&guard, aEvent = document::EventObject(getXWeak(), aEventName)](
170 const uno::Reference<document::XEventListener>& xListener)
174 osl::ResettableMutexGuardScopedReleaser area(guard);
175 xListener->notifyEvent(aEvent);
177 catch (const lang::DisposedException&)
179 throw; // forEach handles this
181 catch (const uno::RuntimeException&)
185 pContainer->forEach<document::XEventListener>(proc);
187 #ifdef _WIN32
189 void OleEmbeddedObject::StateChangeNotification_Impl( bool bBeforeChange, sal_Int32 nOldState, sal_Int32 nNewState,
190 osl::ResettableMutexGuard& guard )
192 if (!m_pInterfaceContainer)
193 return;
195 comphelper::OInterfaceContainerHelper2* pContainer = m_pInterfaceContainer->getContainer(
196 cppu::UnoType<embed::XStateChangeListener>::get());
197 if (!pContainer)
198 return;
200 auto proc
201 = [bBeforeChange, nOldState, nNewState, &guard, aSource = lang::EventObject(getXWeak())](
202 const uno::Reference<embed::XStateChangeListener>& xListener)
206 osl::ResettableMutexGuardScopedReleaser area(guard);
207 if (bBeforeChange)
208 xListener->changingState(aSource, nOldState, nNewState);
209 else
210 xListener->stateChanged(aSource, nOldState, nNewState);
212 catch (const lang::DisposedException&)
214 throw; // forEach handles this
216 catch (const uno::Exception&)
218 // even if the listener complains ignore it for now
221 pContainer->forEach<embed::XStateChangeListener>(proc);
223 #endif
225 void OleEmbeddedObject::GetRidOfComponent(osl::ResettableMutexGuard* guard)
227 #ifdef _WIN32
228 if ( m_pOleComponent )
230 if ( m_nObjectState != -1 && m_nObjectState != embed::EmbedStates::LOADED )
231 SaveObject_Impl();
233 m_pOleComponent->removeCloseListener( m_xClosePreventer );
234 // When releasing the guard below, avoid a case when two threads are doing the same;
235 // store the reference on stack and clear m_pOleComponent in advance
236 rtl::Reference<OleComponent> pOleComponent(std::move(m_pOleComponent));
239 std::optional<osl::ResettableMutexGuardScopedReleaser> oReleaser;
240 if (guard)
241 oReleaser.emplace(*guard);
242 pOleComponent->close(false);
244 catch( const uno::Exception& )
246 m_pOleComponent = std::move(pOleComponent);
247 // TODO: there should be a special listener to wait for component closing
248 // and to notify object, may be object itself can be such a listener
249 m_pOleComponent->addCloseListener( m_xClosePreventer );
250 throw;
253 pOleComponent->disconnectEmbeddedObject();
255 #else
256 (void)guard;
257 #endif
261 void OleEmbeddedObject::Dispose(osl::ResettableMutexGuard* guard)
263 if ( m_pInterfaceContainer )
265 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
266 m_pInterfaceContainer->disposeAndClear( aSource );
267 m_pInterfaceContainer.reset();
270 if ( m_xOwnView.is() )
272 m_xOwnView->Close();
273 m_xOwnView.clear();
276 if ( m_pOleComponent )
277 try {
278 GetRidOfComponent(guard);
279 } catch( const uno::Exception& )
281 m_bDisposed = true;
282 throw; // TODO: there should be a special listener that will close object when
283 // component is finally closed
286 if ( m_xObjectStream.is() )
288 uno::Reference< lang::XComponent > xComp( m_xObjectStream, uno::UNO_QUERY );
289 OSL_ENSURE( xComp.is(), "Storage stream doesn't support XComponent!" );
291 if ( xComp.is() )
293 try {
294 xComp->dispose();
295 } catch( const uno::Exception& ) {}
297 m_xObjectStream.clear();
300 m_xParentStorage.clear();
301 m_xClientSite.clear();
302 m_xClosePreventer.clear();
303 m_xNewCachedVisRepl.clear();
304 m_xNewParentStorage.clear();
305 m_xNewObjectStream.clear();
306 m_xCachedVisualRepresentation.clear();
307 m_xWrappedObject.clear();
308 m_xParent.clear();
309 m_pOleComponent.clear();
311 m_bDisposed = true;
315 uno::Sequence< sal_Int8 > SAL_CALL OleEmbeddedObject::getClassID()
317 // begin wrapping related part ====================
318 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
319 if ( xWrappedObject.is() )
321 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
322 return xWrappedObject->getClassID();
324 // end wrapping related part ====================
326 ::osl::MutexGuard aGuard( m_aMutex );
327 if ( m_bDisposed )
328 throw lang::DisposedException(); // TODO
330 return m_aClassID;
334 OUString SAL_CALL OleEmbeddedObject::getClassName()
336 // begin wrapping related part ====================
337 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
338 if ( xWrappedObject.is() )
340 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
341 return xWrappedObject->getClassName();
343 // end wrapping related part ====================
345 ::osl::MutexGuard aGuard( m_aMutex );
346 if ( m_bDisposed )
347 throw lang::DisposedException(); // TODO
349 return m_aClassName;
353 void SAL_CALL OleEmbeddedObject::setClassInfo(
354 const uno::Sequence< sal_Int8 >& aClassID, const OUString& aClassName )
356 // begin wrapping related part ====================
357 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
358 if ( xWrappedObject.is() )
360 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
361 xWrappedObject->setClassInfo( aClassID, aClassName );
362 return;
364 // end wrapping related part ====================
366 // the object class info can not be changed explicitly
367 throw lang::NoSupportException(); //TODO:
371 uno::Reference< util::XCloseable > SAL_CALL OleEmbeddedObject::getComponent()
373 // begin wrapping related part ====================
374 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
375 if ( xWrappedObject.is() )
377 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
378 return xWrappedObject->getComponent();
380 // end wrapping related part ====================
382 ::osl::MutexGuard aGuard( m_aMutex );
383 if ( m_bDisposed )
384 throw lang::DisposedException(); // TODO
386 if ( m_nObjectState == -1 ) // || m_nObjectState == embed::EmbedStates::LOADED )
388 // the object is still not running
389 throw uno::RuntimeException( u"The object is not loaded!"_ustr,
390 static_cast< ::cppu::OWeakObject* >(this) );
393 #if defined(_WIN32)
394 if (m_pOleComponent.is())
396 return uno::Reference< util::XCloseable >( m_pOleComponent );
398 #endif
400 assert(!m_pOleComponent.is());
401 // TODO/LATER: Is it correct???
402 return uno::Reference< util::XCloseable >();
403 // throw uno::RuntimeException(); // TODO
407 void SAL_CALL OleEmbeddedObject::addStateChangeListener( const uno::Reference< embed::XStateChangeListener >& xListener )
409 // begin wrapping related part ====================
410 if ( m_xWrappedObject.is() )
412 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
413 m_xWrappedObject->addStateChangeListener( xListener );
414 return;
416 // end wrapping related part ====================
418 ::osl::MutexGuard aGuard( m_aMutex );
419 if ( m_bDisposed )
420 throw lang::DisposedException(); // TODO
422 if ( !m_pInterfaceContainer )
423 m_pInterfaceContainer.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex ));
425 m_pInterfaceContainer->addInterface( cppu::UnoType<embed::XStateChangeListener>::get(),
426 xListener );
430 void SAL_CALL OleEmbeddedObject::removeStateChangeListener(
431 const uno::Reference< embed::XStateChangeListener >& xListener )
433 // begin wrapping related part ====================
434 if ( m_xWrappedObject.is() )
436 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
437 m_xWrappedObject->removeStateChangeListener( xListener );
438 return;
440 // end wrapping related part ====================
442 ::osl::MutexGuard aGuard( m_aMutex );
443 if ( m_pInterfaceContainer )
444 m_pInterfaceContainer->removeInterface( cppu::UnoType<embed::XStateChangeListener>::get(),
445 xListener );
449 void SAL_CALL OleEmbeddedObject::close( sal_Bool bDeliverOwnership )
451 // begin wrapping related part ====================
452 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
453 if ( xWrappedObject.is() )
455 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
456 xWrappedObject->close( bDeliverOwnership );
457 return;
459 // end wrapping related part ====================
461 osl::ResettableMutexGuard aGuard(m_aMutex);
462 if ( m_bDisposed )
463 throw lang::DisposedException(); // TODO
465 uno::Reference< uno::XInterface > xSelfHold( static_cast< ::cppu::OWeakObject* >( this ) );
466 lang::EventObject aSource( static_cast< ::cppu::OWeakObject* >( this ) );
468 if ( m_pInterfaceContainer )
470 comphelper::OInterfaceContainerHelper2* pContainer =
471 m_pInterfaceContainer->getContainer( cppu::UnoType<util::XCloseListener>::get());
472 if ( pContainer != nullptr )
474 comphelper::OInterfaceIteratorHelper2 pIterator(*pContainer);
475 while (pIterator.hasMoreElements())
479 static_cast<util::XCloseListener*>(pIterator.next())->queryClosing( aSource, bDeliverOwnership );
481 catch( const uno::RuntimeException& )
483 pIterator.remove();
488 pContainer = m_pInterfaceContainer->getContainer(
489 cppu::UnoType<util::XCloseListener>::get());
490 if ( pContainer != nullptr )
492 comphelper::OInterfaceIteratorHelper2 pCloseIterator(*pContainer);
493 while (pCloseIterator.hasMoreElements())
497 static_cast<util::XCloseListener*>(pCloseIterator.next())->notifyClosing( aSource );
499 catch( const uno::RuntimeException& )
501 pCloseIterator.remove();
507 Dispose(&aGuard);
511 void SAL_CALL OleEmbeddedObject::addCloseListener( const uno::Reference< util::XCloseListener >& xListener )
513 // begin wrapping related part ====================
514 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
515 if ( xWrappedObject.is() )
517 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
518 xWrappedObject->addCloseListener( xListener );
519 return;
521 // end wrapping related part ====================
523 ::osl::MutexGuard aGuard( m_aMutex );
524 if ( m_bDisposed )
525 throw lang::DisposedException(); // TODO
527 if ( !m_pInterfaceContainer )
528 m_pInterfaceContainer.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex ));
530 m_pInterfaceContainer->addInterface( cppu::UnoType<util::XCloseListener>::get(), xListener );
534 void SAL_CALL OleEmbeddedObject::removeCloseListener( const uno::Reference< util::XCloseListener >& xListener )
536 // begin wrapping related part ====================
537 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
538 if ( xWrappedObject.is() )
540 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
541 xWrappedObject->removeCloseListener( xListener );
542 return;
544 // end wrapping related part ====================
546 ::osl::MutexGuard aGuard( m_aMutex );
547 if ( m_bDisposed )
548 throw lang::DisposedException(); // TODO
550 if ( m_pInterfaceContainer )
551 m_pInterfaceContainer->removeInterface( cppu::UnoType<util::XCloseListener>::get(),
552 xListener );
556 void SAL_CALL OleEmbeddedObject::addEventListener( const uno::Reference< document::XEventListener >& xListener )
558 // begin wrapping related part ====================
559 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
560 if ( xWrappedObject.is() )
562 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
563 xWrappedObject->addEventListener( xListener );
564 return;
566 // end wrapping related part ====================
568 ::osl::MutexGuard aGuard( m_aMutex );
569 if ( m_bDisposed )
570 throw lang::DisposedException(); // TODO
572 if ( !m_pInterfaceContainer )
573 m_pInterfaceContainer.reset(new comphelper::OMultiTypeInterfaceContainerHelper2( m_aMutex ));
575 m_pInterfaceContainer->addInterface( cppu::UnoType<document::XEventListener>::get(), xListener );
579 void SAL_CALL OleEmbeddedObject::removeEventListener(
580 const uno::Reference< document::XEventListener >& xListener )
582 // begin wrapping related part ====================
583 uno::Reference< embed::XEmbeddedObject > xWrappedObject = m_xWrappedObject;
584 if ( xWrappedObject.is() )
586 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
587 xWrappedObject->removeEventListener( xListener );
588 return;
590 // end wrapping related part ====================
592 ::osl::MutexGuard aGuard( m_aMutex );
593 if ( m_bDisposed )
594 throw lang::DisposedException(); // TODO
596 if ( m_pInterfaceContainer )
597 m_pInterfaceContainer->removeInterface( cppu::UnoType<document::XEventListener>::get(),
598 xListener );
601 // XInplaceObject ( wrapper related implementation )
603 void SAL_CALL OleEmbeddedObject::setObjectRectangles( const awt::Rectangle& aPosRect,
604 const awt::Rectangle& aClipRect )
606 // begin wrapping related part ====================
607 uno::Reference< embed::XInplaceObject > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
608 if ( xWrappedObject.is() )
610 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
611 xWrappedObject->setObjectRectangles( aPosRect, aClipRect );
612 return;
614 // end wrapping related part ====================
616 throw embed::WrongStateException();
620 void SAL_CALL OleEmbeddedObject::enableModeless( sal_Bool bEnable )
622 // begin wrapping related part ====================
623 uno::Reference< embed::XInplaceObject > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
624 if ( xWrappedObject.is() )
626 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
627 xWrappedObject->enableModeless( bEnable );
628 return;
630 // end wrapping related part ====================
632 throw embed::WrongStateException();
636 void SAL_CALL OleEmbeddedObject::translateAccelerators(
637 const uno::Sequence< awt::KeyEvent >& aKeys )
639 // begin wrapping related part ====================
640 uno::Reference< embed::XInplaceObject > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
641 if ( xWrappedObject.is() )
643 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
644 xWrappedObject->translateAccelerators( aKeys );
645 return;
647 // end wrapping related part ====================
651 // XChild
653 css::uno::Reference< css::uno::XInterface > SAL_CALL OleEmbeddedObject::getParent()
655 // begin wrapping related part ====================
656 uno::Reference< container::XChild > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
657 if ( xWrappedObject.is() )
659 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
660 return xWrappedObject->getParent();
662 // end wrapping related part ====================
664 return m_xParent;
668 void SAL_CALL OleEmbeddedObject::setParent( const css::uno::Reference< css::uno::XInterface >& xParent )
670 // begin wrapping related part ====================
671 uno::Reference< container::XChild > xWrappedObject( m_xWrappedObject, uno::UNO_QUERY );
672 if ( xWrappedObject.is() )
674 // the object was converted to OOo embedded object, the current implementation is now only a wrapper
675 xWrappedObject->setParent( xParent );
676 return;
678 // end wrapping related part ====================
680 m_xParent = xParent;
683 void OleEmbeddedObject::setStream(const css::uno::Reference<css::io::XStream>& xStream)
685 m_xObjectStream = xStream;
688 css::uno::Reference<css::io::XStream> OleEmbeddedObject::getStream()
690 return m_xObjectStream;
693 void OleEmbeddedObject::initialize(const uno::Sequence<uno::Any>& rArguments)
695 if (!rArguments.hasElements())
696 return;
698 comphelper::SequenceAsHashMap aValues(rArguments[0]);
699 auto it = aValues.find(u"StreamReadOnly"_ustr);
700 if (it != aValues.end())
701 it->second >>= m_bStreamReadOnly;
704 OUString SAL_CALL OleEmbeddedObject::getImplementationName()
706 return u"com.sun.star.comp.embed.OleEmbeddedObject"_ustr;
709 sal_Bool SAL_CALL OleEmbeddedObject::supportsService(const OUString& ServiceName)
711 return cppu::supportsService(this, ServiceName);
714 uno::Sequence<OUString> SAL_CALL OleEmbeddedObject::getSupportedServiceNames()
716 return { u"com.sun.star.comp.embed.OleEmbeddedObject"_ustr };
719 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */