embeddedobj/source/commonembedding/embedobj.cxx      |   63 +++++------
 embeddedobj/source/commonembedding/specialobject.cxx |    9 +
 embeddedobj/source/inc/commonembobj.hxx              |    3 
 embeddedobj/source/inc/specialobject.hxx             |    6 +
 include/svx/svdoole2.hxx                             |   17 ++-
 include/svx/unoshape.hxx                             |    2 
 include/vcl/graphicfilter.hxx                        |    4 
 sc/source/ui/docshell/documentlinkmgr.cxx            |    9 +
 sfx2/source/doc/iframe.cxx                           |   82 +++++++++-----
 svx/source/svdraw/svdoole2.cxx                       |  105 +++++++++++++++----
 svx/source/unodraw/shapeimpl.hxx                     |    5 
 svx/source/unodraw/unoshap4.cxx                      |   22 +++
 sw/inc/ndole.hxx                                     |    4 
 sw/source/core/ole/ndole.cxx                         |   90 ++++++++++++++--
 vcl/qa/cppunit/jpeg/JpegReaderTest.cxx               |   31 ++++-
 vcl/source/filter/graphicfilter2.cxx                 |    2 
 vcl/source/gdi/pdfextoutdevdata.cxx                  |    9 +
 xmloff/source/draw/ximpshap.cxx                      |   29 ++++-
 xmloff/source/draw/ximpshap.hxx                      |    2 
 19 files changed, 388 insertions(+), 106 deletions(-)

New commits:
commit 1a338efa6281ea616e3a6d99c1863a4ade5e2a7a
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Apr 20 20:58:21 2023 +0100
Commit:     Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
CommitDate: Thu Jun 1 13:16:51 2023 +0200

    assume IFrame script/macro support isn't needed
    
    seems undocumented at least
    
    Change-Id: I316e4f4f25ddb7cf6b7bac4d856a721b987207a3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151020
    Tested-by: Jenkins
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152151
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx
index b20e1531d10d..3d1260244a67 100644
--- a/sfx2/source/doc/iframe.cxx
+++ b/sfx2/source/doc/iframe.cxx
@@ -167,20 +167,16 @@ sal_Bool SAL_CALL IFrameObject::load(
         uno::Reference < util::XURLTransformer > xTrans( 
util::URLTransformer::create( mxContext ) );
         xTrans->parseStrict( aTargetURL );
 
+        INetURLObject aURLObject(aTargetURL.Complete);
+        if (aURLObject.GetProtocol() == INetProtocol::Macro || 
aURLObject.isSchemeEqualTo(u"vnd.sun.star.script"))
+            return false;
+
         uno::Reference<frame::XFramesSupplier> xParentFrame = 
xFrame->getCreator();
         SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame);
 
-        if (INetURLObject(aTargetURL.Complete).GetProtocol() == 
INetProtocol::Macro)
-        {
-            if (pDoc && !pDoc->AdjustMacroMode())
-                return false;
-        }
-
         bool bUpdateAllowed(true);
         if (pDoc)
         {
-            // perhaps should only check for file targets, but lets default to 
making it strong
-            // unless there is a known need to distinguish
             comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = 
pDoc->getEmbeddedObjectContainer();
             bUpdateAllowed = 
rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
         }
commit 65e402d22dcf4bb9099f56c529ec80059a4934c3
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Thu Apr 13 11:31:17 2023 +0100
Commit:     Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
CommitDate: Thu Jun 1 13:16:26 2023 +0200

    put floating frames under managed links control
    
    like we do for sections and ole objects that link to their content
    
    individual commits in trunk are:
    
    extract a OCommonEmbeddedObject::SetInplaceActiveState for reuse
    
    no behaviour change intended
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150341
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 183e34a3f8c429c0698951e24c17844e416a3825)
    
    use parent window as dialog parent
    
    it makes no odds, but is more convenient for upcoming modification
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150342
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit f93edf343658abd489bde3639d2ffaefd50c0f99)
    
    adjust IFrameObject so it could reuse mxFrame for a reload of content
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150343
    Tested-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 3a727d26fd9eb6fa140bc3f5cadf3db079d42206)
    
    query getUserAllowsLinkUpdate for the case of content in a floating frame
    
    similarly to how it works for the more common "normal" embedded objects
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149971
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 52aa46468531918eabfa2031dedf50377ae72cf7)
    
    add a route to get writer Floating Frame links under 'manage links'
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150349
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 8b8a2844addbd262befb1a2d193dfb590dfa20be)
    
    allow SvxOle2Shape::resetModifiedState to survive having no SdrObject
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150538
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 02379929bd0e1d1676635f0ca1920422702ebb7c)
    
    create the FloatingFrameShape in a separate step to inserting it
    
    this is derived from the path taken by the AddShape(const OUString&)
    function for this case. No change in behavior is intended.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150526
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit bafec47847a0b9697b3bbe9358e53f8118af3024)
    
    add a route to get calc Floating Frame links under 'manage links'
    
    much harder than writer because the organization and ordering
    of properties and object activation etc is different.
    
    This ended up ugly, but functions.
    
    We set FrameURL before AddShape, we have to do it again later because it
    gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
    FrameURL to exist when AddShape triggers SetPersistName which itself
    triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
    know what URL will end up being used. So bodge this by setting FrameURL
    to the temp pre-SdrOle2Obj attached properties and we can smuggle it
    eventually into SdrOle2Obj::SetPersistName at the right point after
    PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
    in order to inform the link manager that this is an IFrame that links to
    a URL
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150539
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    (cherry picked from commit 07179a5a5bd00f34acfa8a3f260dd834ae003c63)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150755
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>
    
    bc5333b137d2da089b3b701ff615c6ddf43063d0
    7eec3132a23faafd9a2878215a0a117a67bc9bf2
    83e38dfa2f84907c2de9680e91f779d34864a9ad
    f90ff71d6a96342574799312f764badaf97980eb
    ea059262c124e3f44249e49b4189732310d28156
    d09ae0c65a55a37743ad7c184070fb8dd97d8a7f
    67fc199fef9e67fa12ca7873f0fe12137aa16d8f
    
    Change-Id: Ia1d12aa5c9afdc1347f6d4364bc6a0b7f41ee168
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152133
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/embeddedobj/source/commonembedding/embedobj.cxx 
b/embeddedobj/source/commonembedding/embedobj.cxx
index c70a7ba40bd6..771ce511847a 100644
--- a/embeddedobj/source/commonembedding/embedobj.cxx
+++ b/embeddedobj/source/commonembedding/embedobj.cxx
@@ -155,6 +155,37 @@ void OCommonEmbeddedObject::StateChangeNotification_Impl( 
bool bBeforeChange, sa
     }
 }
 
