From 683e4de0de8dde7c5570c67cbd2bae17b6d7f0e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Tue, 11 Apr 2023 10:13:37 +0100 Subject: set Referer on loading IFrames so tools, options, security, options, "block any links from document not..." applies to their contents. Change-Id: I04839aea6b07a4a76ac147a85045939ccd9c3c79 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150225 Tested-by: Jenkins Reviewed-by: Stephan Bergmann --- sfx2/source/doc/iframe.cxx | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) From 49a554471cddc3e52ae381f864e689fe4a8c6131 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Thu, 13 Apr 2023 11:31:17 +0100 Subject: put floating frames under managed links control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Change-Id: Ia1d12aa5c9afdc1347f6d4364bc6a0b7f41ee168 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150341 Tested-by: Caolán McNamara Reviewed-by: Caolán McNamara (cherry picked from commit 183e34a3f8c429c0698951e24c17844e416a3825) use parent window as dialog parent it makes no odds, but is more convenient for upcoming modification Change-Id: Ibc5333b137d2da089b3b701ff615c6ddf43063d0 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150342 Tested-by: Caolán McNamara Reviewed-by: Caolán McNamara (cherry picked from commit f93edf343658abd489bde3639d2ffaefd50c0f99) adjust IFrameObject so it could reuse mxFrame for a reload of content Change-Id: I7eec3132a23faafd9a2878215a0a117a67bc9bf2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150343 Tested-by: Caolán McNamara Reviewed-by: Caolán McNamara (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 Change-Id: I83e38dfa2f84907c2de9680e91f779d34864a9ad Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149971 Tested-by: Jenkins Reviewed-by: Caolán McNamara (cherry picked from commit 52aa46468531918eabfa2031dedf50377ae72cf7) add a route to get writer Floating Frame links under 'manage links' Change-Id: If90ff71d6a96342574799312f764badaf97980eb Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150349 Tested-by: Jenkins Reviewed-by: Caolán McNamara (cherry picked from commit 8b8a2844addbd262befb1a2d193dfb590dfa20be) allow SvxOle2Shape::resetModifiedState to survive having no SdrObject Change-Id: Iea059262c124e3f44249e49b4189732310d28156 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150538 Tested-by: Jenkins Reviewed-by: Caolán McNamara (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. Change-Id: Id09ae0c65a55a37743ad7c184070fb8dd97d8a7f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150526 Tested-by: Jenkins Reviewed-by: Caolán McNamara (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 Change-Id: I67fc199fef9e67fa12ca7873f0fe12137aa16d8f Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150539 Tested-by: Jenkins Reviewed-by: Caolán McNamara (cherry picked from commit 07179a5a5bd00f34acfa8a3f260dd834ae003c63) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150753 Reviewed-by: Michael Stahl --- embeddedobj/source/commonembedding/embedobj.cxx | 60 ++++++------ .../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 + sc/source/ui/docshell/documentlinkmgr.cxx | 9 +- sfx2/source/doc/iframe.cxx | 55 +++++++---- svx/source/svdraw/svdoole2.cxx | 104 +++++++++++++++++---- svx/source/unodraw/shapeimpl.hxx | 5 + svx/source/unodraw/unoshap4.cxx | 23 ++++- sw/inc/ndole.hxx | 4 +- sw/source/core/ole/ndole.cxx | 89 ++++++++++++++++-- xmloff/source/draw/ximpshap.cxx | 29 +++++- xmloff/source/draw/ximpshap.hxx | 2 + 15 files changed, 331 insertions(+), 86 deletions(-) From 26a8966b07f6335450ddbf4b0f5d5206db43bcbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= Date: Thu, 20 Apr 2023 20:58:21 +0100 Subject: assume IFrame script/macro support isn't needed seems undocumented at least Change-Id: I316e4f4f25ddb7cf6b7bac4d856a721b987207a3 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151019 Tested-by: Jenkins Reviewed-by: Xisco Fauli --- sfx2/source/doc/iframe.cxx | 15 ++++----------- sfx2/source/inc/eventsupplier.hxx | 1 + 2 files changed, 5 insertions(+), 11 deletions(-) diff -urN libreoffice-7-0-4.old/embeddedobj/source/commonembedding/embedobj.cxx libreoffice-7-0-4/embeddedobj/source/commonembedding/embedobj.cxx --- libreoffice-7-0-4.old/embeddedobj/source/commonembedding/embedobj.cxx 2023-05-24 17:17:08.688721561 +0200 +++ libreoffice-7-0-4/embeddedobj/source/commonembedding/embedobj.cxx 2023-05-24 17:24:13.613547961 +0200 @@ -155,6 +155,37 @@ rGuard.reset(); } +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 ) { @@ -228,34 +259,7 @@ { 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() ) - 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 = nNextState; - if ( !bOk ) - { - SwitchStateTo_Impl( embed::EmbedStates::RUNNING ); - throw embed::WrongStateException(); //TODO: can't activate inplace - } + SetInplaceActiveState(); } else if ( nNextState == embed::EmbedStates::ACTIVE ) { diff -urN libreoffice-7-0-4.old/embeddedobj/source/commonembedding/specialobject.cxx libreoffice-7-0-4/embeddedobj/source/commonembedding/specialobject.cxx --- libreoffice-7-0-4.old/embeddedobj/source/commonembedding/specialobject.cxx 2023-05-24 17:17:08.688721561 +0200 +++ libreoffice-7-0-4/embeddedobj/source/commonembedding/specialobject.cxx 2023-05-24 17:24:13.613547961 +0200 @@ -47,6 +47,7 @@ uno::Any 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 ), @@ -160,4 +161,12 @@ 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 -urN libreoffice-7-0-4.old/embeddedobj/source/inc/commonembobj.hxx libreoffice-7-0-4/embeddedobj/source/inc/commonembobj.hxx --- libreoffice-7-0-4.old/embeddedobj/source/inc/commonembobj.hxx 2023-05-24 17:17:08.688721561 +0200 +++ libreoffice-7-0-4/embeddedobj/source/inc/commonembobj.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -227,6 +227,9 @@ 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 -urN libreoffice-7-0-4.old/embeddedobj/source/inc/specialobject.hxx libreoffice-7-0-4/embeddedobj/source/inc/specialobject.hxx --- libreoffice-7-0-4.old/embeddedobj/source/inc/specialobject.hxx 2023-05-24 17:17:08.688721561 +0200 +++ libreoffice-7-0-4/embeddedobj/source/inc/specialobject.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -48,6 +48,12 @@ 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 -urN libreoffice-7-0-4.old/include/svx/svdoole2.hxx libreoffice-7-0-4/include/svx/svdoole2.hxx --- libreoffice-7-0-4.old/include/svx/svdoole2.hxx 2023-05-24 17:17:08.688721561 +0200 +++ libreoffice-7-0-4/include/svx/svdoole2.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -42,6 +42,7 @@ namespace svt { class EmbeddedObjectRef; } class SdrOle2ObjImpl; +class SvxOle2Shape; class SVXCORE_DLLPUBLIC SdrOle2Obj : public SdrRectObj { @@ -49,7 +50,7 @@ std::unique_ptr mpImpl; private: - SVX_DLLPRIVATE void Connect_Impl(); + SVX_DLLPRIVATE void Connect_Impl(SvxOle2Shape* pCreator = nullptr); SVX_DLLPRIVATE void Disconnect_Impl(); SVX_DLLPRIVATE void AddListeners_Impl(); SVX_DLLPRIVATE void RemoveListeners_Impl(); @@ -105,7 +106,7 @@ // 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). @@ -153,7 +154,7 @@ 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(); @@ -200,6 +201,16 @@ void Connect() { GetRealObject(); } }; +class SVXCORE_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 -urN libreoffice-7-0-4.old/include/svx/unoshape.hxx libreoffice-7-0-4/include/svx/unoshape.hxx --- libreoffice-7-0-4.old/include/svx/unoshape.hxx 2023-05-24 17:17:08.688721561 +0200 +++ libreoffice-7-0-4/include/svx/unoshape.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -607,6 +607,8 @@ bool createObject( const SvGlobalName &aClassName ); void createLink( const OUString& aLinkURL ); + + virtual OUString GetAndClearInitialFrameURL(); }; diff -urN libreoffice-7-0-4.old/sc/source/ui/docshell/documentlinkmgr.cxx libreoffice-7-0-4/sc/source/ui/docshell/documentlinkmgr.cxx --- libreoffice-7-0-4.old/sc/source/ui/docshell/documentlinkmgr.cxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/sc/source/ui/docshell/documentlinkmgr.cxx 2023-05-24 17:24:13.613547961 +0200 @@ -142,7 +142,7 @@ sfx2::SvBaseLink* pBase = rLink.get(); if (bDde && dynamic_cast(pBase)) return true; - if (bOle && dynamic_cast(pBase)) + if (bOle && (dynamic_cast(pBase) || dynamic_cast(pBase))) return true; if (bWebService && dynamic_cast(pBase)) return true; @@ -173,6 +173,13 @@ continue; } + SdrIFrameLink* pIFrameLink = dynamic_cast(pBase); + if (pIFrameLink) + { + pIFrameLink->Update(); + continue; + } + ScWebServiceLink* pWebserviceLink = dynamic_cast(pBase); if (pWebserviceLink) { diff -urN libreoffice-7-0-4.old/sfx2/source/doc/iframe.cxx libreoffice-7-0-4/sfx2/source/doc/iframe.cxx --- libreoffice-7-0-4.old/sfx2/source/doc/iframe.cxx 2023-05-24 17:17:38.000000000 +0200 +++ libreoffice-7-0-4/sfx2/source/doc/iframe.cxx 2023-05-24 17:26:40.329719103 +0200 @@ -33,10 +33,12 @@ #include #include +#include #include #include #include #include +#include #include #include #include @@ -164,41 +166,57 @@ uno::Reference < util::XURLTransformer > xTrans( util::URLTransformer::create( mxContext ) ); xTrans->parseStrict( aTargetURL ); - if (INetURLObject(aTargetURL.Complete).GetProtocol() == INetProtocol::Macro) + INetURLObject aURLObject(aTargetURL.Complete); + if (aURLObject.GetProtocol() == INetProtocol::Macro || aURLObject.isSchemeEqualTo(u"vnd.sun.star.script")) + return false; + + uno::Reference xParentFrame = xFrame->getCreator(); + SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame); + + bool bUpdateAllowed(true); + if (pDoc) + { + comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = pDoc->getEmbeddedObjectContainer(); + bUpdateAllowed = rEmbeddedObjectContainer.getUserAllowsLinkUpdate(); + } + if (!bUpdateAllowed) + return false; + + OUString sReferer; + if (pDoc && pDoc->HasName()) + sReferer = pDoc->GetMedium()->GetName(); + + uno::Reference xParentWindow(xFrame->getContainerWindow()); + + if (!mxFrame.is()) { - uno::Reference xParentFrame = xFrame->getCreator(); - SfxObjectShell* pDoc = SfxMacroLoader::GetObjectShell(xParentFrame); - if (pDoc && !pDoc->AdjustMacroMode()) - return false; + VclPtr pParent = VCLUnoHelper::GetWindow(xParentWindow); + VclPtr pWin = VclPtr::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 ); } - DBG_ASSERT( !mxFrame.is(), "Frame already existing!" ); - VclPtr pParent = VCLUnoHelper::GetWindow( xFrame->getContainerWindow() ); - VclPtr pWin = VclPtr::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(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 ); diff -urN libreoffice-7-0-4.old/svx/source/svdraw/svdoole2.cxx libreoffice-7-0-4/svx/source/svdraw/svdoole2.cxx --- libreoffice-7-0-4.old/svx/source/svdraw/svdoole2.cxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/svx/source/svdraw/svdoole2.cxx 2023-05-24 17:24:13.613547961 +0200 @@ -67,6 +67,7 @@ #include #include #include +#include #include #include #include @@ -591,6 +592,35 @@ 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 xObject = m_pObject->GetObjRef(); + uno::Reference xPersObj(xObject, uno::UNO_QUERY); + if (xPersObj.is()) + { + // let the IFrameObject reload the link + try + { + xPersObj->reload(uno::Sequence(), uno::Sequence()); + } + catch (const uno::Exception&) + { + } + + m_pObject->SetChanged(); + } + + return SUCCESS; +} + class SdrOle2ObjImpl { public: @@ -608,7 +638,7 @@ 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 mxModifyListener; @@ -808,7 +838,7 @@ return !mpImpl->mxObjRef.is(); } -void SdrOle2Obj::Connect() +void SdrOle2Obj::Connect(SvxOle2Shape* pCreator) { if( IsEmptyPresObj() ) return; @@ -821,7 +851,7 @@ return; } - Connect_Impl(); + Connect_Impl(pCreator); AddListeners_Impl(); } @@ -920,24 +950,51 @@ { try { - uno::Reference< embed::XLinkageSupport > xLinkSupport( mpImpl->mxObjRef.GetObject(), uno::UNO_QUERY ); + uno::Reference xObject = mpImpl->mxObjRef.GetObject(); + if (!xObject) + return; + + bool bIFrame = false; + + OUString aLinkURL; + uno::Reference xLinkSupport(xObject, uno::UNO_QUERY); + if (xLinkSupport) + { + if (xLinkSupport->isLink()) + aLinkURL = xLinkSupport->getLinkURL(); + } + else + { + // get IFrame (Floating Frames) listed and updatable from the + // manage links dialog + SvGlobalName aClassId(xObject->getClassID()); + if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID)) + { + uno::Reference xSet(xObject->getComponent(), uno::UNO_QUERY); + if (xSet.is()) + xSet->getPropertyValue("FrameURL") >>= aLinkURL; + bIFrame = true; + } + } - if ( xLinkSupport.is() && xLinkSupport->isLink() ) + if (!aLinkURL.isEmpty()) // this is a file link so the model link manager should handle it { - OUString aLinkURL = xLinkSupport->getLinkURL(); + sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager()); - if ( !aLinkURL.isEmpty() ) + if ( pLinkManager ) { - // this is a file link so the model link manager should handle it - sfx2::LinkManager* pLinkManager(getSdrModelFromSdrObject().GetLinkManager()); - - if ( pLinkManager ) + SdrEmbedObjectLink* pEmbedObjectLink = nullptr; + if (!bIFrame) { - mpImpl->mpObjectLink = new SdrEmbedObjectLink( this ); - mpImpl->maLinkURL = aLinkURL; - pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL ); - mpImpl->mpObjectLink->Connect(); + pEmbedObjectLink = new SdrEmbedObjectLink(this); + mpImpl->mpObjectLink = pEmbedObjectLink; } + else + mpImpl->mpObjectLink = new SdrIFrameLink(this); + mpImpl->maLinkURL = aLinkURL; + pLinkManager->InsertFileLink( *mpImpl->mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL ); + if (pEmbedObjectLink) + pEmbedObjectLink->Connect(); } } } @@ -948,7 +1005,7 @@ } } -void SdrOle2Obj::Connect_Impl() +void SdrOle2Obj::Connect_Impl(SvxOle2Shape* pCreator) { if(!mpImpl->aPersistName.isEmpty() ) { @@ -988,6 +1045,17 @@ } } + if (pCreator) + { + OUString sFrameURL(pCreator->GetAndClearInitialFrameURL()); + if (!sFrameURL.isEmpty() && svt::EmbeddedObjectRef::TryRunningState(mpImpl->mxObjRef.GetObject())) + { + uno::Reference xSet(mpImpl->mxObjRef->getComponent(), uno::UNO_QUERY); + if (xSet.is()) + xSet->setPropertyValue("FrameURL", uno::Any(sFrameURL)); + } + } + if ( mpImpl->mxObjRef.is() ) { if ( !mpImpl->mxLightClient.is() ) @@ -1301,14 +1369,14 @@ 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 -urN libreoffice-7-0-4.old/svx/source/unodraw/shapeimpl.hxx libreoffice-7-0-4/svx/source/unodraw/shapeimpl.hxx --- libreoffice-7-0-4.old/svx/source/unodraw/shapeimpl.hxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/svx/source/unodraw/shapeimpl.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -64,8 +64,11 @@ 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; @@ -82,6 +85,8 @@ 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 -urN libreoffice-7-0-4.old/svx/source/unodraw/unoshap4.cxx libreoffice-7-0-4/svx/source/unodraw/unoshap4.cxx --- libreoffice-7-0-4.old/svx/source/unodraw/unoshap4.cxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/svx/source/unodraw/unoshap4.cxx 2023-05-24 17:24:13.613547961 +0200 @@ -174,7 +174,7 @@ #else pOle = static_cast(GetSdrObject()); #endif - pOle->SetPersistName( aPersistName ); + pOle->SetPersistName( aPersistName, this ); return true; } break; @@ -495,10 +495,11 @@ void SvxOle2Shape::resetModifiedState() { - ::comphelper::IEmbeddedHelper* pPersist = GetSdrObject()->getSdrModelFromSdrObject().GetPersist(); + SdrObject* pObject = GetSdrObject(); + ::comphelper::IEmbeddedHelper* pPersist = pObject ? pObject->getSdrModelFromSdrObject().GetPersist() : nullptr; if( pPersist && !pPersist->isEnableSetModified() ) { - SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >( GetSdrObject() ); + SdrOle2Obj* pOle = dynamic_cast< SdrOle2Obj* >(pObject); if( pOle && !pOle->IsEmpty() ) { uno::Reference < util::XModifiable > xMod( pOle->GetObjRef(), uno::UNO_QUERY ); @@ -548,6 +549,11 @@ return aClassName; } +OUString SvxOle2Shape::GetAndClearInitialFrameURL() +{ + return OUString(); +} + SvxAppletShape::SvxAppletShape(SdrObject* pObject) : SvxOle2Shape( pObject, getSvxMapProvider().GetMap(SVXMAP_APPLET), getSvxMapProvider().GetPropertySet(SVXMAP_APPLET, SdrObject::GetGlobalDrawObjectItemPool()) ) { @@ -701,8 +707,19 @@ { } +OUString SvxFrameShape::GetAndClearInitialFrameURL() +{ + OUString sRet(m_sInitialFrameURL); + m_sInitialFrameURL.clear(); + return sRet; +} + void SvxFrameShape::Create( SdrObject* pNewObj, SvxDrawPage* pNewPage ) { + uno::Reference xSet(static_cast(this), uno::UNO_QUERY); + if (xSet) + xSet->getPropertyValue("FrameURL") >>= m_sInitialFrameURL; + SvxShape::Create( pNewObj, pNewPage ); const SvGlobalName aIFrameClassId( SO3_IFRAME_CLASSID ); createObject(aIFrameClassId); diff -urN libreoffice-7-0-4.old/sw/inc/ndole.hxx libreoffice-7-0-4/sw/inc/ndole.hxx --- libreoffice-7-0-4.old/sw/inc/ndole.hxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/sw/inc/ndole.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -28,7 +28,7 @@ class SwDoc; class SwOLENode; class SwOLEListener_Impl; -class SwEmbedObjectLink; +namespace sfx2 { class SvBaseLink; } class DeflateData; class SW_DLLPUBLIC SwOLEObj @@ -90,7 +90,7 @@ bool mbOLESizeInvalid; /**< Should be considered at SwDoc::PrtOLENotify (e.g. copied). Is not persistent. */ - SwEmbedObjectLink* mpObjectLink; + sfx2::SvBaseLink* mpObjectLink; OUString maLinkURL; SwOLENode( const SwNodeIndex &rWhere, diff -urN libreoffice-7-0-4.old/sw/source/core/ole/ndole.cxx libreoffice-7-0-4/sw/source/core/ole/ndole.cxx --- libreoffice-7-0-4.old/sw/source/core/ole/ndole.cxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/sw/source/core/ole/ndole.cxx 2023-05-24 17:24:13.613547961 +0200 @@ -146,6 +146,8 @@ // 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; @@ -208,6 +210,44 @@ 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 xObject = m_pOleNode->GetOLEObj().GetOleRef(); + uno::Reference xPersObj(xObject, uno::UNO_QUERY); + if (xPersObj.is()) + { + // let the IFrameObject reload the link + try + { + xPersObj->reload(uno::Sequence(), uno::Sequence()); + } + catch (const uno::Exception&) + { + } + + m_pOleNode->SetChanged(); + } + + return SUCCESS; + } + +}; + +} + SwOLENode::SwOLENode( const SwNodeIndex &rWhere, const svt::EmbeddedObjectRef& xObj, SwGrfFormatColl *pGrfColl, @@ -605,18 +645,49 @@ { try { - uno::Reference< embed::XLinkageSupport > xLinkSupport( maOLEObj.m_xOLERef.GetObject(), uno::UNO_QUERY_THROW ); - if ( xLinkSupport->isLink() ) + uno::Reference xObject = maOLEObj.m_xOLERef.GetObject(); + if (!xObject) + return; + + bool bIFrame = false; + + OUString aLinkURL; + uno::Reference xLinkSupport(xObject, uno::UNO_QUERY); + if (xLinkSupport) + { + if (xLinkSupport->isLink()) + aLinkURL = xLinkSupport->getLinkURL(); + } + else + { + // get IFrame (Floating Frames) listed and updatable from the + // manage links dialog + SvGlobalName aClassId(xObject->getClassID()); + if (aClassId == SvGlobalName(SO3_IFRAME_CLASSID)) + { + uno::Reference 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 { - const OUString aLinkURL = xLinkSupport->getLinkURL(); - if ( !aLinkURL.isEmpty() ) + 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, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL ); - mpObjectLink->Connect(); + mpObjectLink = new SwIFrameLink(this); } + maLinkURL = aLinkURL; + GetDoc()->getIDocumentLinksAdministration().GetLinkManager().InsertFileLink( *mpObjectLink, sfx2::SvBaseLinkObjectType::ClientOle, aLinkURL ); + if (pEmbedObjectLink) + pEmbedObjectLink->Connect(); } } catch( uno::Exception& ) diff -urN libreoffice-7-0-4.old/xmloff/source/draw/ximpshap.cxx libreoffice-7-0-4/xmloff/source/draw/ximpshap.cxx --- libreoffice-7-0-4.old/xmloff/source/draw/ximpshap.cxx 2023-05-24 17:17:38.000000000 +0200 +++ libreoffice-7-0-4/xmloff/source/draw/ximpshap.cxx 2023-05-24 17:26:15.413109472 +0200 @@ -3245,9 +3245,35 @@ { } +uno::Reference SdXMLFloatingFrameShapeContext::CreateFloatingFrameShape() const +{ + uno::Reference xServiceFact(GetImport().GetModel(), uno::UNO_QUERY); + if (!xServiceFact.is()) + return nullptr; + uno::Reference 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 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() ) { @@ -3256,7 +3282,6 @@ // set pos, size, shear and rotate SetTransformation(); - uno::Reference< beans::XPropertySet > xProps( mxShape, uno::UNO_QUERY ); if( xProps.is() ) { if( !maFrameName.isEmpty() ) diff -urN libreoffice-7-0-4.old/xmloff/source/draw/ximpshap.hxx libreoffice-7-0-4/xmloff/source/draw/ximpshap.hxx --- libreoffice-7-0-4.old/xmloff/source/draw/ximpshap.hxx 2023-05-24 17:17:08.692721562 +0200 +++ libreoffice-7-0-4/xmloff/source/draw/ximpshap.hxx 2023-05-24 17:24:13.613547961 +0200 @@ -513,6 +513,8 @@ OUString maFrameName; OUString maHref; + css::uno::Reference CreateFloatingFrameShape() const; + public: SdXMLFloatingFrameShapeContext( SvXMLImport& rImport, sal_uInt16 nPrfx,