diff --git a/include/vcl/errinf.hxx b/include/vcl/errinf.hxx index 88f4a3bb2390..670c085cf495 100644 --- a/include/vcl/errinf.hxx +++ b/include/vcl/errinf.hxx @@ -65,11 +65,18 @@ public: static void RegisterDisplay(BasicDisplayErrorFunc*); static void RegisterDisplay(WindowDisplayErrorFunc*); + + static void SetLock(bool bLock); + static bool GetLock(); + static void Reset(); private: DisplayFnPtr pDsp; bool bIsWindowDsp; + + bool m_bLock; + sal_uInt16 nNextError; std::vector errorHandlers; diff --git a/sw/qa/core/unocore/data/broken-embedded-object.odt b/sw/qa/core/unocore/data/broken-embedded-object.odt new file mode 100644 index 000000000000..94a0809235e9 Binary files /dev/null and b/sw/qa/core/unocore/data/broken-embedded-object.odt differ diff --git a/sw/qa/core/unocore/unocore.cxx b/sw/qa/core/unocore/unocore.cxx index 520c1e21ea28..a480a082f975 100644 --- a/sw/qa/core/unocore/unocore.cxx +++ b/sw/qa/core/unocore/unocore.cxx @@ -16,6 +16,7 @@ #include #include +#include #include #include @@ -184,6 +185,36 @@ CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testViewCursorTextFrame) xStorable->storeToURL(maTempFile.GetURL(), aStoreArgs); } +/// Fails the test if an error popup would be presented. +static void BasicDisplayErrorHandler(const OUString& /*rErr*/, const OUString& /*rAction*/) +{ + CPPUNIT_ASSERT(false); +} + +CPPUNIT_TEST_FIXTURE(SwCoreUnocoreTest, testBrokenEmbeddedObject) +{ + // Given a document with a broken embedded object (the XML markup is not well-formed): + load(DATA_DIRECTORY, "broken-embedded-object.odt"); + uno::Reference xSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference xObjects(xSupplier->getEmbeddedObjects(), + uno::UNO_QUERY); + uno::Reference xObject(xObjects->getByIndex(0), uno::UNO_QUERY); + uno::Reference xEmbeddedObject; + // Get the property first, which initializes Draw, which would overwrite our error handler. + xObject->getPropertyValue("EmbeddedObject") >>= xEmbeddedObject; + ErrorRegistry::RegisterDisplay(&BasicDisplayErrorHandler); + + // When trying to load that embedded object: + xObject->getPropertyValue("EmbeddedObject") >>= xEmbeddedObject; + + // Then make sure we get a non-empty reference and an error popup it not shown: + CPPUNIT_ASSERT(xEmbeddedObject.is()); + // Without the accompanying fix in place, we got this reference, but first an error popup was + // shown to the user. + CPPUNIT_ASSERT( + xEmbeddedObject->supportsService("com.sun.star.comp.embed.OCommonEmbeddedObject")); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/unocore/unoframe.cxx b/sw/source/core/unocore/unoframe.cxx index dd6de80c47af..dcf25fadde59 100644 --- a/sw/source/core/unocore/unoframe.cxx +++ b/sw/source/core/unocore/unoframe.cxx @@ -112,6 +112,7 @@ #include #include #include +#include #include #include @@ -1977,9 +1978,28 @@ void SwXFrame::setPropertyValue(const OUString& rPropertyName, const ::uno::Any& throw uno::RuntimeException(); } +namespace +{ +/// Redirect error popups to developer warnings for the duration of the UNO API call. +class DisplayLockGuard +{ + bool m_bLock; + +public: + DisplayLockGuard() + { + m_bLock = ErrorRegistry::GetLock(); + ErrorRegistry::SetLock(true); + } + + ~DisplayLockGuard() { ErrorRegistry::SetLock(m_bLock); } +}; +} + uno::Any SwXFrame::getPropertyValue(const OUString& rPropertyName) { SolarMutexGuard aGuard; + DisplayLockGuard aDisplayGuard; uno::Any aAny; SwFrameFormat* pFormat = GetFrameFormat(); const SfxItemPropertyMapEntry* pEntry = m_pPropSet->getPropertyMap().getByName(rPropertyName); diff --git a/vcl/source/window/errinf.cxx b/vcl/source/window/errinf.cxx index cf829175edff..71191122b2c5 100644 --- a/vcl/source/window/errinf.cxx +++ b/vcl/source/window/errinf.cxx @@ -51,6 +51,7 @@ bool ErrorStringFactory::CreateString(const ErrorInfo* pInfo, OUString& rStr) ErrorRegistry::ErrorRegistry() : pDsp(nullptr) , bIsWindowDsp(false) + , m_bLock(false) , nNextError(0) { for(DynamicErrorInfo*& rp : ppDynErrInfo) @@ -71,6 +72,18 @@ void ErrorRegistry::RegisterDisplay(WindowDisplayErrorFunc *aDsp) rData.pDsp = reinterpret_cast< DisplayFnPtr >(aDsp); } +void ErrorRegistry::SetLock(bool bLock) +{ + ErrorRegistry& rData = GetErrorRegistry(); + rData.m_bLock = bLock; +} + +bool ErrorRegistry::GetLock() +{ + ErrorRegistry& rData = GetErrorRegistry(); + return rData.m_bLock; +} + void ErrorRegistry::Reset() { ErrorRegistry &rData = GetErrorRegistry(); @@ -157,7 +170,7 @@ DialogMask ErrorHandler::HandleError(ErrCode nErrCodeId, weld::Window *pParent, OUString aErr; if (ErrorStringFactory::CreateString(pInfo.get(), aErr)) { - if(!rData.pDsp) + if (!rData.pDsp || rData.m_bLock) { SAL_WARN( "vcl", "Action: " << aAction << "Error: " << aErr); }