+void OCommonEmbeddedObject::SetInplaceActiveState()
+{
+    if ( !m_xClientSite.is() )
+        throw embed::WrongStateException( "client site not set, yet", *this );
+
+    uno::Reference< embed::XInplaceClient > xInplaceClient( m_xClientSite, 
uno::UNO_QUERY );
+    if ( !xInplaceClient.is() || !xInplaceClient->canInplaceActivate() )
+        throw embed::WrongStateException(); //TODO: can't activate inplace
+    xInplaceClient->activatingInplace();
+
+    uno::Reference< embed::XWindowSupplier > xClientWindowSupplier( 
xInplaceClient, uno::UNO_QUERY_THROW );
+
+    m_xClientWindow = xClientWindowSupplier->getWindow();
+    m_aOwnRectangle = xInplaceClient->getPlacement();
+    m_aClipRectangle = xInplaceClient->getClipRectangle();
+    awt::Rectangle aRectangleToShow = GetRectangleInterception( 
m_aOwnRectangle, m_aClipRectangle );
+
+    // create own window based on the client window
+    // place and resize the window according to the rectangles
+    uno::Reference< awt::XWindowPeer > xClientWindowPeer( m_xClientWindow, 
uno::UNO_QUERY_THROW );
+
+    // dispatch provider may not be provided
+    uno::Reference< frame::XDispatchProvider > xContainerDP = 
xInplaceClient->getInplaceDispatchProvider();
+    bool bOk = m_xDocHolder->ShowInplace( xClientWindowPeer, aRectangleToShow, 
xContainerDP );
+    m_nObjectState = embed::EmbedStates::INPLACE_ACTIVE;
+    if ( !bOk )
+    {
+        SwitchStateTo_Impl( embed::EmbedStates::RUNNING );
+        throw embed::WrongStateException(); //TODO: can't activate inplace
+    }
+}
 
 void OCommonEmbeddedObject::SwitchStateTo_Impl( sal_Int32 nNextState )
 {
@@ -229,37 +260,7 @@ void OCommonEmbeddedObject::SwitchStateTo_Impl( sal_Int32 
nNextState )
         {
             if ( nNextState == embed::EmbedStates::INPLACE_ACTIVE )
             {
-                if ( !m_xClientSite.is() )
-                    throw embed::WrongStateException( "client site not set, 
yet", *this );
-
-                uno::Reference< embed::XInplaceClient > xInplaceClient( 
m_xClientSite, uno::UNO_QUERY );
-                if ( xInplaceClient.is() && 
xInplaceClient->canInplaceActivate() )
-                {
-                    xInplaceClient->activatingInplace();
-
-                    uno::Reference< embed::XWindowSupplier > 
xClientWindowSupplier( xInplaceClient, uno::UNO_QUERY_THROW );
-
-                    m_xClientWindow = xClientWindowSupplier->getWindow();
-                    m_aOwnRectangle = xInplaceClient->getPlacement();
-                    m_aClipRectangle = xInplaceClient->getClipRectangle();
-                    awt::Rectangle aRectangleToShow = 
GetRectangleInterception( m_aOwnRectangle, m_aClipRectangle );
-
-                    // create own window based on the client window
-                    // place and resize the window according to the rectangles
-                    uno::Reference< awt::XWindowPeer > xClientWindowPeer( 
m_xClientWindow, uno::UNO_QUERY_THROW );
-
-                    // dispatch provider may not be provided
-                    uno::Reference< frame::XDispatchProvider > xContainerDP = 
xInplaceClient->getInplaceDispatchProvider();
-                    bool bOk = m_xDocHolder->ShowInplace( xClientWindowPeer, 
aRectangleToShow, xContainerDP );
-                    m_nObjectState = nNextState;
-                    if ( !bOk )
-                    {
-                        SwitchStateTo_Impl( embed::EmbedStates::RUNNING );
-                        throw embed::WrongStateException(); //TODO: can't 
activate inplace
-                    }
-                }
-                else
-                    throw embed::WrongStateException(); //TODO: can't activate 
inplace
+                SetInplaceActiveState();
             }
             else if ( nNextState == embed::EmbedStates::ACTIVE )
             {
diff --git a/embeddedobj/source/commonembedding/specialobject.cxx 
b/embeddedobj/source/commonembedding/specialobject.cxx
index 5b8cdb8c12b6..6a08fb69c3a2 100644
--- a/embeddedobj/source/commonembedding/specialobject.cxx
+++ b/embeddedobj/source/commonembedding/specialobject.cxx
@@ -61,6 +61,7 @@ uno::Any SAL_CALL OSpecialEmbeddedObject::queryInterface( 
const uno::Type& rType
     aReturn = ::cppu::queryInterface( rType,
                                         static_cast< embed::XEmbeddedObject* 
>( this ),
                                         static_cast< embed::XInplaceObject* >( 
this ),
+                                        static_cast< 
embed::XCommonEmbedPersist* >( static_cast< embed::XEmbedPersist* >( this ) ),
                                         static_cast< embed::XVisualObject* >( 
this ),
                                         static_cast< embed::XClassifiedObject* 
>( this ),
                                         static_cast< 
embed::XComponentSupplier* >( this ),
@@ -175,4 +176,12 @@ void SAL_CALL OSpecialEmbeddedObject::doVerb( sal_Int32 
nVerbID )
         OCommonEmbeddedObject::doVerb( nVerbID );
 }
 
+void SAL_CALL OSpecialEmbeddedObject::reload(
+                const uno::Sequence< beans::PropertyValue >&,
+                const uno::Sequence< beans::PropertyValue >&)
+{
+    // Allow IFrames to reload their content
+    SetInplaceActiveState();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/embeddedobj/source/inc/commonembobj.hxx 
b/embeddedobj/source/inc/commonembobj.hxx
index 52624c291775..704dd14e3ec3 100644
--- a/embeddedobj/source/inc/commonembobj.hxx
+++ b/embeddedobj/source/inc/commonembobj.hxx
@@ -227,6 +227,9 @@ private:
                     const css::uno::Sequence< css::beans::PropertyValue >& 
lArguments,
                     const css::uno::Sequence< css::beans::PropertyValue >& 
lObjArgs );
 
+protected:
+    void SetInplaceActiveState();
+
 public:
     OCommonEmbeddedObject(
         const css::uno::Reference< css::uno::XComponentContext >& rxContext,
diff --git a/embeddedobj/source/inc/specialobject.hxx 
b/embeddedobj/source/inc/specialobject.hxx
index 32ad61a7a582..ce5c01b35ae7 100644
--- a/embeddedobj/source/inc/specialobject.hxx
+++ b/embeddedobj/source/inc/specialobject.hxx
@@ -48,6 +48,12 @@ public:
     virtual void SAL_CALL changeState( sal_Int32 nNewState ) override;
 
     virtual void SAL_CALL doVerb( sal_Int32 nVerbID ) override;
+
+// XCommonEmbedPersist
+
+    virtual void SAL_CALL reload(
+                const css::uno::Sequence< css::beans::PropertyValue >& 
lArguments,
+                const css::uno::Sequence< css::beans::PropertyValue >& 
lObjArgs ) override;
 };
 
 #endif
diff --git a/include/svx/svdoole2.hxx b/include/svx/svdoole2.hxx
index 80fb05ed1b9a..83b6f69230c0 100644
--- a/include/svx/svdoole2.hxx
+++ b/include/svx/svdoole2.hxx
@@ -42,6 +42,7 @@ namespace frame { class XModel; }
 namespace svt { class EmbeddedObjectRef; }
 
 class SdrOle2ObjImpl;
+class SvxOle2Shape;
 
 class SVX_DLLPUBLIC SdrOle2Obj : public SdrRectObj
 {
@@ -49,7 +50,7 @@ private:
     std::unique_ptr<SdrOle2ObjImpl> mpImpl;
 
 private:
-    SVX_DLLPRIVATE void Connect_Impl();
+    SVX_DLLPRIVATE void Connect_Impl(SvxOle2Shape* pCreator = nullptr);
     SVX_DLLPRIVATE void Disconnect_Impl();
     SVX_DLLPRIVATE void Reconnect_Impl();
     SVX_DLLPRIVATE void AddListeners_Impl();
@@ -96,7 +97,7 @@ public:
     // OLE object has got a separate PersistName member now;
     // !!! use ::SetPersistName( ... ) only, if you know what you do !!!
     const OUString& GetPersistName() const;
-    void        SetPersistName( const OUString& rPersistName );
+    void        SetPersistName( const OUString& rPersistName, SvxOle2Shape* 
pCreator = nullptr );
 
     // One can add an application name to a SdrOle2Obj, which can be queried 
for
     // later on (SD needs this for presentation objects).
@@ -144,7 +145,7 @@ public:
                                          sal_Int64 nAspect );
     static bool Unload( const css::uno::Reference< css::embed::XEmbeddedObject 
>& xObj, sal_Int64 nAspect );
     bool Unload();
-    void Connect();
+    void Connect(SvxOle2Shape* pCreator = nullptr);
     void Disconnect();
     void ObjectLoaded();
 
@@ -192,6 +193,16 @@ public:
     bool                Connect() { return GetRealObject() != nullptr; }
 };
 
+class SVX_DLLPUBLIC SdrIFrameLink final : public sfx2::SvBaseLink
+{
+    SdrOle2Obj* m_pObject;
+
+public:
+    explicit SdrIFrameLink(SdrOle2Obj* pObject);
+    virtual ::sfx2::SvBaseLink::UpdateResult DataChanged(
+        const OUString& rMimeType, const css::uno::Any & rValue ) override;
+};
+
 #endif // INCLUDED_SVX_SVDOOLE2_HXX
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/svx/unoshape.hxx b/include/svx/unoshape.hxx
index 94a137c73ae8..0765e18f8356 100644
--- a/include/svx/unoshape.hxx
+++ b/include/svx/unoshape.hxx
@@ -593,6 +593,8 @@ public:
     bool createObject( const SvGlobalName &aClassName );
 
     void createLink( const OUString& aLinkURL );
+
+    virtual OUString GetAndClearInitialFrameURL();
 };
 
 
diff --git a/sc/source/ui/docshell/documentlinkmgr.cxx 
b/sc/source/ui/docshell/documentlinkmgr.cxx
index e723ee709b13..849da97bdf56 100644
--- a/sc/source/ui/docshell/documentlinkmgr.cxx
+++ b/sc/source/ui/docshell/documentlinkmgr.cxx
@@ -135,7 +135,7 @@ bool DocumentLinkManager::hasDdeOrOleOrWebServiceLinks(bool 
bDde, bool bOle, boo
         sfx2::SvBaseLink* pBase = rLink.get();
         if (bDde && dynamic_cast<ScDdeLink*>(pBase))
             return true;
-        if (bOle && dynamic_cast<SdrEmbedObjectLink*>(pBase))
+        if (bOle && (dynamic_cast<SdrEmbedObjectLink*>(pBase) || 
dynamic_cast<SdrIFrameLink*>(pBase)))
             return true;
         if (bWebService && dynamic_cast<ScWebServiceLink*>(pBase))
             return true;
@@ -166,6 +166,13 @@ bool 
DocumentLinkManager::updateDdeOrOleOrWebServiceLinks(vcl::Window* pWin)
             continue;
         }
 
+        SdrIFrameLink* pIFrameLink = dynamic_cast<SdrIFrameLink*>(pBase);
+        if (pIFrameLink)
+        {
+            pIFrameLink->Update();
+            continue;
+        }
+
         ScWebServiceLink* pWebserviceLink = 
dynamic_cast<ScWebServiceLink*>(pBase);
         if (pWebserviceLink)
         {
diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx
index f8764e98fb4d..b20e1531d10d 100644
--- a/sfx2/source/doc/iframe.cxx
+++ b/sfx2/source/doc/iframe.cxx
@@ -176,31 +176,46 @@ sal_Bool SAL_CALL IFrameObject::load(
                 return false;
         }
 
+        bool bUpdateAllowed(true);
+        if (pDoc)
+        {
+            // perhaps should only check for file targets, but lets default to 
making it strong
+            // unless there is a known need to distinguish
+            comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = 
pDoc->getEmbeddedObjectContainer();
+            bUpdateAllowed = 
rEmbeddedObjectContainer.getUserAllowsLinkUpdate();
+        }
+        if (!bUpdateAllowed)
+            return false;
+
         OUString sReferer;
         if (pDoc && pDoc->HasName())
             sReferer = pDoc->GetMedium()->GetName();
 
-        DBG_ASSERT( !mxFrame.is(), "Frame already existing!" );
-        VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( 
xFrame->getContainerWindow() );
-        VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( 
pParent, maFrmDescr.IsFrameBorderOn() );
-        pWin->SetSizePixel( pParent->GetOutputSizePixel() );
-        pWin->SetBackground();
-        pWin->Show();
-
-        uno::Reference < awt::XWindow > xWindow( 
pWin->GetComponentInterface(), uno::UNO_QUERY );
-        xFrame->setComponent( xWindow, uno::Reference < frame::XController >() 
);
+        uno::Reference<css::awt::XWindow> 
xParentWindow(xFrame->getContainerWindow());
 
-        // we must destroy the IFrame before the parent is destroyed
-        xWindow->addEventListener( this );
-
-        mxFrame = frame::Frame::create( mxContext );
-        uno::Reference < awt::XWindow > xWin( pWin->GetComponentInterface(), 
uno::UNO_QUERY );
-        mxFrame->initialize( xWin );
-        mxFrame->setName( maFrmDescr.GetName() );
-
-        uno::Reference < frame::XFramesSupplier > xFramesSupplier( xFrame, 
uno::UNO_QUERY );
-        if ( xFramesSupplier.is() )
-            mxFrame->setCreator( xFramesSupplier );
+        if (!mxFrame.is())
+        {
+            VclPtr<vcl::Window> pParent = 
VCLUnoHelper::GetWindow(xParentWindow);
+            VclPtr<IFrameWindow_Impl> pWin = 
VclPtr<IFrameWindow_Impl>::Create( pParent, maFrmDescr.IsFrameBorderOn() );
+            pWin->SetSizePixel( pParent->GetOutputSizePixel() );
+            pWin->SetBackground();
+            pWin->Show();
+
+            uno::Reference < awt::XWindow > xWindow( 
pWin->GetComponentInterface(), uno::UNO_QUERY );
+            xFrame->setComponent( xWindow, uno::Reference < frame::XController 
>() );
+
+            // we must destroy the IFrame before the parent is destroyed
+            xWindow->addEventListener( this );
+
+            mxFrame = frame::Frame::create( mxContext );
+            uno::Reference < awt::XWindow > xWin( 
pWin->GetComponentInterface(), uno::UNO_QUERY );
+            mxFrame->initialize( xWin );
+            mxFrame->setName( maFrmDescr.GetName() );
+
+            uno::Reference < frame::XFramesSupplier > xFramesSupplier( xFrame, 
uno::UNO_QUERY );
+            if ( xFramesSupplier.is() )
+                mxFrame->setCreator( xFramesSupplier );
+        }
 
         uno::Sequence < beans::PropertyValue > aProps{
             comphelper::makePropertyValue("PluginMode", sal_Int16(2)),
diff --git a/svx/source/svdraw/svdoole2.cxx b/svx/source/svdraw/svdoole2.cxx
index 2935d8e4b902..441f27202b54 100644
--- a/svx/source/svdraw/svdoole2.cxx
+++ b/svx/source/svdraw/svdoole2.cxx
@@ -77,6 +77,7 @@
 #include <sdr/contact/viewcontactofsdrole2obj.hxx>
 #include <svx/svdograf.hxx>
 #include <sdr/properties/oleproperties.hxx>
+#include <svx/unoshape.hxx>
 #include <svx/xlnclit.hxx>
 #include <svx/xbtmpit.hxx>
 #include <svx/xflbmtit.hxx>
@@ -590,6 +591,35 @@ void SdrEmbedObjectLink::Closed()
     SvBaseLink::Closed();
 }
 
+SdrIFrameLink::SdrIFrameLink(SdrOle2Obj* pObject)
+    : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, 
SotClipboardFormatId::SVXB)
+    , m_pObject(pObject)
+{
+    SetSynchron( false );
+}
+
+::sfx2::SvBaseLink::UpdateResult SdrIFrameLink::DataChanged(
+    const OUString&, const uno::Any& )
+{
+    uno::Reference<embed::XEmbeddedObject> xObject = m_pObject->GetObjRef();
+    uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, 
uno::UNO_QUERY);
+    if (xPersObj.is())
+    {
+        // let the IFrameObject reload the link
+        try
+        {
+            xPersObj->reload(uno::Sequence<beans::PropertyValue>(), 
uno::Sequence<beans::PropertyValue>());
+        }
+        catch (const uno::Exception&)
+        {
+        }
+
+        m_pObject->SetChanged();
+    }
+
+    return SUCCESS;
+}
+
 class SdrOle2ObjImpl
 {
 public:
@@ -608,7 +638,7 @@ public:
     bool mbLoadingOLEObjectFailed:1; // New local var to avoid repeated 
loading if load of OLE2 fails
     bool mbConnected:1;
 
-    SdrEmbedObjectLink* mpObjectLink;
+    sfx2::SvBaseLink* mpObjectLink;
     OUString maLinkURL;
 
     rtl::Reference<SvxUnoShapeModifyListener> mxModifyListener;
@@ -783,7 +813,7 @@ bool SdrOle2Obj::IsEmpty() const
     return !mpImpl->mxObjRef.is();
 }
 
-void SdrOle2Obj::Connect()
+void SdrOle2Obj::Connect(SvxOle2Shape* pCreator)
 {
     if( IsEmptyPresObj() )
         return;
@@ -796,7 +826,7 @@ void SdrOle2Obj::Connect()
         return;
     }
 
-    Connect_Impl();
+    Connect_Impl(pCreator);
     AddListeners_Impl();
 }
 
@@ -905,21 +935,51 @@ void SdrOle2Obj::CheckFileLink_Impl()
     {
         try
         {
-            uno::Reference< embed::XLinkageSupport > xLinkSupport( 
mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY );
-            if ( xLinkSupport.is() && xLinkSupport->isLink() )
+            uno::Reference<embed::XEmbeddedObject> xObject = 
mpImpl->mxObjRef.GetObject();
+            if (!xObject)
+                return;
+
+            bool bIFrame = false;
+
+            OUString aLinkURL;
+            uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, 
uno::UNO_QUERY);
+            if (xLinkSupport)
+            {
+                if (xLinkSupport->isLink())
+                    aLinkURL = xLinkSupport->getLinkURL();
+            }
+            else
             {
-                OUString aLinkURL = xLinkSupport->getLinkURL();
-                if ( !aLinkURL.isEmpty() )
+                // get IFrame (Floating Frames) listed and updatable from the
+                // manage links dialog
+                SvGlobalName aClassId(xObject->getClassID());
+                if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
                 {
-                    // this is a file link so the model link manager should 
handle it
-                    sfx2::LinkManager* pLinkManager = pModel->GetLinkManager();
-                    if ( pLinkManager )
+                    uno::Reference<beans::XPropertySet> 
xSet(xObject->getComponent(), uno::UNO_QUERY);
+                    if (xSet.is())
+                        xSet->getPropertyValue("FrameURL") >>= aLinkURL;
+                    bIFrame = true;
+                }
+            }
+
+            if (!aLinkURL.isEmpty()) // this is a file link so the model link 
manager should handle it
+            {
+                sfx2::LinkManager* pLinkManager(GetModel()->GetLinkManager());
+
+                if ( pLinkManager )
+                {
+                    SdrEmbedObjectLink* pEmbedObjectLink = nullptr;
+                    if (!bIFrame)
                     {
-                        mpImpl->mpObjectLink = new SdrEmbedObjectLink( this );
-                        mpImpl->maLinkURL = aLinkURL;
-                        pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, 
OBJECT_CLIENT_OLE, aLinkURL );
-                        mpImpl->mpObjectLink->Connect();
+                        pEmbedObjectLink = new SdrEmbedObjectLink(this);
+                        mpImpl->mpObjectLink = pEmbedObjectLink;
                     }
+                    else
+                        mpImpl->mpObjectLink = new SdrIFrameLink(this);
+                    mpImpl->maLinkURL = aLinkURL;
+                    pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, 
OBJECT_CLIENT_OLE, aLinkURL );
+                    if (pEmbedObjectLink)
+                        pEmbedObjectLink->Connect();
                 }
             }
         }
