summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/source/lib/init.cxx18
-rw-r--r--sfx2/source/view/lokhelper.cxx61
2 files changed, 55 insertions, 24 deletions
diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx
index 8d3b0ddf7e26..2bfe8ae373d6 100644
--- a/desktop/source/lib/init.cxx
+++ b/desktop/source/lib/init.cxx
@@ -5042,28 +5042,14 @@ static void doc_destroyView(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis
SfxLokHelper::destroyView(nId);
}
-static void doc_setView(LibreOfficeKitDocument* pThis, int nId)
+static void doc_setView(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int nId)
{
comphelper::ProfileZone aZone("doc_setView");
SolarMutexGuard aGuard;
SetLastExceptionMsg();
- LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis);
- const auto handlerIt = pDocument->mpCallbackFlushHandlers.find(nId);
- if (handlerIt != pDocument->mpCallbackFlushHandlers.end())
- handlerIt->second->disableCallbacks();
-
- try
- {
- SfxLokHelper::setView(nId);
- }
- catch (const std::exception&)
- {
- }
-
- if (handlerIt != pDocument->mpCallbackFlushHandlers.end())
- handlerIt->second->enableCallbacks();
+ SfxLokHelper::setView(nId);
}
static int doc_getView(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/)
diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx
index f4c9e6cbdb8d..9277ac5760c4 100644
--- a/sfx2/source/view/lokhelper.cxx
+++ b/sfx2/source/view/lokhelper.cxx
@@ -32,6 +32,36 @@
using namespace com::sun::star;
+namespace {
+/// Used to disable callbacks.
+/// Needed to avoid recursion when switching views,
+/// which can cause clients to invoke LOKit API and
+/// implicitly set the view, which might cause an
+/// infinite recursion if not detected and prevented.
+class DisableCallbacks
+{
+public:
+ DisableCallbacks()
+ {
+ assert(m_nDisabled >= 0 && "Expected non-negative DisabledCallbacks state when disabling.");
+ ++m_nDisabled;
+ }
+
+ ~DisableCallbacks()
+ {
+ assert(m_nDisabled > 0 && "Expected positive DisabledCallbacks state when re-enabling.");
+ --m_nDisabled;
+ }
+
+ static bool disabled() { return m_nDisabled != 0; }
+
+private:
+ static int m_nDisabled;
+};
+
+int DisableCallbacks::m_nDisabled = 0;
+}
+
int SfxLokHelper::createView()
{
SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst();
@@ -79,6 +109,8 @@ void SfxLokHelper::setView(int nId)
{
if (static_cast<sal_Int32>(pViewShell->GetViewShellId()) == nViewShellId)
{
+ DisableCallbacks dc;
+
// update the current LOK language for the dialog tunneling
comphelper::LibreOfficeKit::setLanguageTag(pViewShell->GetLOKLanguageTag());
@@ -164,6 +196,9 @@ static OString lcl_escapeQuotes(const OString &rStr)
void SfxLokHelper::notifyOtherView(SfxViewShell* pThisView, SfxViewShell const* pOtherView, int nType, const OString& rKey, const OString& rPayload)
{
+ if (DisableCallbacks::disabled())
+ return;
+
OString aPayload = OStringLiteral("{ \"viewId\": \"") + OString::number(SfxLokHelper::getView(pThisView)) +
"\", \"part\": \"" + OString::number(pThisView->getPart()) +
"\", \"" + rKey + "\": \"" + lcl_escapeQuotes(rPayload) + "\" }";
@@ -173,7 +208,7 @@ void SfxLokHelper::notifyOtherView(SfxViewShell* pThisView, SfxViewShell const*
void SfxLokHelper::notifyOtherViews(SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload)
{
- if (SfxLokHelper::getViewsCount() <= 1)
+ if (SfxLokHelper::getViewsCount() <= 1 || DisableCallbacks::disabled())
return;
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
@@ -210,7 +245,7 @@ namespace {
void SfxLokHelper::sendUnoStatus(const SfxViewShell* pShell, const SfxPoolItem* pItem)
{
- if (!pShell || !pItem || pItem == INVALID_POOL_ITEM)
+ if (!pShell || !pItem || pItem == INVALID_POOL_ITEM || DisableCallbacks::disabled())
return;
boost::property_tree::ptree aItem = pItem->dumpAsJSON();
@@ -234,7 +269,7 @@ void SfxLokHelper::notifyWindow(const SfxViewShell* pThisView,
{
assert(pThisView);
- if (SfxLokHelper::getViewsCount() <= 0 || nLOKWindowId == 0)
+ if (SfxLokHelper::getViewsCount() <= 0 || nLOKWindowId == 0 || DisableCallbacks::disabled())
return;
OStringBuffer aPayload;
@@ -258,6 +293,10 @@ void SfxLokHelper::notifyWindow(const SfxViewShell* pThisView,
void SfxLokHelper::notifyInvalidation(SfxViewShell const* pThisView, const OString& rPayload)
{
OStringBuffer aBuf(32);
+
+ if (DisableCallbacks::disabled())
+ return;
+
aBuf.append(rPayload);
if (comphelper::LibreOfficeKit::isPartInInvalidation())
{
@@ -269,10 +308,7 @@ void SfxLokHelper::notifyInvalidation(SfxViewShell const* pThisView, const OStri
void SfxLokHelper::notifyDocumentSizeChanged(SfxViewShell const* pThisView, const OString& rPayload, vcl::ITiledRenderable* pDoc, bool bInvalidateAll)
{
- if (!comphelper::LibreOfficeKit::isActive())
- return;
-
- if (!pDoc)
+ if (!pDoc || !comphelper::LibreOfficeKit::isActive() || DisableCallbacks::disabled())
return;
if (bInvalidateAll)
@@ -289,7 +325,7 @@ void SfxLokHelper::notifyDocumentSizeChanged(SfxViewShell const* pThisView, cons
void SfxLokHelper::notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc, bool bInvalidateAll)
{
- if (!comphelper::LibreOfficeKit::isActive())
+ if (!comphelper::LibreOfficeKit::isActive() || DisableCallbacks::disabled())
return;
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
@@ -302,6 +338,9 @@ void SfxLokHelper::notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc
void SfxLokHelper::notifyVisCursorInvalidation(OutlinerViewShell const* pThisView, const OString& rRectangle, bool bMispelledWord, const OString& rHyperlink)
{
+ if (DisableCallbacks::disabled())
+ return;
+
OString sPayload;
if (comphelper::LibreOfficeKit::isViewIdForVisCursorInvalidation())
{
@@ -320,6 +359,9 @@ void SfxLokHelper::notifyVisCursorInvalidation(OutlinerViewShell const* pThisVie
void SfxLokHelper::notifyAllViews(int nType, const OString& rPayload)
{
+ if (DisableCallbacks::disabled())
+ return;
+
const auto payload = rPayload.getStr();
SfxViewShell* pViewShell = SfxViewShell::GetFirst();
while (pViewShell)
@@ -331,6 +373,9 @@ void SfxLokHelper::notifyAllViews(int nType, const OString& rPayload)
void SfxLokHelper::notifyContextChange(SfxViewShell const* pViewShell, const OUString& aApplication, const OUString& aContext)
{
+ if (DisableCallbacks::disabled())
+ return;
+
OString aBuffer =
OUStringToOString(aApplication.replace(' ', '_'), RTL_TEXTENCODING_UTF8) +
" " +