diff options
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 15 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 88 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.h | 2 | ||||
-rw-r--r-- | include/LibreOfficeKit/LibreOfficeKit.hxx | 13 | ||||
-rw-r--r-- | sfx2/source/appl/macroloader.cxx | 18 |
5 files changed, 135 insertions, 1 deletions
diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index 62ec69d63576..81cbecedc686 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -107,6 +107,7 @@ public: void testCommentsCalc(); void testCommentsImpress(); void testCommentsCallbacksWriter(); + void testRunMacro(); CPPUNIT_TEST_SUITE(DesktopLOKTest); CPPUNIT_TEST(testGetStyles); @@ -145,6 +146,7 @@ public: CPPUNIT_TEST(testCommentsCalc); CPPUNIT_TEST(testCommentsImpress); CPPUNIT_TEST(testCommentsCallbacksWriter); + CPPUNIT_TEST(testRunMacro); CPPUNIT_TEST_SUITE_END(); uno::Reference<lang::XComponent> mxComponent; @@ -2096,6 +2098,19 @@ void DesktopLOKTest::testCommentsCallbacksWriter() comphelper::LibreOfficeKit::setActive(false); } +void DesktopLOKTest::testRunMacro() +{ + LibLibreOffice_Impl aOffice; + bool bGoodMacro, bNonExistentMacro; + + // Tools macros come pre-installed in system share/basic folder, + bGoodMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, OString("macro:///Tools.Debug.ActivateReadOnlyFlag()").getStr()); + CPPUNIT_ASSERT(bGoodMacro); + + bNonExistentMacro = aOffice.m_pOfficeClass->runMacro(&aOffice, OString("macro:///I.Am.Not(There)").getStr()); + CPPUNIT_ASSERT(!bNonExistentMacro); +} + CPPUNIT_TEST_SUITE_REGISTRATION(DesktopLOKTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 61fbc61889a3..56d70b261849 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -40,6 +40,8 @@ #include <com/sun/star/frame/Desktop.hpp> #include <com/sun/star/frame/DispatchResultEvent.hpp> #include <com/sun/star/frame/DispatchResultState.hpp> +#include <com/sun/star/frame/XDispatchProvider.hpp> +#include <com/sun/star/frame/XSynchronousDispatch.hpp> #include <com/sun/star/frame/XStorable.hpp> #include <com/sun/star/lang/Locale.hpp> #include <com/sun/star/lang/XComponent.hpp> @@ -1054,6 +1056,7 @@ static void doc_destroy(LibreOfficeKitDocument *pThis) static void lo_destroy (LibreOfficeKit* pThis); static int lo_initialize (LibreOfficeKit* pThis, const char* pInstallPath, const char* pUserProfilePath); static LibreOfficeKitDocument* lo_documentLoad (LibreOfficeKit* pThis, const char* pURL); +static bool lo_runMacro (LibreOfficeKit* pThis, const char* pURL); static char * lo_getError (LibreOfficeKit* pThis); static void lo_freeError (char* pFree); static LibreOfficeKitDocument* lo_documentLoadWithOptions (LibreOfficeKit* pThis, @@ -1082,6 +1085,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl() m_pOfficeClass->destroy = lo_destroy; m_pOfficeClass->documentLoad = lo_documentLoad; + m_pOfficeClass->runMacro = lo_runMacro; m_pOfficeClass->getError = lo_getError; m_pOfficeClass->freeError = lo_freeError; m_pOfficeClass->documentLoadWithOptions = lo_documentLoadWithOptions; @@ -1211,6 +1215,90 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, return nullptr; } +static bool lo_runMacro( LibreOfficeKit* pThis, const char *pURL) +{ + SolarMutexGuard aGuard; + + LibLibreOffice_Impl* pLib = static_cast<LibLibreOffice_Impl*>(pThis); + + OUString sURL( pURL, strlen(pURL), RTL_TEXTENCODING_UTF8 ); + if (sURL.isEmpty()) + { + pLib->maLastExceptionMsg = "Macro to run was not provided."; + SAL_INFO("lok", "Macro URL is empty"); + return false; + } + + if (!sURL.startsWith("macro://")) + { + pLib->maLastExceptionMsg = "This doesn't look like macro URL"; + SAL_INFO("lok", "Macro URL is invalid"); + return false; + } + + pLib->maLastExceptionMsg.clear(); + + if (!xContext.is()) + { + pLib->maLastExceptionMsg = "ComponentContext is not available"; + SAL_INFO("lok", "ComponentContext is not available"); + return false; + } + + util::URL aURL; + aURL.Complete = sURL; + + uno::Reference < util::XURLTransformer > xParser( util::URLTransformer::create( xContext ) ); + + if( xParser.is() ) + xParser->parseStrict( aURL ); + + uno::Reference<frame::XDesktop2> xComponentLoader = frame::Desktop::create(xContext); + + if (!xComponentLoader.is()) + { + pLib->maLastExceptionMsg = "ComponentLoader is not available"; + SAL_INFO("lok", "ComponentLoader is not available"); + return false; + } + + xFactory = xContext->getServiceManager(); + + if (xFactory.is()) + { + uno::Reference<frame::XDispatchProvider> xDP; + xSFactory.set(xFactory, uno::UNO_QUERY_THROW); + xDP.set( xSFactory->createInstance("com.sun.star.comp.sfx2.SfxMacroLoader"), uno::UNO_QUERY ); + uno::Reference<frame::XDispatch> xD = xDP->queryDispatch( aURL, OUString(), 0); + + if (!xD.is()) + { + pLib->maLastExceptionMsg = "Macro loader is not available"; + SAL_INFO("lok", "Macro loader is not available"); + return false; + } + + uno::Reference < frame::XSynchronousDispatch > xSyncDisp( xD, uno::UNO_QUERY_THROW ); + uno::Sequence<css::beans::PropertyValue> aEmpty; + css::beans::PropertyValue aErr; + uno::Any aRet; + + aRet = xSyncDisp->dispatchWithReturnValue( aURL, aEmpty ); + aRet >>= aErr; + + if (aErr.Name == "ErrorCode") + { + pLib->maLastExceptionMsg = "An error occured running macro"; + SAL_INFO("lok", "Macro execution terminated with errors"); + return false; + } + + return true; + } + + return false; +} + static void lo_registerCallback (LibreOfficeKit* pThis, LibreOfficeKitCallback pCallback, void* pData) diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index c7a2130315da..2a5dbcabb817 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -78,6 +78,8 @@ struct _LibreOfficeKitClass /// @see lok::Office::getVersionInfo(). char* (*getVersionInfo) (LibreOfficeKit* pThis); + + bool (*runMacro) (LibreOfficeKit *pThis, const char* pURL); #endif }; diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index 447f44b09885..57b86f9be9fc 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -591,6 +591,19 @@ public: { return mpThis->pClass->getVersionInfo(mpThis); } + + /** + * Run a macro. + * + * Same syntax as on command line is permissible (ie. the macro:// URI forms) + * + * @param pURL macro url to run + */ + + inline bool runMacro( const char* pURL) + { + return mpThis->pClass->runMacro( mpThis, pURL ); + } #endif // defined LOK_USE_UNSTABLE_API || defined LIBO_INTERNAL_ONLY }; diff --git a/sfx2/source/appl/macroloader.cxx b/sfx2/source/appl/macroloader.cxx index 19737c90b22a..ce1e85e0c88b 100644 --- a/sfx2/source/appl/macroloader.cxx +++ b/sfx2/source/appl/macroloader.cxx @@ -147,7 +147,23 @@ uno::Any SAL_CALL SfxMacroLoader::dispatchWithReturnValue( const util::URL& aURL, const uno::Sequence<beans::PropertyValue>& ) { uno::Any aRet; - loadMacro( aURL.Complete, aRet, GetObjectShell_Impl() ); + ErrCode nErr = loadMacro( aURL.Complete, aRet, GetObjectShell_Impl() ); + + // aRet gets set to a different value only if nErr == ERRCODE_NONE + // Return it in such case to preserve the original behaviour + + // In all other cases (nErr != ERRCODE_NONE), the calling code gets + // the actual error code back + if ( nErr != ERRCODE_NONE ) + { + beans::PropertyValue aErrorCode; + + aErrorCode.Name = "ErrorCode"; + aErrorCode.Value <<= nErr; + + aRet <<= aErrorCode; + } + return aRet; } |