@@ -937,7 +997,7 @@ void SdrOle2Obj::Reconnect_Impl()
     Connect_Impl();
 }
 
-void SdrOle2Obj::Connect_Impl()
+void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator)
 {
     if( pModel && !mpImpl->aPersistName.isEmpty() )
     {
@@ -975,6 +1035,17 @@ void SdrOle2Obj::Connect_Impl()
                 }
             }
 
+            if (pCreator)
+            {
+                OUString sFrameURL(pCreator->GetAndClearInitialFrameURL());
+                if (!sFrameURL.isEmpty() && 
svt::EmbeddedObjectRef::TryRunningState(mpImpl->mxObjRef.GetObject()))
+                {
+                    uno::Reference<beans::XPropertySet> 
xSet(mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY);
+                    if (xSet.is())
+                        xSet->setPropertyValue("FrameURL", 
uno::Any(sFrameURL));
+                }
+            }
+
             if ( mpImpl->mxObjRef.is() )
             {
                 if ( !mpImpl->pLightClient )
@@ -1415,14 +1486,14 @@ SdrObject* SdrOle2Obj::getFullDragClone() const
     return createSdrGrafObjReplacement(false);
 }
 
-void SdrOle2Obj::SetPersistName( const OUString& rPersistName )
+void SdrOle2Obj::SetPersistName( const OUString& rPersistName, SvxOle2Shape* 
pCreator )
 {
     DBG_ASSERT( mpImpl->aPersistName.isEmpty(), "Persist name changed!");
 
     mpImpl->aPersistName = rPersistName;
     mpImpl->mbLoadingOLEObjectFailed = false;
 
-    Connect();
+    Connect(pCreator);
     SetChanged();
 }
 
