tdf#147590 update OLE object after document refresh

Regression from b099da78a6f0b3e120f706714003b05d84d11e70
we didn't update linked OLE document after document reload

Change-Id: I8e52f6430f454b276cb43449c6f7a3b0e07e909f
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/130692
Reviewed-by: Samuel Mehrbrodt <samuel.mehrbrodt@allotropia.de>
Tested-by: Jenkins
diff --git a/comphelper/source/container/embeddedobjectcontainer.cxx b/comphelper/source/container/embeddedobjectcontainer.cxx
index 2d85b73..094597f 100644
--- a/comphelper/source/container/embeddedobjectcontainer.cxx
+++ b/comphelper/source/container/embeddedobjectcontainer.cxx
@@ -1158,7 +1158,8 @@ namespace {

}

bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded,const uno::Reference < embed::XStorage >& _xStorage)
bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEmbedded, bool _bAutoSaveEvent,
                                              const uno::Reference < embed::XStorage >& _xStorage)
{
    bool bResult = false;
    try
@@ -1222,7 +1223,7 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm
                uno::Reference< embed::XEmbedPersist > xPersist( xObj, uno::UNO_QUERY );
                if ( xPersist.is() )
                {
                    uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 2 : 3 );
                    uno::Sequence< beans::PropertyValue > aArgs( _bOasisFormat ? 3 : 4 );
                    auto pArgs = aArgs.getArray();
                    pArgs[0].Name = "StoreVisualReplacement";
                    pArgs[0].Value <<= !_bOasisFormat;
@@ -1230,11 +1231,15 @@ bool EmbeddedObjectContainer::StoreAsChildren(bool _bOasisFormat,bool _bCreateEm
                    // if it is an embedded object or the optimized inserting fails the normal inserting should be done
                    pArgs[1].Name = "CanTryOptimization";
                    pArgs[1].Value <<= !_bCreateEmbedded;

                    pArgs[2].Name = "AutoSaveEvent";
                    pArgs[2].Value <<= _bAutoSaveEvent;

                    if ( !_bOasisFormat )
                    {
                        // if object has no cached replacement it will use this one
                        pArgs[2].Name = "VisualReplacement";
                        pArgs[2].Value <<= xStream;
                        pArgs[3].Name = "VisualReplacement";
                        pArgs[3].Value <<= xStream;
                    }

                    try
diff --git a/embeddedobj/Library_embobj.mk b/embeddedobj/Library_embobj.mk
index 35a65483..18cf555 100644
--- a/embeddedobj/Library_embobj.mk
+++ b/embeddedobj/Library_embobj.mk
@@ -21,6 +21,10 @@ $(eval $(call gb_Library_set_include,embobj,\
	$$(INCLUDE) \
))

$(eval $(call gb_Library_add_defs,embobj,\
    -DEMBOBJ_DLLIMPLEMENTATION \
))

$(eval $(call gb_Library_use_external,embobj,boost_headers))

$(eval $(call gb_Library_use_sdk_api,embobj))
diff --git a/embeddedobj/source/commonembedding/embedobj.cxx b/embeddedobj/source/commonembedding/embedobj.cxx
index 223f25e..240112b 100644
--- a/embeddedobj/source/commonembedding/embedobj.cxx
+++ b/embeddedobj/source/commonembedding/embedobj.cxx
@@ -639,6 +639,13 @@ void SAL_CALL OCommonEmbeddedObject::setContainerName( const OUString& sName )
    m_aContainerName = sName;
}

void OCommonEmbeddedObject::SetOleState(bool bIsOleUpdate)
{
    ::osl::MutexGuard aGuard( m_aMutex );

    m_bOleUpdate = bIsOleUpdate;
}

css::uno::Reference< css::uno::XInterface > SAL_CALL OCommonEmbeddedObject::getParent()
{
    return m_xParent;
diff --git a/embeddedobj/source/commonembedding/miscobj.cxx b/embeddedobj/source/commonembedding/miscobj.cxx
index a5d5573..f41d359 100644
--- a/embeddedobj/source/commonembedding/miscobj.cxx
+++ b/embeddedobj/source/commonembedding/miscobj.cxx
@@ -35,6 +35,13 @@
#include <cppuhelper/queryinterface.hxx>
#include <comphelper/mimeconfighelper.hxx>

#include <vcl/weld.hxx>
#include <unotools/resmgr.hxx>
#include <vcl/stdtext.hxx>
#include <strings.hrc>
#include <osl/file.hxx>
#include <comphelper/DirectoryHelper.hxx>

#include <vcl/svapp.hxx>
#include <tools/diagnose_ex.h>
#include <cppuhelper/supportsservice.hxx>
@@ -62,7 +69,11 @@ OCommonEmbeddedObject::OCommonEmbeddedObject( const uno::Reference< uno::XCompon
, m_bWaitSaveCompleted( false )
, m_bIsLinkURL( false )
, m_bLinkTempFileChanged( false )
, m_pLinkFile( )
, m_bOleUpdate( false )
, m_bInHndFunc( false )
, m_bLinkHasPassword( false )
, m_aLinkTempFile( )
, m_bHasClonedSize( false )
, m_nClonedMapUnit( 0 )
{
@@ -88,7 +99,11 @@ OCommonEmbeddedObject::OCommonEmbeddedObject(
, m_bWaitSaveCompleted( false )
, m_bIsLinkURL( true )
, m_bLinkTempFileChanged( false )
, m_pLinkFile( )
, m_bOleUpdate( false )
, m_bInHndFunc( false )
, m_bLinkHasPassword( false )
, m_aLinkTempFile( )
, m_bHasClonedSize( false )
, m_nClonedMapUnit( 0 )
{
@@ -224,26 +239,13 @@ void OCommonEmbeddedObject::LinkInit_Impl(
        // task-ID above)
        //
        // open OLE original data as read input file
        uno::Reference< ucb::XSimpleFileAccess3 > xTempAccess( ucb::SimpleFileAccess::create( m_xContext ) );
        uno::Reference< io::XInputStream > xInStream( xTempAccess->openFileRead( m_aLinkURL ) );

        if(xInStream.is())
        if ( comphelper::DirectoryHelper::fileExists( m_aLinkURL ) )
        {
            // create temporary file
            m_aLinkTempFile = io::TempFile::create(m_xContext);
            uno::Reference< ucb::XSimpleFileAccess > xTempOutAccess(ucb::SimpleFileAccess::create(m_xContext));
            // if the temp stream is used, then the temp file remains locked
            uno::Reference< io::XOutputStream > xOutStream(xTempOutAccess->openFileWrite(m_aLinkTempFile->getUri()));
            m_aLinkTempFile = io::TempFile::create( m_xContext );

            if(m_aLinkTempFile.is())
            {
                // completely copy content of original OLE data
                ::comphelper::OStorageHelper::CopyInputToOutput(xInStream, xOutStream);

                // reset flag m_bLinkTempFileChanged, so it will also work for multiple
                // save op's of the containing file/document
                m_bLinkTempFileChanged = false;
            }
            m_pLinkFile.reset( new FileChangedChecker( m_aLinkURL ) );
            handleLinkedOLE( CopyBackToOLELink::CopyLinkToTempInit );
        }
    }

@@ -379,6 +381,123 @@ void OCommonEmbeddedObject::PostEvent_Impl( const OUString& aEventName )
}


static int ShowMsgDialog( TranslateId Msg, const OUString& sFileName )
{
    std::locale aResLocale = Translate::Create( "emo" );
    OUString aMsg  = Translate::get( Msg, aResLocale );
    OUString aBtn  = Translate::get( BTN_OVERWRITE_TEXT, aResLocale );
    OUString aTemp = sFileName;

    osl::FileBase::getSystemPathFromFileURL( sFileName, aTemp );

    aMsg = aMsg.replaceFirst( "%{filename}", aTemp );
    weld::Window* pParent = Application::GetFrameWeld( nullptr );

    std::unique_ptr<weld::MessageDialog> xQueryBox (Application::CreateMessageDialog( pParent,
        VclMessageType::Warning, VclButtonsType::NONE, aMsg ) );
    xQueryBox->add_button( aBtn, RET_YES );
    xQueryBox->add_button( GetStandardText( StandardButtonType::Cancel ), RET_CANCEL );
    xQueryBox->set_default_response( RET_CANCEL );

    return xQueryBox->run();
}


void OCommonEmbeddedObject::handleLinkedOLE( CopyBackToOLELink eState )
{
    // do not refresh and autosave at the same time
    // when refresh all, then get both Link and Ole Update, in this case ignore OLE-refresh
    if ( m_bInHndFunc || m_bOleUpdate || !m_aLinkTempFile.is() )
        return;

    m_bInHndFunc = true;

    bool bLnkFileChg = m_pLinkFile->hasFileChanged( false );
    bool bTmpFileChg = m_bLinkTempFileChanged;


    if ( eState != CopyBackToOLELink::CopyLinkToTempInit && !bLnkFileChg && !bTmpFileChg )
    {
        // no changes
        eState = CopyBackToOLELink::NoCopy;
    }
    else if ( ( eState == CopyBackToOLELink::CopyTempToLink ) && bLnkFileChg && !bTmpFileChg )
    {
        // Save pressed,  but the Link-file is changed, but not the temp-file
        // in this case update the object with new link data
        eState = CopyBackToOLELink::CopyLinkToTempRefresh;
    }
    else if ( ( eState == CopyBackToOLELink::CopyTempToLink ) && bLnkFileChg && bTmpFileChg )
    {
        // Save pressed,  but the Link-file is changed, question to user for overwrite
        if ( ShowMsgDialog(STR_OVERWRITE_LINK, m_aLinkURL) == RET_CANCEL )
            eState = CopyBackToOLELink::NoCopy;
    }
    else if ( ( eState == CopyBackToOLELink::CopyLinkToTemp ) && bTmpFileChg )
    {
        // Refresh pressed,  but the Temp-file is changed, question to user for overwrite
        // it is not importent it has bLnkFileChg, always overwite the temp-file
        if ( ShowMsgDialog( STR_OVERWRITE_TEMP, m_aLinkURL ) == RET_CANCEL )
            eState = CopyBackToOLELink::NoCopy;
    }

    auto writeFile = [ this ]( const OUString& SrcName, const OUString& DesName )
    {
        uno::Reference < ucb::XSimpleFileAccess2 > xWriteAccess( ucb::SimpleFileAccess::create( m_xContext ) );
        uno::Reference < ucb::XSimpleFileAccess > xReadAccess( ucb::SimpleFileAccess::create( m_xContext ) );

        try
        {
            uno::Reference < io::XInputStream > xInStream( xReadAccess->openFileRead (SrcName ) );

            // This is *needed* since OTempFileService calls OTempFileService::readBytes which
            // ensures the SvStream mpStream gets/is opened, *but* also sets the mnCachedPos from
            // OTempFileService which still points to the end-of-file (from write-cc'ing).
            uno::Reference < io::XSeekable > xSeek( xInStream, uno::UNO_QUERY_THROW );
            xSeek->seek( 0 );

            xWriteAccess->writeFile( DesName, xInStream );
            m_bLinkTempFileChanged = false;
            // store the new timestamp
            m_pLinkFile->hasFileChanged();
        }
        catch ( const uno::Exception& ex )
        {
            OUString aMsg;
            osl::FileBase::getSystemPathFromFileURL( SrcName, aMsg );
            aMsg = ex.Message + "\n\n" + aMsg;
            weld::Window* pParent = Application::GetFrameWeld( nullptr );
            std::unique_ptr<weld::MessageDialog> xQueryBox( Application::CreateMessageDialog( pParent,
                                                     VclMessageType::Error, VclButtonsType::Ok, aMsg ) );

            xQueryBox->run();
        }
    };

    switch ( eState )
    {
        case CopyBackToOLELink::NoCopy:
            break;
        case CopyBackToOLELink::CopyLinkToTemp: // copy Link-File to Temp-File   (Refresh)
        case CopyBackToOLELink::CopyLinkToTempInit: //create temp file
            writeFile( m_aLinkURL, m_aLinkTempFile->getUri() );
            break;
        case CopyBackToOLELink::CopyTempToLink: // copy Temp-File to Link-File   (Save)
            // tdf#141529 if we have a changed copy of the original OLE data we now
            // need to write it back 'over' the original OLE data
            writeFile( m_aLinkTempFile->getUri(), m_aLinkURL );
            break;
        case CopyBackToOLELink::CopyLinkToTempRefresh: // need a Refresh not save
            // do nothing
            break;
        default:
            break;
    }

    m_bInHndFunc = false;
}


uno::Any SAL_CALL OCommonEmbeddedObject::queryInterface( const uno::Type& rType )
{
    uno::Any aReturn;
diff --git a/embeddedobj/source/commonembedding/persistence.cxx b/embeddedobj/source/commonembedding/persistence.cxx
index 77bc947..b32d07f 100644
--- a/embeddedobj/source/commonembedding/persistence.cxx
+++ b/embeddedobj/source/commonembedding/persistence.cxx
@@ -54,6 +54,7 @@
#include <comphelper/mimeconfighelper.hxx>
#include <comphelper/namedvaluecollection.hxx>
#include <comphelper/propertyvalue.hxx>
#include <unotools/mediadescriptor.hxx>

#include <tools/diagnose_ex.h>
#include <sal/log.hxx>
@@ -392,6 +393,8 @@ uno::Reference< util::XCloseable > OCommonEmbeddedObject::LoadLink_Impl()

    try
    {
        handleLinkedOLE(CopyBackToOLELink::CopyLinkToTemp);

        // the document is not really an embedded one, it is a link
        EmbedAndReparentDoc_Impl( xDocument );

@@ -1254,12 +1257,14 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed::
                            const uno::Sequence< beans::PropertyValue >& lArguments,
                            const uno::Sequence< beans::PropertyValue >& lObjArgs )
{
    // TODO: use lObjArgs

    ::osl::ResettableMutexGuard aGuard( m_aMutex );
    if ( m_bDisposed )
        throw lang::DisposedException(); // TODO

    bool AutoSaveEvent = false;
    utl::MediaDescriptor lArgs(lObjArgs);
    lArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent;

    if ( m_nObjectState == -1 )
    {
        // the object is still not loaded
@@ -1279,26 +1284,8 @@ void SAL_CALL OCommonEmbeddedObject::storeAsEntry( const uno::Reference< embed::
    {
        m_aNewEntryName = sEntName;

        if(m_aLinkTempFile.is() && m_bLinkTempFileChanged)
        {
            // tdf#141529 if we have a changed copy of the original OLE data we now
            // need to write it back 'over' the original OLE data
            uno::Reference < ucb::XSimpleFileAccess2 > xFileAccess(ucb::SimpleFileAccess::create( m_xContext ));

            uno::Reference< ucb::XSimpleFileAccess > xTempAccess(ucb::SimpleFileAccess::create(m_xContext));
            // if the temp stream is used, then the temp file remains locked
            uno::Reference< io::XInputStream > xInStream(xTempAccess->openFileRead(m_aLinkTempFile->getUri()));
            // This is *needed* since OTempFileService calls OTempFileService::readBytes which
            // ensures the SvStream mpStream gets/is opened, *but* also sets the mnCachedPos from
            // OTempFileService which still points to the end-of-file (from write-cc'ing).
            uno::Reference < io::XSeekable > xSeek( xInStream, uno::UNO_QUERY_THROW );
            xSeek->seek(0);

            xFileAccess->writeFile(m_aLinkURL, xInStream);

            // reset flag m_bLinkTempFileChanged
            m_bLinkTempFileChanged = false;
        }
        if ( !AutoSaveEvent )
            handleLinkedOLE(CopyBackToOLELink::CopyTempToLink);

        return;
    }
diff --git a/embeddedobj/source/inc/commonembobj.hxx b/embeddedobj/source/inc/commonembobj.hxx
index 785a28e..61abe02 100644
--- a/embeddedobj/source/inc/commonembobj.hxx
+++ b/embeddedobj/source/inc/commonembobj.hxx
@@ -36,9 +36,11 @@
#include <com/sun/star/lang/XServiceInfo.hpp>
#include <com/sun/star/lang/XInitialization.hpp>
#include <cppuhelper/weak.hxx>
#include <embeddedobj/embeddedupdate.hxx>
#include <rtl/ref.hxx>
#include <map>
#include <memory>
#include <svtools/filechangedchecker.hxx>

namespace com::sun::star {
    namespace embed {
@@ -76,6 +78,7 @@ class Interceptor;
 * document model successfully.
 */
class OCommonEmbeddedObject : public css::embed::XEmbeddedObject
                            , public css::embed::EmbeddedUpdate
                            , public css::embed::XEmbedPersist2
                            , public css::embed::XLinkageSupport
                            , public css::embed::XInplaceObject
@@ -141,6 +144,9 @@ protected:

    bool m_bIsLinkURL;
    bool m_bLinkTempFileChanged;
    ::std::unique_ptr< FileChangedChecker > m_pLinkFile;
    bool m_bOleUpdate;
    bool m_bInHndFunc;

    // embedded object related stuff
    OUString m_aEntryName;
@@ -193,6 +199,16 @@ private:

    void Deactivate();

    // when State = CopyTempToLink        -> the user pressed the save button
    //                                       when change in embedded part then copy to the linked-file
    //              CopyLinkToTemp        -> the user pressed the refresh button
    //                                       when change in linked-file then copy to the embedded part (temp-file)
    //              CopyLinkToTempInit    -> create the temp file
    //              CopyLinkToTempRefresh -> when save and Link change but not temp then update temp
    enum class CopyBackToOLELink {NoCopy, CopyTempToLink, CopyLinkToTemp, CopyLinkToTempInit, CopyLinkToTempRefresh};

    void handleLinkedOLE( CopyBackToOLELink eState );

    void StateChangeNotification_Impl( bool bBeforeChange, sal_Int32 nOldState, sal_Int32 nNewState,::osl::ResettableMutexGuard& _rGuard );

    void SwitchStateTo_Impl( sal_Int32 nNextState );
@@ -294,6 +310,10 @@ public:

    virtual void SAL_CALL setContainerName( const OUString& sName ) override;

// EmbeddedUpdate

    virtual void SetOleState(bool bIsOleUpdate) override;


// XVisualObject

diff --git a/embeddedobj/source/inc/strings.hrc b/embeddedobj/source/inc/strings.hrc
new file mode 100644
index 0000000..a3b323c
--- /dev/null
+++ b/embeddedobj/source/inc/strings.hrc
@@ -0,0 +1,19 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#define NC_(Context, String) TranslateId(Context, reinterpret_cast<char const *>(u8##String))

#define BTN_OVERWRITE_TEXT           NC_("BTN_OVERWRITE_TEXT", "Overwrite")
#define STR_OVERWRITE_LINK           NC_("STR_OVERWRITE_LINK", "You have made changes to the %{filename}, saving will overwrite the data from the inserted object.\n\nDo you still want to overwrite this data?")
#define STR_OVERWRITE_TEMP           NC_("STR_OVERWRITE_TEMP", "You have changed the data in the inserted object which will be overwritten by updating the %{filename}.\n\nDo you still want to overwrite this data?")


/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/framework/source/services/autorecovery.cxx b/framework/source/services/autorecovery.cxx
index 86715bd..e3321773 100644
--- a/framework/source/services/autorecovery.cxx
+++ b/framework/source/services/autorecovery.cxx
@@ -3008,6 +3008,8 @@ void AutoRecovery::implts_saveOneDoc(const OUString&                            
    // for make hyperlinks working
    lNewArgs[utl::MediaDescriptor::PROP_DOCUMENTBASEURL] <<= OUString();

    lNewArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] <<= true;

    // try to save this document as a new temp file every time.
    // Mark AutoSave state as "INCOMPLETE" if it failed.
    // Because the last temp file is too old and does not include all changes.
diff --git a/include/comphelper/embeddedobjectcontainer.hxx b/include/comphelper/embeddedobjectcontainer.hxx
index c477a6f..cc040da 100644
--- a/include/comphelper/embeddedobjectcontainer.hxx
+++ b/include/comphelper/embeddedobjectcontainer.hxx
@@ -166,6 +166,7 @@ public:
    bool            StoreChildren(bool _bOasisFormat,bool _bObjectsOnly);
    bool            StoreAsChildren( bool _bOasisFormat
                                        ,bool _bCreateEmbedded
                                        ,bool _bAutoSaveEvent
                                        ,const css::uno::Reference < css::embed::XStorage >& _xStorage);

    static css::uno::Reference< css::io::XInputStream > GetGraphicReplacementStream(
diff --git a/include/embeddedobj/embeddedupdate.hxx b/include/embeddedobj/embeddedupdate.hxx
new file mode 100644
index 0000000..1db3f36
--- /dev/null
+++ b/include/embeddedobj/embeddedupdate.hxx
@@ -0,0 +1,52 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <embeddedobj/embobjdllapi.h>

namespace com
{
namespace sun
{
namespace star
{
namespace embed
{
/** This class is only used to tell the OCommonEmbeddedObject class
    that the following call is an Link- / Ole-refresh.

    @since LibreOffice 7.4
 */
class EMBOBJ_DLLPUBLIC EmbeddedUpdate
{
    /** By "Refresh all" is used to perform an OLE update and a link update.
        In the case of a link update, the class OCommonEmbeddedObject is
        informed with true that a link update will take place next

        @param bIsOleUpdate
            what kind of update, when true  is OLE-Object
                                 when false is Link-Object
     */
public:
    virtual void SetOleState(bool bIsOleUpdate) = 0;

    EmbeddedUpdate() = default;
    virtual ~EmbeddedUpdate() = default;

private:
    EmbeddedUpdate(const EmbeddedUpdate&) = delete;
    EmbeddedUpdate& operator=(const EmbeddedUpdate&) = delete;
};
};
};
};
};

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/embeddedobj/embobjdllapi.h b/include/embeddedobj/embobjdllapi.h
new file mode 100644
index 0000000..36aa542
--- /dev/null
+++ b/include/embeddedobj/embobjdllapi.h
@@ -0,0 +1,20 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <sal/types.h>

#if defined(EMBOBJ_DLLIMPLEMENTATION)
#define EMBOBJ_DLLPUBLIC SAL_DLLPUBLIC_EXPORT
#else
#define EMBOBJ_DLLPUBLIC SAL_DLLPUBLIC_IMPORT
#endif

/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/include/svtools/embedhlp.hxx b/include/svtools/embedhlp.hxx
index 9d4cb8e..4930e5b7 100644
--- a/include/svtools/embedhlp.hxx
+++ b/include/svtools/embedhlp.hxx
@@ -49,6 +49,7 @@ class SVT_DLLPUBLIC EmbeddedObjectRef

    SVT_DLLPRIVATE std::unique_ptr<SvStream> GetGraphicStream( bool bUpdate ) const;
    SVT_DLLPRIVATE void GetReplacement( bool bUpdate );
    SVT_DLLPRIVATE void UpdateOleObject( bool bUpdateOle);

    EmbeddedObjectRef& operator = ( const EmbeddedObjectRef& ) = delete;

@@ -101,7 +102,9 @@ public:
                        const css::uno::Reference< css::io::XInputStream >& xInGrStream,
                        const OUString& rMediaType );

    void            UpdateReplacement();
                    // bUpdateOle = false udate the Link-Objects
                    //            = true  update the OLE-Objects
    void            UpdateReplacement( bool bUpdateOle = false );
    void            UpdateReplacementOnDemand();
    void Lock( bool bLock = true );
    void            Clear();
diff --git a/include/svtools/filechangedchecker.hxx b/include/svtools/filechangedchecker.hxx
index d63d146..9800654 100644
--- a/include/svtools/filechangedchecker.hxx
+++ b/include/svtools/filechangedchecker.hxx
@@ -35,7 +35,11 @@ private:

public:
    void resetTimer();
    bool hasFileChanged();
    // bUpdate = true  when file has changed, get the return and the object get the new time
    //         = false when file has changed, only get the return, not change the object
    bool hasFileChanged(bool bUpdate = true);
    FileChangedChecker(const OUString& rFilename,
            const ::std::function<void ()>& rCallback);
    // with out Timer function
    FileChangedChecker(const OUString& rFilename);
};
diff --git a/include/unotools/mediadescriptor.hxx b/include/unotools/mediadescriptor.hxx
index 1e4b3c0..92728fa 100644
--- a/include/unotools/mediadescriptor.hxx
+++ b/include/unotools/mediadescriptor.hxx
@@ -101,6 +101,7 @@ class UNOTOOLS_DLLPUBLIC MediaDescriptor : public comphelper::SequenceAsHashMap
        static constexpr OUStringLiteral PROP_VIEWONLY = u"ViewOnly";
        static constexpr OUStringLiteral PROP_DOCUMENTBASEURL = u"DocumentBaseURL";
        static constexpr OUStringLiteral PROP_SUGGESTEDSAVEASNAME = u"SuggestedSaveAsName";
        static constexpr OUStringLiteral PROP_AUTOSAVEEVENT = u"AutoSaveEvent";

    // interface
    public:
diff --git a/reportdesign/source/core/api/ReportDefinition.cxx b/reportdesign/source/core/api/ReportDefinition.cxx
index 638b7a8..e9f5393 100644
--- a/reportdesign/source/core/api/ReportDefinition.cxx
+++ b/reportdesign/source/core/api/ReportDefinition.cxx
@@ -1291,6 +1291,8 @@ void SAL_CALL OReportDefinition::storeToStorage( const uno::Reference< embed::XS
    uno::Sequence< uno::Any > aDelegatorArguments;
    utl::MediaDescriptor aDescriptor( _aMediaDescriptor );
    lcl_extractAndStartStatusIndicator( aDescriptor, xStatusIndicator, aDelegatorArguments );
    bool AutoSaveEvent = false;
    aDescriptor[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent;

    // properties
    uno::Sequence < beans::PropertyValue > aProps;
@@ -1382,7 +1384,7 @@ void SAL_CALL OReportDefinition::storeToStorage( const uno::Reference< embed::XS
        if ( _xStorageToSaveTo == m_pImpl->m_xStorage )
            bPersist = m_pImpl->m_pObjectContainer->StoreChildren(true,false);
        else
            bPersist = m_pImpl->m_pObjectContainer->StoreAsChildren(true,true,_xStorageToSaveTo);
            bPersist = m_pImpl->m_pObjectContainer->StoreAsChildren(true,true,AutoSaveEvent,_xStorageToSaveTo);

        if( bPersist )
            m_pImpl->m_pObjectContainer->SetPersistentEntries(m_pImpl->m_xStorage);
diff --git a/sfx2/source/doc/objstor.cxx b/sfx2/source/doc/objstor.cxx
index fec08d3..288b6a7 100644
--- a/sfx2/source/doc/objstor.cxx
+++ b/sfx2/source/doc/objstor.cxx
@@ -76,6 +76,7 @@
#include <unotools/ucbhelper.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/docinfohelper.hxx>
#include <unotools/mediadescriptor.hxx>
#include <ucbhelper/content.hxx>
#include <sot/storage.hxx>
#include <sot/exchange.hxx>
@@ -3242,10 +3243,14 @@ bool SfxObjectShell::SaveAsChildren( SfxMedium& rMedium )
        return true;
    }

    bool AutoSaveEvent = false;
    utl::MediaDescriptor lArgs(rMedium.GetArgs());
    lArgs[utl::MediaDescriptor::PROP_AUTOSAVEEVENT] >>= AutoSaveEvent;

    if ( pImpl->mxObjectContainer )
    {
        bool bOasis = ( SotStorage::GetVersion( xStorage ) > SOFFICE_FILEFORMAT_60 );
        GetEmbeddedObjectContainer().StoreAsChildren(bOasis,SfxObjectCreateMode::EMBEDDED == eCreateMode,xStorage);
        GetEmbeddedObjectContainer().StoreAsChildren(bOasis,SfxObjectCreateMode::EMBEDDED == eCreateMode,AutoSaveEvent,xStorage);
    }

    uno::Sequence<OUString> aExceptions;
diff --git a/svtools/source/misc/embedhlp.cxx b/svtools/source/misc/embedhlp.cxx
index 29e42779..809a2b1 100644
--- a/svtools/source/misc/embedhlp.cxx
+++ b/svtools/source/misc/embedhlp.cxx
@@ -51,6 +51,7 @@
#include <com/sun/star/embed/XStateChangeListener.hpp>
#include <com/sun/star/embed/XLinkageSupport.hpp>
#include <com/sun/star/chart2/XDefaultSizeTransmitter.hpp>
#include <embeddedobj/embeddedupdate.hxx>
#include <cppuhelper/implbase.hxx>
#include <vcl/svapp.hxx>
#include <tools/diagnose_ex.h>
@@ -878,7 +879,7 @@ bool EmbeddedObjectRef::IsChart(const css::uno::Reference < css::embed::XEmbedde
        || SvGlobalName(SO3_SCH_CLASSID_60) == aObjClsId;
}

void EmbeddedObjectRef::UpdateReplacement()
void EmbeddedObjectRef::UpdateReplacement( bool bUpdateOle )
{
    if (mpImpl->bUpdating)
    {
@@ -886,10 +887,20 @@ void EmbeddedObjectRef::UpdateReplacement()
        return;
    }
    mpImpl->bUpdating = true;
    UpdateOleObject( bUpdateOle );
    GetReplacement(true);
    UpdateOleObject( false );
    mpImpl->bUpdating = false;
}

void EmbeddedObjectRef::UpdateOleObject( bool bUpdateOle )
{
    embed::EmbeddedUpdate* pObj = dynamic_cast<embed::EmbeddedUpdate*> (GetObject().get());
    if( pObj )
        pObj->SetOleState( bUpdateOle );
}


void EmbeddedObjectRef::UpdateReplacementOnDemand()
{
    mpImpl->pGraphic.reset();
diff --git a/svtools/source/misc/filechangedchecker.cxx b/svtools/source/misc/filechangedchecker.cxx
index 8536eb0..dd7cf22 100644
--- a/svtools/source/misc/filechangedchecker.cxx
+++ b/svtools/source/misc/filechangedchecker.cxx
@@ -21,7 +21,7 @@ FileChangedChecker::FileChangedChecker(const OUString& rFilename,
    , mLastModTime()
    , mpCallback(rCallback)
{
    // Get the curren last file modified Status
    // Get the current last file modified Status
    getCurrentModTime(mLastModTime);

    // associate the callback function for the Timer
@@ -34,10 +34,23 @@ FileChangedChecker::FileChangedChecker(const OUString& rFilename,
    resetTimer();
}

FileChangedChecker::FileChangedChecker(const OUString& rFilename)
    : mTimer("")
    , mFileName(rFilename)
    , mLastModTime()
    , mpCallback(nullptr)
{
    // Get the current last file modified Status
    getCurrentModTime(mLastModTime);
}

void FileChangedChecker::resetTimer()
{
    if (mpCallback == nullptr)
        return;

    // Start the Idle if it's not active
    if(!mTimer.IsActive())
    if (!mTimer.IsActive())
        mTimer.Start();

    // Set lowest Priority
@@ -61,7 +74,7 @@ bool FileChangedChecker::getCurrentModTime(TimeValue& o_rValue) const
    return true;
}

bool FileChangedChecker::hasFileChanged()
bool FileChangedChecker::hasFileChanged(bool bUpdate)
{
    // Get the current file Status
    TimeValue newTime={0,0};
@@ -75,7 +88,8 @@ bool FileChangedChecker::hasFileChanged()
    {
        // Since the file has changed, set the new status as the file status and
        // return True
        mLastModTime = newTime ;
        if(bUpdate)
            mLastModTime = newTime ;

        return true;
    }
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index b241541..3358043 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -757,7 +757,7 @@ void SwViewShell::UpdateOleObjectPreviews()

        SwOLEObj& rOleObj = pOleNode->GetOLEObj();
        svt::EmbeddedObjectRef& rObject = rOleObj.GetObject();
        rObject.UpdateReplacement();
        rObject.UpdateReplacement( true );
        // Trigger the repaint.
        pOleNode->SetChanged();
    }