From 41ff704cc49b7097b717882616011962ecd7198f Mon Sep 17 00:00:00 2001 From: Tor Lillqvist Date: Wed, 21 Apr 2021 17:37:57 +0300 Subject: Add API to LibreOfficeKit to set arbitrary run-time options in core Add setOption(const char*, const char*) At the moment this enables starting and stopping the ProfileZone event recording and overriding the SAL_LOG environment variable. Change-Id: Ic3a934bb4246c755a91eee8a8343fafc15815116 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114439 Tested-by: Jenkins CollaboraOffice Reviewed-by: Tor Lillqvist Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114559 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/114656 Tested-by: Tor Lillqvist --- desktop/source/lib/init.cxx | 30 +++++++++++++++ include/LibreOfficeKit/LibreOfficeKit.h | 3 ++ include/LibreOfficeKit/LibreOfficeKit.hxx | 33 ++++++++++++++++ include/sal/log.hxx | 2 + sal/osl/all/log.cxx | 63 ++++++++++++++++++------------- sal/util/sal.map | 1 + 6 files changed, 106 insertions(+), 26 deletions(-) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 23400d906628..ecbd0f3f97e5 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2076,6 +2076,8 @@ static void lo_sendDialogEvent(LibreOfficeKit* pThis, unsigned long long int nLOKWindowId, const char* pArguments); +static void lo_setOption(LibreOfficeKit* pThis, const char* pOption, const char* pValue); + LibLibreOffice_Impl::LibLibreOffice_Impl() : m_pOfficeClass( gOfficeClass.lock() ) , maThread(nullptr) @@ -2101,6 +2103,7 @@ LibLibreOffice_Impl::LibLibreOffice_Impl() m_pOfficeClass->signDocument = lo_signDocument; m_pOfficeClass->runLoop = lo_runLoop; m_pOfficeClass->sendDialogEvent = lo_sendDialogEvent; + m_pOfficeClass->setOption = lo_setOption; gOfficeClass = m_pOfficeClass; } @@ -3842,6 +3845,33 @@ static void lo_sendDialogEvent(LibreOfficeKit* /*pThis*/, unsigned long long int lcl_sendDialogEvent(nWindowId, pArguments); } +static void lo_setOption(LibreOfficeKit* /*pThis*/, const char *pOption, const char* pValue) +{ + static char* pCurrentSalLogOverride = nullptr; + + if (strcmp(pOption, "profilezonerecording") == 0) + { + if (strcmp(pValue, "start") == 0) + comphelper::ProfileZone::startRecording(); + else if (strcmp(pValue, "stop") == 0) + comphelper::ProfileZone::stopRecording(); + } + else if (strcmp(pOption, "sallogoverride") == 0) + { + if (pCurrentSalLogOverride != nullptr) + free(pCurrentSalLogOverride); + if (pValue == nullptr) + pCurrentSalLogOverride = nullptr; + else + pCurrentSalLogOverride = strdup(pValue); + + if (pCurrentSalLogOverride == nullptr || pCurrentSalLogOverride[0] == '\0') + sal_detail_set_log_selector(nullptr); + else + sal_detail_set_log_selector(pCurrentSalLogOverride); + } +} + static void doc_postUnoCommand(LibreOfficeKitDocument* pThis, const char* pCommand, const char* pArguments, bool bNotifyWhenFinished) { comphelper::ProfileZone aZone("doc_postUnoCommand"); diff --git a/include/LibreOfficeKit/LibreOfficeKit.h b/include/LibreOfficeKit/LibreOfficeKit.h index 2279260d0e90..82738d65ff93 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.h +++ b/include/LibreOfficeKit/LibreOfficeKit.h @@ -115,6 +115,9 @@ struct _LibreOfficeKitClass void (*sendDialogEvent) (LibreOfficeKit* pThis, unsigned long long int nLOKWindowId, const char* pArguments); + + /// @see lok::Office::setOption + void (*setOption) (LibreOfficeKit* pThis, const char* pOption, const char* pValue); }; #define LIBREOFFICEKIT_DOCUMENT_HAS(pDoc,member) LIBREOFFICEKIT_HAS_MEMBER(LibreOfficeKitDocumentClass,member,(pDoc)->pClass->nSize) diff --git a/include/LibreOfficeKit/LibreOfficeKit.hxx b/include/LibreOfficeKit/LibreOfficeKit.hxx index 962270452e20..06fe5abc19e2 100644 --- a/include/LibreOfficeKit/LibreOfficeKit.hxx +++ b/include/LibreOfficeKit/LibreOfficeKit.hxx @@ -990,6 +990,39 @@ public: { mpThis->pClass->sendDialogEvent(mpThis, nWindowId, pArguments); } + + /** + * Generic function to toggle and tweak various things in the core LO + * + * The currently available option names and their allowed values are: + * + * "profilezonerecording": "start" or "stop" + * Start or stop recording profile zone trace data in the process. + * + * "sallogoverride": "" + * Override the SAL_LOG environment variable + * + * For the syntax of the string see the documentation for "Basic + * logging functionality" in LibreOffice internal API + * documentation (include/sal/log.hxx). If the logging selector + * has been set by this function to a non-empty value, that is used + * instead of the environment variable SAL_LOG. + * + * The parameter is not copied so you should pass a value that + * points to memory that will stay valid until you call setOption + * with this option name the next time. + * + * If you pass nullptr or an empty string as value, the + * environment variable SAL_LOG is again used as by default. You + * can switch back and forth as you like. + * + * @param pOption the option name + * @param pValue its value + */ + void setOption(const char* pOption, const char* pValue) + { + mpThis->pClass->setOption(mpThis, pOption, pValue); + } }; /// Factory method to create a lok::Office instance. diff --git a/include/sal/log.hxx b/include/sal/log.hxx index 6f9da7671b03..943ab3169bca 100644 --- a/include/sal/log.hxx +++ b/include/sal/log.hxx @@ -41,6 +41,8 @@ extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_log( sal_detail_LogLevel level, char const * area, char const * where, char const * message, sal_uInt32 backtraceDepth); +extern "C" SAL_DLLPUBLIC void SAL_CALL sal_detail_set_log_selector(char const *logSelector); + // the return value is actually "enum sal_detail_LogAction", but due to ABI // compatibility, it's left as the original "sal_Bool" / "unsigned char". extern "C" SAL_DLLPUBLIC unsigned char SAL_CALL sal_detail_log_report( diff --git a/sal/osl/all/log.cxx b/sal/osl/all/log.cxx index 927e78b97064..c493f4ddf03e 100644 --- a/sal/osl/all/log.cxx +++ b/sal/osl/all/log.cxx @@ -125,7 +125,9 @@ char const* setEnvFromLoggingIniFile(const char* env, const char* key) } #endif -char const * getLogLevel() { +char const* pLogSelector = nullptr; + +char const* getLogLevelEnvVar() { static char const* const pLevel = [] { char const* pResult = nullptr; @@ -176,33 +178,36 @@ std::ofstream * getLogFile() { return pFile; } -void maybeOutputTimestamp(std::ostringstream &s) { - static const std::pair aFlags = [] { - char const* env = getLogLevel(); - bool outputTimestamp = false; - bool outputRelativeTimer = false; - for (char const* p = env; p && *p;) + +std::pair getTimestampFlags(char const *selector) +{ + bool outputTimestamp = false; + bool outputRelativeTimer = false; + for (char const* p = selector; p && *p;) { if (*p++ == '+') - { - char const * p1 = p; - while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') { - ++p1; - } - if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP"))) - outputTimestamp = true; - else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER"))) - outputRelativeTimer = true; - char const * p2 = p1; - while (*p2 != '+' && *p2 != '-' && *p2 != '\0') { - ++p2; + { + char const * p1 = p; + while (*p1 != '.' && *p1 != '+' && *p1 != '-' && *p1 != '\0') { + ++p1; + } + if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("TIMESTAMP"))) + outputTimestamp = true; + else if (equalStrings(p, p1 - p, RTL_CONSTASCII_STRINGPARAM("RELATIVETIMER"))) + outputRelativeTimer = true; + char const * p2 = p1; + while (*p2 != '+' && *p2 != '-' && *p2 != '\0') { + ++p2; + } + p = p2; } - p = p2; - } } - return std::pair(outputTimestamp, outputRelativeTimer); - }(); - const auto& [outputTimestamp, outputRelativeTimer] = aFlags; + return std::pair(outputTimestamp, outputRelativeTimer); +} + +void maybeOutputTimestamp(std::ostringstream &s) { + static const std::pair aEnvFlags = getTimestampFlags(getLogLevelEnvVar()); + const auto& [outputTimestamp, outputRelativeTimer] = (pLogSelector == nullptr ? aEnvFlags : getTimestampFlags(pLogSelector)); if (outputTimestamp) { @@ -340,6 +345,11 @@ void sal_detail_log( #endif } +void sal_detail_set_log_selector(char const *logSelector) +{ + pLogSelector = logSelector; +} + void sal_detail_logFormat( sal_detail_LogLevel level, char const * area, char const * where, char const * format, ...) @@ -372,12 +382,13 @@ unsigned char sal_detail_log_report(sal_detail_LogLevel level, char const * area return SAL_DETAIL_LOG_ACTION_LOG; } assert(area != nullptr); - static char const* const env = [] { - char const* pResult = getLogLevel(); + static char const* const envEnv = [] { + char const* pResult = getLogLevelEnvVar(); if (!pResult) pResult = "+WARN"; return pResult; }(); + char const* const env = (pLogSelector == nullptr ? envEnv : pLogSelector); std::size_t areaLen = std::strlen(area); enum Sense { POSITIVE = 0, NEGATIVE = 1 }; std::size_t senseLen[2] = { 0, 1 }; diff --git a/sal/util/sal.map b/sal/util/sal.map index dbd22c36ee16..49efb2a436cd 100644 --- a/sal/util/sal.map +++ b/sal/util/sal.map @@ -747,6 +747,7 @@ PRIVATE_1.6 { # LibreOffice 6.4 global: rtl_str_toInt64_WithLength; rtl_ustr_toInt64_WithLength; + sal_detail_set_log_selector; } PRIVATE_1.5; PRIVATE_1.7 { # LibreOffice 7.1 -- cgit