diff --git a/svx/source/unodraw/shapeimpl.hxx b/svx/source/unodraw/shapeimpl.hxx
index a78b6cc13dee..77394b0f83e5 100644
--- a/svx/source/unodraw/shapeimpl.hxx
+++ b/svx/source/unodraw/shapeimpl.hxx
@@ -62,8 +62,11 @@ public:
 
     virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override;
 };
+
 class SvxFrameShape : public SvxOle2Shape
 {
+private:
+    OUString m_sInitialFrameURL;
 protected:
     // override these for special property handling in subcasses. Return true 
if property is handled
     virtual bool setPropertyValueImpl( const OUString& rName, const 
SfxItemPropertySimpleEntry* pProperty, const css::uno::Any& rValue ) override;
@@ -80,6 +83,8 @@ public:
     virtual void SAL_CALL setPropertyValues( const css::uno::Sequence< 
OUString >& aPropertyNames, const css::uno::Sequence< css::uno::Any >& aValues 
) override;
 
     virtual void Create( SdrObject* pNewOpj, SvxDrawPage* pNewPage ) override;
+
+    virtual OUString GetAndClearInitialFrameURL() override;
 };
 
 
diff --git a/svx/source/unodraw/unoshap4.cxx b/svx/source/unodraw/unoshap4.cxx
index 59f39cbbb702..f59eb93f79aa 100644
--- a/svx/source/unodraw/unoshap4.cxx
+++ b/svx/source/unodraw/unoshap4.cxx
@@ -176,7 +176,7 @@ bool SvxOle2Shape::setPropertyValueImpl( const OUString& 
rName, const SfxItemPro
 #else
             pOle = static_cast<SdrOle2Obj*>(mpObj.get());
 #endif
-            pOle->SetPersistName( aPersistName );
+            pOle->SetPersistName( aPersistName, this );
             return true;
         }
         break;
@@ -505,10 +505,11 @@ void SvxOle2Shape::createLink( const OUString& aLinkURL )
 
 void SvxOle2Shape::resetModifiedState()
 {
-    ::comphelper::IEmbeddedHelper* pPersist = mpModel ? mpModel->GetPersist() 
: nullptr;
+    SdrObject* pObject = GetSdrObject();
+    ::comphelper::IEmbeddedHelper* pPersist = pObject ? 
pObject->GetModel()->GetPersist() : nullptr;
     if( pPersist && !pPersist->isEnableSetModified() )
     {
-        SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( mpObj.get() );
+        SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >(pObject);
         if( pOle && !pOle->IsEmpty() )
         {
             uno::Reference < util::XModifiable > xMod( pOle->GetObjRef(), 
uno::UNO_QUERY );
@@ -558,6 +559,10 @@ const SvGlobalName 
SvxOle2Shape::GetClassName_Impl(OUString& rHexCLSID)
     return aClassName;
 }
 
+OUString SvxOle2Shape::GetAndClearInitialFrameURL()
+{
+    return OUString();
+}
 
 SvxAppletShape::SvxAppletShape( SdrObject* pObject ) throw()
 : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_APPLET), 
getSvxMapProvider().GetPropertySet(SVXMAP_APPLET, 
SdrObject::GetGlobalDrawObjectItemPool())  )
@@ -713,8 +718,19 @@ SvxFrameShape::~SvxFrameShape() throw()
 {
 }
 
+OUString SvxFrameShape::GetAndClearInitialFrameURL()
+{
+    OUString sRet(m_sInitialFrameURL);
+    m_sInitialFrameURL.clear();
+    return sRet;
+}
+
 void SvxFrameShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage )
 {
+    uno::Reference<beans::XPropertySet> xSet(static_cast<OWeakObject *>(this), 
uno::UNO_QUERY);
+    if (xSet)
+        xSet->getPropertyValue("FrameURL") >>= m_sInitialFrameURL;
+
     SvxShape::Create( pNewObj, pNewPage );
     const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID );
     createObject(aIFrameClassId);
diff --git a/sw/inc/ndole.hxx b/sw/inc/ndole.hxx
index c878689b78eb..6f6105b56c6d 100644
--- a/sw/inc/ndole.hxx
+++ b/sw/inc/ndole.hxx
@@ -27,7 +27,7 @@ class SwGrfFormatColl;
 class SwDoc;
 class SwOLENode;
 class SwOLEListener_Impl;
-class SwEmbedObjectLink;
+namespace sfx2 { class SvBaseLink; }
 class DeflateData;
 
 class SW_DLLPUBLIC SwOLEObj
@@ -87,7 +87,7 @@ class SW_DLLPUBLIC SwOLENode: public SwNoTextNode
     bool   bOLESizeInvalid; /**< Should be considered at SwDoc::PrtOLENotify
                                    (e.g. copied). Is not persistent. */
 
-    SwEmbedObjectLink*  mpObjectLink;
+    sfx2::SvBaseLink*  mpObjectLink;
     OUString maLinkURL;
 
     SwOLENode(  const SwNodeIndex &rWhere,
diff --git a/sw/source/core/ole/ndole.cxx b/sw/source/core/ole/ndole.cxx
index aa7449a6a1ec..c1b74e45fad6 100644
--- a/sw/source/core/ole/ndole.cxx
+++ b/sw/source/core/ole/ndole.cxx
@@ -145,6 +145,8 @@ void SAL_CALL SwOLEListener_Impl::disposing( const 
lang::EventObject& )
 // TODO/LATER: actually SwEmbedObjectLink should be used here, but because 
different objects are used to control
 //             embedded object different link objects with the same 
functionality had to be implemented
 
+namespace {
+
 class SwEmbedObjectLink : public sfx2::SvBaseLink
 {
     SwOLENode*          pOleNode;
@@ -205,6 +207,45 @@ void SwEmbedObjectLink::Closed()
     SvBaseLink::Closed();
 }
 
+class SwIFrameLink : public sfx2::SvBaseLink
+{
+    SwOLENode* m_pOleNode;
+
+public:
+    explicit SwIFrameLink(SwOLENode* pNode)
+        : ::sfx2::SvBaseLink(::SfxLinkUpdateMode::ONCALL, 
SotClipboardFormatId::SVXB)
+        , m_pOleNode(pNode)
+    {
+        SetSynchron( false );
+    }
+
+    ::sfx2::SvBaseLink::UpdateResult DataChanged(
+        const OUString&, const uno::Any& )
+    {
+        uno::Reference<embed::XEmbeddedObject> xObject = 
m_pOleNode->GetOLEObj().GetOleRef();
+        uno::Reference<embed::XCommonEmbedPersist> xPersObj(xObject, 
uno::UNO_QUERY);
+        if (xPersObj.is())
+        {
+            // let the IFrameObject reload the link
+            try
+            {
+                xPersObj->reload(uno::Sequence<beans::PropertyValue>(), 
uno::Sequence<beans::PropertyValue>());
+            }
+            catch (const uno::Exception&)
+            {
+            }
+
+// TODO may need to backport 2da75024f88f7c3242fedd9b5bf4832a596402c0 for this?
+//            m_pOleNode->SetChanged();
+        }
+
+        return SUCCESS;
+    }
+
+};
+
+}
+
 SwOLENode::SwOLENode( const SwNodeIndex &rWhere,
                     const svt::EmbeddedObjectRef& xObj,
                     SwGrfFormatColl *pGrfColl,
@@ -598,18 +639,49 @@ void SwOLENode::CheckFileLink_Impl()
     {
         try
         {
-            uno::Reference< embed::XLinkageSupport > xLinkSupport( 
aOLEObj.xOLERef.GetObject(), uno::UNO_QUERY_THROW );
-            if ( xLinkSupport->isLink() )
+            uno::Reference<embed::XEmbeddedObject> xObject = 
aOLEObj.xOLERef.GetObject();
+            if (!xObject)
+                return;
+
+            bool bIFrame = false;
+
+            OUString aLinkURL;
+            uno::Reference<embed::XLinkageSupport> xLinkSupport(xObject, 
uno::UNO_QUERY);
+            if (xLinkSupport)
+            {
+                if (xLinkSupport->isLink())
+                    aLinkURL = xLinkSupport->getLinkURL();
+            }
+            else
             {
-                const OUString aLinkURL = xLinkSupport->getLinkURL();
-                if ( !aLinkURL.isEmpty() )
+                // get IFrame (Floating Frames) listed and updatable from the
+                // manage links dialog
+                SvGlobalName aClassId(xObject->getClassID());
+                if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID))
+                {
+                    uno::Reference<beans::XPropertySet> 
xSet(xObject->getComponent(), uno::UNO_QUERY);
+                    if (xSet.is())
+                        xSet->getPropertyValue("FrameURL") >>= aLinkURL;
+                    bIFrame = true;
+                }
+            }
+
+            if (!aLinkURL.isEmpty()) // this is a file link so the model link 
manager should handle it
+            {
+                SwEmbedObjectLink* pEmbedObjectLink = nullptr;
+                if (!bIFrame)
+                {
+                    pEmbedObjectLink = new SwEmbedObjectLink(this);
+                    mpObjectLink = pEmbedObjectLink;
+                }
+                else
                 {
-                    // this is a file link so the model link manager should 
handle it
-                    mpObjectLink = new SwEmbedObjectLink( this );
-                    maLinkURL = aLinkURL;
-                    
GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( 
*mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL );
-                    mpObjectLink->Connect();
+                    mpObjectLink = new SwIFrameLink(this);
                 }
+                maLinkURL = aLinkURL;
+                
GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( 
*mpObjectLink, OBJECT_CLIENT_OLE, aLinkURL );
+                if (pEmbedObjectLink)
+                    pEmbedObjectLink->Connect();
             }
         }
         catch( uno::Exception& )
diff --git a/xmloff/source/draw/ximpshap.cxx b/xmloff/source/draw/ximpshap.cxx
index 7c6d41a75b82..582aa25abca4 100644
--- a/xmloff/source/draw/ximpshap.cxx
+++ b/xmloff/source/draw/ximpshap.cxx
@@ -3237,9 +3237,35 @@ 
SdXMLFloatingFrameShapeContext::~SdXMLFloatingFrameShapeContext()
 {
 }
 
+uno::Reference<drawing::XShape> 
SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape() const
+{
+    uno::Reference<lang::XMultiServiceFactory> 
xServiceFact(GetImport().GetModel(), uno::UNO_QUERY);
+    if (!xServiceFact.is())
+        return nullptr;
+    uno::Reference<drawing::XShape> xShape(
+            xServiceFact->createInstance("com.sun.star.drawing.FrameShape"), 
uno::UNO_QUERY);
+    return xShape;
+}
+
 void SdXMLFloatingFrameShapeContext::StartElement( const css::uno::Reference< 
css::xml::sax::XAttributeList >& )
 {
-    AddShape("com.sun.star.drawing.FrameShape");
+    uno::Reference<drawing::XShape> 
xShape(SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape());
+
+    uno::Reference< beans::XPropertySet > xProps(xShape, uno::UNO_QUERY);
+    // set FrameURL before AddShape, we have to do it again later because it
+    // gets cleared when the SdrOle2Obj is attached to the XShape.  But we want
+    // FrameURL to exist when AddShape triggers SetPersistName which itself
+    // triggers SdrOle2Obj::CheckFileLink_Impl and at that point we want to
+    // know what URL will end up being used. So bodge this by setting FrameURL
+    // to the temp pre-SdrOle2Obj attached properties and we can smuggle it
+    // eventually into SdrOle2Obj::SetPersistName at the right point after
+    // PersistName is set but before SdrOle2Obj::CheckFileLink_Impl is called
+    // in order to inform the link manager that this is an IFrame that links to
+    // a URL
+    if (xProps && !maHref.isEmpty())
+        xProps->setPropertyValue("FrameURL", Any(maHref));
+
+    AddShape(xShape);
 
     if( mxShape.is() )
     {
@@ -3248,7 +3274,6 @@ void SdXMLFloatingFrameShapeContext::StartElement( const 
css::uno::Reference< cs
         // set pos, size, shear and rotate
         SetTransformation();
 
-        uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY 
);
         if( xProps.is() )
         {
             if( !maFrameName.isEmpty() )
diff --git a/xmloff/source/draw/ximpshap.hxx b/xmloff/source/draw/ximpshap.hxx
index 56bdd7f84934..030bb0d92fbc 100644
--- a/xmloff/source/draw/ximpshap.hxx
+++ b/xmloff/source/draw/ximpshap.hxx
@@ -523,6 +523,8 @@ private:
     OUString maFrameName;
     OUString maHref;
 
+    css::uno::Reference<css::drawing::XShape> CreateFloatingFrameShape() const;
+
 public:
 
     SdXMLFloatingFrameShapeContext( SvXMLImport& rImport, sal_uInt16 nPrfx,
commit dce0f352058f2129dc554ffcd6c063e62ade9855
Author:     Caolán McNamara <caol...@redhat.com>
AuthorDate: Tue Apr 11 10:13:37 2023 +0100
Commit:     Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
CommitDate: Thu Jun 1 10:48:11 2023 +0200

    set Referer on loading IFrames
    
    so tools, options, security, options,
    "block any links from document not..."
    applies to their contents.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150221
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caol...@redhat.com>
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150751
    Reviewed-by: Stephan Bergmann <sberg...@redhat.com>
    (cherry picked from commit acff9ca0579333b45d10ae5f8cd48172f563dddd)
    (cherry picked from commit 04c8176fb40d2eb983aa0bd0a6ce65804d3f6ecd)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152097
    Tested-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>
    
    Change-Id: I04839aea6b07a4a76ac147a85045939ccd9c3c79

diff --git a/sfx2/source/doc/iframe.cxx b/sfx2/source/doc/iframe.cxx
index 413d38482d28..f8764e98fb4d 100644
--- a/sfx2/source/doc/iframe.cxx
+++ b/sfx2/source/doc/iframe.cxx
@@ -32,12 +32,14 @@
 #include <com/sun/star/ui/dialogs/XExecutableDialog.hpp>
 #include <com/sun/star/embed/XEmbeddedObject.hpp>
 
+#include <comphelper/propertyvalue.hxx>
 #include <cppuhelper/implbase.hxx>
 #include <cppuhelper/supportsservice.hxx>
 #include <rtl/ref.hxx>
 #include <svtools/miscopt.hxx>
 #include <svl/ownlist.hxx>
 #include <svl/itemprop.hxx>
+#include <sfx2/docfile.hxx>
 #include <sfx2/frmdescr.hxx>
 #include <sfx2/objsh.hxx>
 #include <sfx2/sfxdlg.hxx>
@@ -165,14 +167,19 @@ sal_Bool SAL_CALL IFrameObject::load(
         uno::Reference < util::XURLTransformer > xTrans( 
util::URLTransformer::create( mxContext ) );
         xTrans->parseStrict( aTargetURL );
 
+        uno::Reference<frame::XFramesSupplier> xParentFrame = 
xFrame->getCreator();
+        SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame);
+
         if (INetURLObject(aTargetURL.Complete).GetProtocol() == 
INetProtocol::Macro)
         {
-            uno::Reference<frame::XFramesSupplier> xParentFrame = 
xFrame->getCreator();
-            SfxObjectShell* pDoc = 
SfxMacroLoader::GetObjectShell(xParentFrame);
             if (pDoc && !pDoc->AdjustMacroMode())
                 return false;
         }
 
+        OUString sReferer;
+        if (pDoc && pDoc->HasName())
+            sReferer = pDoc->GetMedium()->GetName();
+
         DBG_ASSERT( !mxFrame.is(), "Frame already existing!" );
         VclPtr<vcl::Window> pParent = VCLUnoHelper::GetWindow( 
xFrame->getContainerWindow() );
         VclPtr<IFrameWindow_Impl> pWin = VclPtr<IFrameWindow_Impl>::Create( 
pParent, maFrmDescr.IsFrameBorderOn() );
@@ -195,11 +202,11 @@ sal_Bool SAL_CALL IFrameObject::load(
         if ( xFramesSupplier.is() )
             mxFrame->setCreator( xFramesSupplier );
 
-        uno::Sequence < beans::PropertyValue > aProps(2);
-        aProps[0].Name = "PluginMode";
-        aProps[0].Value <<= (sal_Int16) 2;
-        aProps[1].Name = "ReadOnly";
-        aProps[1].Value <<= true;
+        uno::Sequence < beans::PropertyValue > aProps{
+            comphelper::makePropertyValue("PluginMode", sal_Int16(2)),
+            comphelper::makePropertyValue("ReadOnly", true),
+            comphelper::makePropertyValue("Referer", sReferer)
+        };
         uno::Reference < frame::XDispatch > xDisp = mxFrame->queryDispatch( 
aTargetURL, "_self", 0 );
         if ( xDisp.is() )
             xDisp->dispatch( aTargetURL, aProps );
commit eafa93e578a760e82654305ec8d14cc801fa00ee
Author:     Miklos Vajna <vmik...@collabora.co.uk>
AuthorDate: Tue Jun 5 17:43:33 2018 +0200
Commit:     Gabor Kelemen <gabor.kelemen.ext...@allotropia.de>
CommitDate: Thu Jun 1 10:32:50 2023 +0200

    tdf#102928 PDF export: do recompress CMYK images
    
    The export filter writes /DeviceRGB unconditionally, so for now don't
    optimize CMYK image handling here. Though the added GraphicDescriptor
    API allows supporting this natively in the export filter in the future.
    
    Change-Id: I76b44b910948467aeb1f15e5ae765201d183c99d
    Reviewed-on: https://gerrit.libreoffice.org/55343
    Reviewed-by: Miklos Vajna <vmik...@collabora.co.uk>
    Tested-by: Jenkins <c...@libreoffice.org>

diff --git a/include/vcl/graphicfilter.hxx b/include/vcl/graphicfilter.hxx
index 8b8a7cef3008..fbe45f8e6a21 100644
--- a/include/vcl/graphicfilter.hxx
+++ b/include/vcl/graphicfilter.hxx
@@ -146,6 +146,7 @@ class VCL_DLLPUBLIC GraphicDescriptor final
     GraphicFileFormat   nFormat;
     bool                bCompressed;
     bool                bOwnStream;
+    sal_uInt8 mnNumberOfImageComponents;
 
     void                ImpConstruct();
 
@@ -214,6 +215,9 @@ public:
     /** @return bits/pixel or 0 **/
     sal_uInt16          GetBitsPerPixel() const { return nBitsPerPixel; }
 
+    /** @return number of color channels */
+    sal_uInt8 GetNumberOfImageComponents() const { return 
mnNumberOfImageComponents; }
+
     /** @return filter number that is needed by the GraphFilter to read this 
format */
     static OUString GetImportFormatShortName( GraphicFileFormat nFormat );
 };
diff --git a/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx 
b/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
index 127de3c9f0e0..004d6f52239e 100644
--- a/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
+++ b/vcl/qa/cppunit/jpeg/JpegReaderTest.cxx
@@ -22,7 +22,7 @@ class JpegReaderTest : public test::BootstrapFixtureBase
         return m_directories.getURLFromSrc(maDataUrl) + sFileName;
     }
 
-    Bitmap loadJPG(const OUString& aURL);
+    Graphic loadJPG(const OUString& aURL);
 
 public:
     JpegReaderTest() :
@@ -91,19 +91,30 @@ bool checkRect(Bitmap& rBitmap, int aLayerNumber, long 
nAreaHeight, long nAreaWi
     return true;
 }
 
-Bitmap JpegReaderTest::loadJPG(const OUString& aURL)
+int getNumberOfImageComponents(const Graphic& rGraphic)
+{
+    GfxLink aLink = rGraphic.GetLink();
+    SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(aLink.GetData()), 
aLink.GetDataSize(),
+                                 StreamMode::READ | StreamMode::WRITE);
+    GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+    CPPUNIT_ASSERT(aDescriptor.Detect(true));
+    return aDescriptor.GetNumberOfImageComponents();
+}
+
+Graphic JpegReaderTest::loadJPG(const OUString& aURL)
 {
     GraphicFilter& rFilter = GraphicFilter::GetGraphicFilter();
     Graphic aGraphic;
     SvFileStream aFileStream(aURL, StreamMode::READ);
     sal_uInt16 bResult = rFilter.ImportGraphic(aGraphic, aURL, aFileStream);
     CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), bResult);
-    return aGraphic.GetBitmapEx().GetBitmap();
+    return aGraphic;
 }
 
 void JpegReaderTest::testReadRGB()
 {
-    Bitmap aBitmap = loadJPG(getFullUrl("JPEGTestRGB.jpeg"));
+    Graphic aGraphic = loadJPG(getFullUrl("JPEGTestRGB.jpeg"));
+    Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
     Size aSize = aBitmap.GetSizePixel();
     CPPUNIT_ASSERT_EQUAL(12L, aSize.Width());
     CPPUNIT_ASSERT_EQUAL(12L, aSize.Height());
@@ -113,11 +124,14 @@ void JpegReaderTest::testReadRGB()
     CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0xff, 0x00, 0x00), 
nMaxDelta));
     CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0x00, 0xff, 0x00), 
nMaxDelta));
     CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x00, 0x00, 0xff), 
nMaxDelta));
+
+    CPPUNIT_ASSERT_EQUAL(3, getNumberOfImageComponents(aGraphic));
 }
 
 void JpegReaderTest::testReadGray()
 {
-    Bitmap aBitmap = loadJPG(getFullUrl("JPEGTestGray.jpeg"));
+    Graphic aGraphic = loadJPG(getFullUrl("JPEGTestGray.jpeg"));
+    Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
     Size aSize = aBitmap.GetSizePixel();
     CPPUNIT_ASSERT_EQUAL(12L, aSize.Width());
     CPPUNIT_ASSERT_EQUAL(12L, aSize.Height());
@@ -129,11 +143,14 @@ void JpegReaderTest::testReadGray()
     CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0x36, 0x36, 0x36), 
nMaxDelta));
     CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0xb6, 0xb6, 0xb6), 
nMaxDelta));
     CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x12, 0x12, 0x12), 
nMaxDelta));
+
+    CPPUNIT_ASSERT_EQUAL(1, getNumberOfImageComponents(aGraphic));
 }
 
 void JpegReaderTest::testReadCMYK()
 {
-    Bitmap aBitmap = loadJPG(getFullUrl("JPEGTestCMYK.jpeg"));
+    Graphic aGraphic = loadJPG(getFullUrl("JPEGTestCMYK.jpeg"));
+    Bitmap aBitmap = aGraphic.GetBitmapEx().GetBitmap();
     Size aSize = aBitmap.GetSizePixel();
     CPPUNIT_ASSERT_EQUAL(12L, aSize.Width());
     CPPUNIT_ASSERT_EQUAL(12L, aSize.Height());
@@ -143,6 +160,8 @@ void JpegReaderTest::testReadCMYK()
     CPPUNIT_ASSERT(checkRect(aBitmap, 1, 8, 8, Color(0xff, 0x00, 0x00), 
maxDelta));
     CPPUNIT_ASSERT(checkRect(aBitmap, 2, 8, 8, Color(0x00, 0xff, 0x00), 
maxDelta));
     CPPUNIT_ASSERT(checkRect(aBitmap, 3, 8, 8, Color(0x00, 0x00, 0xff), 
maxDelta));
+
+    CPPUNIT_ASSERT_EQUAL(4, getNumberOfImageComponents(aGraphic));
 }
 
 CPPUNIT_TEST_SUITE_REGISTRATION(JpegReaderTest);
diff --git a/vcl/source/filter/graphicfilter2.cxx 
b/vcl/source/filter/graphicfilter2.cxx
index 0a7d5034e463..e1243f5569b7 100644
--- a/vcl/source/filter/graphicfilter2.cxx
+++ b/vcl/source/filter/graphicfilter2.cxx
@@ -99,6 +99,7 @@ void GraphicDescriptor::ImpConstruct()
     nBitsPerPixel = 0;
     nPlanes = 0;
     bCompressed = false;
+    mnNumberOfImageComponents = 0;
 }
 
 bool GraphicDescriptor::ImpDetectBMP( SvStream& rStm, bool bExtendedInfo )
@@ -374,6 +375,7 @@ bool GraphicDescriptor::ImpDetectJPG( SvStream& rStm,  bool 
bExtendedInfo )
                                         .ReadUChar( nComponentsIdentifier )
                                         .ReadUChar( nSamplingFactor )
                                         .ReadUChar( 
nQuantizationTableDestinationSelector );
+                                    mnNumberOfImageComponents = 
nNumberOfImageComponents;
 
                                     // nSamplingFactor (lower nibble: vertical,
                                     // upper nibble: horizontal) is unused
diff --git a/vcl/source/gdi/pdfextoutdevdata.cxx 
b/vcl/source/gdi/pdfextoutdevdata.cxx
index ccc242061fa4..a8111c92ceaf 100644
--- a/vcl/source/gdi/pdfextoutdevdata.cxx
+++ b/vcl/source/gdi/pdfextoutdevdata.cxx
@@ -24,6 +24,7 @@
 #include "vcl/dllapi.h"
 #include "basegfx/polygon/b2dpolygon.hxx"
 #include "basegfx/polygon/b2dpolygontools.hxx"
+#include <vcl/graphicfilter.hxx>
 
 #include <set>
 #include <memory>
@@ -823,6 +824,14 @@ bool PDFExtOutDevData::HasAdequateCompression( const 
Graphic &rGraphic ) const
 
     // FIXME: ideally we'd also pre-empt the DPI related scaling too.
 
+    GfxLink aLink = rGraphic.GetLink();
+    SvMemoryStream aMemoryStream(const_cast<sal_uInt8*>(aLink.GetData()), 
aLink.GetDataSize(),
+                                 StreamMode::READ | StreamMode::WRITE);
+    GraphicDescriptor aDescriptor(aMemoryStream, nullptr);
+    if (aDescriptor.Detect(true) && aDescriptor.GetNumberOfImageComponents() 
== 4)
+        // 4 means CMYK, which is not handled.
+        return false;
+
     Size aSize = rGraphic.GetSizePixel();
     if (rGraphic.GetLink().GetDataSize() == 0)
         return false;

Reply via email to