[Libreoffice-commits] core.git: 2 commits - desktop/Library_sofficeapp.mk desktop/source desktop/unx

Stephan Bergmann sbergman at redhat.com
Mon Apr 4 15:35:54 UTC 2016


 desktop/Library_sofficeapp.mk          |    5 
 desktop/source/app/officeipcthread.cxx |  799 +++++++++++++++++++++++----------
 desktop/source/app/officeipcthread.hxx |   10 
 desktop/unx/source/start.c             |    2 
 4 files changed, 574 insertions(+), 242 deletions(-)

New commits:
commit 5da71ff3b088f224cd3a731ce51c620e0cd3e5d3
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Mon Apr 4 17:34:03 2016 +0200

    Add DBus-based IPC mechanism for xdg-app
    
    first cut; triggered on LIBO_XDGAPP env var for now
    
    Change-Id: If4586aedb58499e36a5d87cc8d171400ce7e9499

diff --git a/desktop/Library_sofficeapp.mk b/desktop/Library_sofficeapp.mk
index 30dc907..04bc491 100644
--- a/desktop/Library_sofficeapp.mk
+++ b/desktop/Library_sofficeapp.mk
@@ -23,7 +23,10 @@ $(eval $(call gb_Library_add_libs,sofficeapp,\
     ) \
 ))
 
-$(eval $(call gb_Library_use_external,sofficeapp,boost_headers))
+$(eval $(call gb_Library_use_externals,sofficeapp, \
+    boost_headers \
+    dbus \
+))
 
 ifeq ($(ENABLE_BREAKPAD),TRUE)
 $(eval $(call gb_Library_use_external,sofficeapp,breakpad))
diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx
index c4f50f4..a5d9ac7 100644
--- a/desktop/source/app/officeipcthread.cxx
+++ b/desktop/source/app/officeipcthread.cxx
@@ -17,6 +17,9 @@
  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
  */
 
+#include <sal/config.h>
+
+#include <config_dbus.h>
 #include <config_features.h>
 
 #include "app.hxx"
@@ -44,8 +47,13 @@
 #include <tools/getprocessworkingdir.hxx>
 
 #include <cassert>
+#include <cstdlib>
 #include <memory>
 
+#if ENABLE_DBUS
+#include <dbus/dbus.h>
+#endif
+
 using namespace desktop;
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::lang;
@@ -365,6 +373,8 @@ protected:
 
     virtual ~IpcThread() {}
 
+    bool process(OString const & arguments, bool * wait);
+
     RequestHandler * handler_;
 };
 
@@ -386,6 +396,262 @@ private:
     osl::Pipe pipe_;
 };
 
+#if ENABLE_DBUS
+
+namespace {
+
+struct DbusConnectionHolder {
+    explicit DbusConnectionHolder(DBusConnection * theConnection):
+        connection(theConnection)
+    {}
+
+    ~DbusConnectionHolder() { clear(); }
+
+    void clear() {
+        if (connection != nullptr) {
+            dbus_connection_unref(connection);
+        }
+        connection = nullptr;
+    }
+
+    DBusConnection * connection;
+
+private:
+    DbusConnectionHolder(DbusConnectionHolder &) = delete;
+    void operator =(DbusConnectionHolder) = delete;
+};
+
+struct DbusMessageHolder {
+    explicit DbusMessageHolder(DBusMessage * theMessage): message(theMessage) {}
+
+    ~DbusMessageHolder() { clear(); }
+
+    void clear() {
+        if (message != nullptr) {
+            dbus_message_unref(message);
+        }
+        message = nullptr;
+    }
+
+    DBusMessage * message;
+
+private:
+    DbusMessageHolder(DbusMessageHolder &) = delete;
+    void operator =(DbusMessageHolder) = delete;
+};
+
+}
+
+class DbusIpcThread: public IpcThread {
+public:
+    static RequestHandler::Status enable(rtl::Reference<IpcThread> * thread);
+
+private:
+    explicit DbusIpcThread(DBusConnection * connection):
+        IpcThread("DbusIPC"), connection_(connection)
+    {}
+
+    virtual ~DbusIpcThread() {}
+
+    void execute() override;
+
+    void close() override;
+
+    DbusConnectionHolder connection_;
+};
+
+RequestHandler::Status DbusIpcThread::enable(rtl::Reference<IpcThread> * thread)
+{
+    assert(thread != nullptr);
+    if (!dbus_threads_init_default()) {
+        SAL_WARN("desktop.app", "dbus_threads_init_default failed");
+        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+    }
+    DBusError e;
+    dbus_error_init(&e);
+    DbusConnectionHolder con(dbus_bus_get(DBUS_BUS_SESSION, &e));
+    assert((con.connection == nullptr) == bool(dbus_error_is_set(&e)));
+    if (con.connection == nullptr) {
+        SAL_WARN(
+            "desktop.app",
+            "dbus_bus_get failed with: " << e.name << ": " << e.message);
+        dbus_error_free(&e);
+        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+    }
+    for (;;) {
+        int n = dbus_bus_request_name(
+            con.connection, "org.libreoffice.LibreOfficeIpc0",
+            DBUS_NAME_FLAG_DO_NOT_QUEUE, &e);
+        assert((n == -1) == bool(dbus_error_is_set(&e)));
+        switch (n) {
+        case -1:
+            SAL_WARN(
+                "desktop.app",
+                "dbus_bus_request_name failed with: " << e.name << ": "
+                << e.message);
+            dbus_error_free(&e);
+            return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+        case DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER:
+            *thread = new DbusIpcThread(con.connection);
+            con.connection = nullptr;
+            return RequestHandler::IPC_STATUS_OK;
+        case DBUS_REQUEST_NAME_REPLY_EXISTS:
+            {
+                OStringBuffer buf(ARGUMENT_PREFIX);
+                OUString arg;
+                if (!(tools::getProcessWorkingDir(arg)
+                      && addArgument(buf, '1', arg)))
+                {
+                    buf.append('0');
+                }
+                sal_uInt32 narg = rtl_getAppCommandArgCount();
+                for (sal_uInt32 i = 0; i != narg; ++i) {
+                    rtl_getAppCommandArg(i, &arg.pData);
+                    if (!addArgument(buf, ',', arg)) {
+                        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+                    }
+                }
+                char const * argstr = buf.getStr();
+                DbusMessageHolder msg(
+                    dbus_message_new_method_call(
+                        "org.libreoffice.LibreOfficeIpc0",
+                        "/org/libreoffice/LibreOfficeIpc0",
+                        "org.libreoffice.LibreOfficeIpcIfc0", "Execute"));
+                if (msg.message == nullptr) {
+                    SAL_WARN(
+                        "desktop.app", "dbus_message_new_method_call failed");
+                    return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+                }
+                DBusMessageIter it;
+                dbus_message_iter_init_append(msg.message, &it);
+                if (!dbus_message_iter_append_basic(
+                        &it, DBUS_TYPE_STRING, &argstr))
+                {
+                    SAL_WARN(
+                        "desktop.app", "dbus_message_iter_append_basic failed");
+                    return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+                }
+                DbusMessageHolder repl(
+                    dbus_connection_send_with_reply_and_block(
+                        con.connection, msg.message, DBUS_TIMEOUT_INFINITE,
+                        &e));
+                assert(
+                    (repl.message == nullptr) == bool(dbus_error_is_set(&e)));
+                if (repl.message == nullptr) {
+                    SAL_INFO(
+                        "desktop.app",
+                        "dbus_connection_send_with_reply_and_block failed"
+                            " with: " << e.name << ": " << e.message);
+                    dbus_error_free(&e);
+                    break;
+                }
+                return RequestHandler::IPC_STATUS_2ND_OFFICE;
+            }
+        default:
+            assert(false);
+            // fall through
+        case DBUS_REQUEST_NAME_REPLY_IN_QUEUE:
+        case DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER:
+            SAL_WARN(
+                "desktop.app",
+                "dbus_bus_request_name failed with unexpected " << +n);
+            return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
+        }
+    }
+}
+
+void DbusIpcThread::execute()
+{
+    assert(handler_ != nullptr);
+    handler_->cReady.wait();
+    for (;;) {
+        {
+            osl::MutexGuard g(RequestHandler::GetMutex());
+            if (handler_->mState == RequestHandler::State::Downing) {
+                break;
+            }
+        }
+        dbus_connection_read_write(connection_.connection, 0);
+        DbusMessageHolder msg(
+            dbus_connection_pop_message(connection_.connection));
+        if (msg.message == nullptr) {
+            continue;
+        }
+        if (!dbus_message_is_method_call(
+                msg.message, "org.libreoffice.LibreOfficeIpcIfc0", "Execute"))
+        {
+            SAL_INFO("desktop.app", "unknown DBus message ignored");
+            continue;
+        }
+        DBusMessageIter it;
+        if (!dbus_message_iter_init(msg.message, &it)) {
+            SAL_WARN("desktop.app", "DBus message without argument ignored");
+            continue;
+        }
+        if (dbus_message_iter_get_arg_type(&it) != DBUS_TYPE_STRING) {
+            SAL_WARN(
+                "desktop.app", "DBus message with non-string argument ignored");
+            continue;
+        }
+        char const * argstr;
+        dbus_message_iter_get_basic(&it, &argstr);
+        bool wait = false;
+        {
+            osl::MutexGuard g(RequestHandler::GetMutex());
+            if (!process(argstr, &wait)) {
+                continue;
+            }
+        }
+        if (wait) {
+            handler_->cProcessed.wait();
+        }
+        DbusMessageHolder repl(dbus_message_new_method_return(msg.message));
+        if (repl.message == nullptr) {
+            SAL_WARN("desktop.app", "dbus_message_new_method_return failed");
+            continue;
+        }
+        dbus_uint32_t serial = 0;
+        if (!dbus_connection_send(
+                connection_.connection, repl.message, &serial)) {
+            SAL_WARN("desktop.app", "dbus_connection_send failed");
+            continue;
+        }
+        dbus_connection_flush(connection_.connection);
+    }
+}
+
+void DbusIpcThread::close() {
+    assert(connection_.connection != nullptr);
+    DBusError e;
+    dbus_error_init(&e);
+    int n = dbus_bus_release_name(
+        connection_.connection, "org.libreoffice.LibreOfficeIpc0", &e);
+    assert((n == -1) == bool(dbus_error_is_set(&e)));
+    switch (n) {
+    case -1:
+        SAL_WARN(
+            "desktop.app",
+            "dbus_bus_release_name failed with: " << e.name << ": "
+                << e.message);
+        dbus_error_free(&e);
+        break;
+    case DBUS_RELEASE_NAME_REPLY_RELEASED:
+        break;
+    default:
+        assert(false);
+        // fall through
+    case DBUS_RELEASE_NAME_REPLY_NOT_OWNER:
+    case DBUS_RELEASE_NAME_REPLY_NON_EXISTENT:
+        SAL_WARN(
+            "desktop.app",
+            "dbus_bus_release_name failed with unexpected " << +n);
+        break;
+    }
+    connection_.clear();
+}
+
+#endif
+
 namespace
 {
     class theRequestHandlerMutex
@@ -462,8 +728,27 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
         return IPC_STATUS_OK;
     }
 
+    enum class Kind { Pipe, Dbus };
+    Kind kind = Kind::Pipe;
+#if ENABLE_DBUS
+    if (std::getenv("LIBO_XDGAPP") != nullptr) {
+        kind = Kind::Dbus;
+    }
+#endif
     rtl::Reference<IpcThread> thread;
-    Status stat = PipeIpcThread::enable(&thread);
+    Status stat;
+    switch (kind) {
+    case Kind::Pipe:
+        stat = PipeIpcThread::enable(&thread);
+        break;
+    case Kind::Dbus:
+#if ENABLE_DBUS
+        stat = DbusIpcThread::enable(&thread);
+        break;
+#endif
+    default:
+        assert(false);
+    }
     assert(thread.is() == (stat == IPC_STATUS_OK));
     if (stat == IPC_STATUS_OK) {
         pGlobal = new RequestHandler;
@@ -656,6 +941,209 @@ void RequestHandler::WaitForReady()
     }
 }
 
+bool IpcThread::process(OString const & arguments, bool * wait) {
+    assert(wait != nullptr);
+
+    std::unique_ptr< CommandLineArgs > aCmdLineArgs;
+    try
+    {
+        Parser p(arguments);
+        aCmdLineArgs.reset( new CommandLineArgs( p ) );
+    }
+    catch ( const CommandLineArgs::Supplier::Exception & )
+    {
+        SAL_WARN("desktop.app", "Error in received command line arguments");
+        return false;
+    }
+
+    bool bDocRequestSent = false;
+
+    OUString aUnknown( aCmdLineArgs->GetUnknown() );
+    if ( !aUnknown.isEmpty() || aCmdLineArgs->IsHelp() )
+    {
+        ApplicationEvent* pAppEvent =
+            new ApplicationEvent(ApplicationEvent::TYPE_HELP, aUnknown);
+        ImplPostForeignAppEvent( pAppEvent );
+    }
+    else if ( aCmdLineArgs->IsVersion() )
+    {
+        ApplicationEvent* pAppEvent =
+            new ApplicationEvent(ApplicationEvent::TYPE_VERSION);
+        ImplPostForeignAppEvent( pAppEvent );
+    }
+    else
+    {
+        const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs();
+
+        if ( aCmdLineArgs->IsQuickstart() )
+        {
+            // we have to use application event, because we have to start quickstart service in main thread!!
+            ApplicationEvent* pAppEvent =
+                new ApplicationEvent(ApplicationEvent::TYPE_QUICKSTART);
+            ImplPostForeignAppEvent( pAppEvent );
+        }
+
+        // handle request for acceptor
+        std::vector< OUString > const & accept = aCmdLineArgs->GetAccept();
+        for (std::vector< OUString >::const_iterator i(accept.begin());
+             i != accept.end(); ++i)
+        {
+            ApplicationEvent* pAppEvent = new ApplicationEvent(
+                ApplicationEvent::TYPE_ACCEPT, *i);
+            ImplPostForeignAppEvent( pAppEvent );
+        }
+        // handle acceptor removal
+        std::vector< OUString > const & unaccept = aCmdLineArgs->GetUnaccept();
+        for (std::vector< OUString >::const_iterator i(unaccept.begin());
+             i != unaccept.end(); ++i)
+        {
+            ApplicationEvent* pAppEvent = new ApplicationEvent(
+                ApplicationEvent::TYPE_UNACCEPT, *i);
+            ImplPostForeignAppEvent( pAppEvent );
+        }
+
+        ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
+            aCmdLineArgs->getCwdUrl());
+        handler_->cProcessed.reset();
+        pRequest->pcProcessed = &handler_->cProcessed;
+
+        // Print requests are not dependent on the --invisible cmdline argument as they are
+        // loaded with the "hidden" flag! So they are always checked.
+        pRequest->aPrintList = aCmdLineArgs->GetPrintList();
+        bDocRequestSent |= !pRequest->aPrintList.empty();
+        pRequest->aPrintToList = aCmdLineArgs->GetPrintToList();
+        pRequest->aPrinterName = aCmdLineArgs->GetPrinterName();
+        bDocRequestSent |= !( pRequest->aPrintToList.empty() || pRequest->aPrinterName.isEmpty() );
+
+        if ( !rCurrentCmdLineArgs.IsInvisible() )
+        {
+            // Read cmdline args that can open/create documents. As they would open a window
+            // they are only allowed if the "--invisible" is currently not used!
+            pRequest->aOpenList = aCmdLineArgs->GetOpenList();
+            bDocRequestSent |= !pRequest->aOpenList.empty();
+            pRequest->aViewList = aCmdLineArgs->GetViewList();
+            bDocRequestSent |= !pRequest->aViewList.empty();
+            pRequest->aStartList = aCmdLineArgs->GetStartList();
+            bDocRequestSent |= !pRequest->aStartList.empty();
+            pRequest->aForceOpenList = aCmdLineArgs->GetForceOpenList();
+            bDocRequestSent |= !pRequest->aForceOpenList.empty();
+            pRequest->aForceNewList = aCmdLineArgs->GetForceNewList();
+            bDocRequestSent |= !pRequest->aForceNewList.empty();
+
+            // Special command line args to create an empty document for a given module
+
+            // #i18338# (lo)
+            // we only do this if no document was specified on the command line,
+            // since this would be inconsistent with the behaviour of
+            // the first process, see OpenClients() (call to OpenDefault()) in app.cxx
+            if ( aCmdLineArgs->HasModuleParam() && !bDocRequestSent )
+            {
+                SvtModuleOptions aOpt;
+                SvtModuleOptions::EFactory eFactory = SvtModuleOptions::EFactory::WRITER;
+                if ( aCmdLineArgs->IsWriter() )
+                    eFactory = SvtModuleOptions::EFactory::WRITER;
+                else if ( aCmdLineArgs->IsCalc() )
+                    eFactory = SvtModuleOptions::EFactory::CALC;
+                else if ( aCmdLineArgs->IsDraw() )
+                    eFactory = SvtModuleOptions::EFactory::DRAW;
+                else if ( aCmdLineArgs->IsImpress() )
+                    eFactory = SvtModuleOptions::EFactory::IMPRESS;
+                else if ( aCmdLineArgs->IsBase() )
+                    eFactory = SvtModuleOptions::EFactory::DATABASE;
+                else if ( aCmdLineArgs->IsMath() )
+                    eFactory = SvtModuleOptions::EFactory::MATH;
+                else if ( aCmdLineArgs->IsGlobal() )
+                    eFactory = SvtModuleOptions::EFactory::WRITERGLOBAL;
+                else if ( aCmdLineArgs->IsWeb() )
+                    eFactory = SvtModuleOptions::EFactory::WRITERWEB;
+
+                if ( !pRequest->aOpenList.empty() )
+                    pRequest->aModule = aOpt.GetFactoryName( eFactory );
+                else
+                    pRequest->aOpenList.push_back( aOpt.GetFactoryEmptyDocumentURL( eFactory ) );
+                bDocRequestSent = true;
+            }
+        }
+
+        if ( !aCmdLineArgs->IsQuickstart() ) {
+            bool bShowHelp = false;
+            OUStringBuffer aHelpURLBuffer;
+            if (aCmdLineArgs->IsHelpWriter()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://swriter/start");
+            } else if (aCmdLineArgs->IsHelpCalc()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://scalc/start");
+            } else if (aCmdLineArgs->IsHelpDraw()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://sdraw/start");
+            } else if (aCmdLineArgs->IsHelpImpress()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://simpress/start");
+            } else if (aCmdLineArgs->IsHelpBase()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://sdatabase/start");
+            } else if (aCmdLineArgs->IsHelpBasic()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://sbasic/start");
+            } else if (aCmdLineArgs->IsHelpMath()) {
+                bShowHelp = true;
+                aHelpURLBuffer.append("vnd.sun.star.help://smath/start");
+            }
+            if (bShowHelp) {
+                aHelpURLBuffer.append("?Language=");
+                aHelpURLBuffer.append(utl::ConfigManager::getLocale());
+#if defined UNX
+                aHelpURLBuffer.append("&System=UNX");
+#elif defined WNT
+                aHelpURLBuffer.appendAscii("&System=WIN");
+#endif
+                ApplicationEvent* pAppEvent = new ApplicationEvent(
+                    ApplicationEvent::TYPE_OPENHELPURL,
+                    aHelpURLBuffer.makeStringAndClear());
+                ImplPostForeignAppEvent( pAppEvent );
+            }
+        }
+
+        if ( bDocRequestSent )
+        {
+            // Send requests to dispatch watcher if we have at least one. The receiver
+            // is responsible to delete the request after processing it.
+            if ( aCmdLineArgs->HasModuleParam() )
+            {
+                SvtModuleOptions    aOpt;
+
+                // Support command line parameters to start a module (as preselection)
+                if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
+                    pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::WRITER );
+                else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
+                    pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::CALC );
+                else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
+                    pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::IMPRESS );
+                else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
+                    pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::DRAW );
+            }
+
+            ImplPostProcessDocumentsEvent( pRequest );
+        }
+        else
+        {
+            // delete not used request again
+            delete pRequest;
+            pRequest = nullptr;
+        }
+        if (aCmdLineArgs->IsEmpty())
+        {
+            // no document was sent, just bring Office to front
+            ApplicationEvent* pAppEvent =
+                new ApplicationEvent(ApplicationEvent::TYPE_APPEAR);
+            ImplPostForeignAppEvent( pAppEvent );
+        }
+    }
+    *wait = bDocRequestSent;
+    return true;
+}
+
 void PipeIpcThread::execute()
 {
     assert(handler_ != nullptr);
@@ -700,210 +1188,15 @@ void PipeIpcThread::execute()
             if (aArguments.isEmpty())
                 continue;
 
-            std::unique_ptr< CommandLineArgs > aCmdLineArgs;
-            try
-            {
-                Parser p(aArguments);
-                aCmdLineArgs.reset( new CommandLineArgs( p ) );
-            }
-            catch ( const CommandLineArgs::Supplier::Exception & )
-            {
-                SAL_WARN("desktop.app", "Error in received command line arguments");
+            bool wait = false;
+            if (!process(aArguments, &wait)) {
                 continue;
             }
 
-            bool bDocRequestSent = false;
-
-            OUString aUnknown( aCmdLineArgs->GetUnknown() );
-            if ( !aUnknown.isEmpty() || aCmdLineArgs->IsHelp() )
-            {
-                ApplicationEvent* pAppEvent =
-                    new ApplicationEvent(ApplicationEvent::TYPE_HELP, aUnknown);
-                ImplPostForeignAppEvent( pAppEvent );
-            }
-            else if ( aCmdLineArgs->IsVersion() )
-            {
-                ApplicationEvent* pAppEvent =
-                    new ApplicationEvent(ApplicationEvent::TYPE_VERSION);
-                ImplPostForeignAppEvent( pAppEvent );
-            }
-            else
-            {
-                const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs();
-
-                if ( aCmdLineArgs->IsQuickstart() )
-                {
-                    // we have to use application event, because we have to start quickstart service in main thread!!
-                    ApplicationEvent* pAppEvent =
-                        new ApplicationEvent(ApplicationEvent::TYPE_QUICKSTART);
-                    ImplPostForeignAppEvent( pAppEvent );
-                }
-
-                // handle request for acceptor
-                std::vector< OUString > const & accept = aCmdLineArgs->
-                    GetAccept();
-                for (std::vector< OUString >::const_iterator i(accept.begin());
-                     i != accept.end(); ++i)
-                {
-                    ApplicationEvent* pAppEvent = new ApplicationEvent(
-                        ApplicationEvent::TYPE_ACCEPT, *i);
-                    ImplPostForeignAppEvent( pAppEvent );
-                }
-                // handle acceptor removal
-                std::vector< OUString > const & unaccept = aCmdLineArgs->
-                    GetUnaccept();
-                for (std::vector< OUString >::const_iterator i(
-                         unaccept.begin());
-                     i != unaccept.end(); ++i)
-                {
-                    ApplicationEvent* pAppEvent = new ApplicationEvent(
-                        ApplicationEvent::TYPE_UNACCEPT, *i);
-                    ImplPostForeignAppEvent( pAppEvent );
-                }
-
-                ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
-                    aCmdLineArgs->getCwdUrl());
-                handler_->cProcessed.reset();
-                pRequest->pcProcessed = &handler_->cProcessed;
-
-                // Print requests are not dependent on the --invisible cmdline argument as they are
-                // loaded with the "hidden" flag! So they are always checked.
-                pRequest->aPrintList = aCmdLineArgs->GetPrintList();
-                bDocRequestSent |= !pRequest->aPrintList.empty();
-                pRequest->aPrintToList = aCmdLineArgs->GetPrintToList();
-                pRequest->aPrinterName = aCmdLineArgs->GetPrinterName();
-                bDocRequestSent |= !( pRequest->aPrintToList.empty() || pRequest->aPrinterName.isEmpty() );
-
-                if ( !rCurrentCmdLineArgs.IsInvisible() )
-                {
-                    // Read cmdline args that can open/create documents. As they would open a window
-                    // they are only allowed if the "--invisible" is currently not used!
-                    pRequest->aOpenList = aCmdLineArgs->GetOpenList();
-                    bDocRequestSent |= !pRequest->aOpenList.empty();
-                    pRequest->aViewList = aCmdLineArgs->GetViewList();
-                    bDocRequestSent |= !pRequest->aViewList.empty();
-                    pRequest->aStartList = aCmdLineArgs->GetStartList();
-                    bDocRequestSent |= !pRequest->aStartList.empty();
-                    pRequest->aForceOpenList = aCmdLineArgs->GetForceOpenList();
-                    bDocRequestSent |= !pRequest->aForceOpenList.empty();
-                    pRequest->aForceNewList = aCmdLineArgs->GetForceNewList();
-                    bDocRequestSent |= !pRequest->aForceNewList.empty();
-
-                    // Special command line args to create an empty document for a given module
-
-                    // #i18338# (lo)
-                    // we only do this if no document was specified on the command line,
-                    // since this would be inconsistent with the behaviour of
-                    // the first process, see OpenClients() (call to OpenDefault()) in app.cxx
-                    if ( aCmdLineArgs->HasModuleParam() && !bDocRequestSent )
-                    {
-                        SvtModuleOptions aOpt;
-                        SvtModuleOptions::EFactory eFactory = SvtModuleOptions::EFactory::WRITER;
-                        if ( aCmdLineArgs->IsWriter() )
-                            eFactory = SvtModuleOptions::EFactory::WRITER;
-                        else if ( aCmdLineArgs->IsCalc() )
-                            eFactory = SvtModuleOptions::EFactory::CALC;
-                        else if ( aCmdLineArgs->IsDraw() )
-                            eFactory = SvtModuleOptions::EFactory::DRAW;
-                        else if ( aCmdLineArgs->IsImpress() )
-                            eFactory = SvtModuleOptions::EFactory::IMPRESS;
-                        else if ( aCmdLineArgs->IsBase() )
-                            eFactory = SvtModuleOptions::EFactory::DATABASE;
-                        else if ( aCmdLineArgs->IsMath() )
-                            eFactory = SvtModuleOptions::EFactory::MATH;
-                        else if ( aCmdLineArgs->IsGlobal() )
-                            eFactory = SvtModuleOptions::EFactory::WRITERGLOBAL;
-                        else if ( aCmdLineArgs->IsWeb() )
-                            eFactory = SvtModuleOptions::EFactory::WRITERWEB;
-
-                        if ( !pRequest->aOpenList.empty() )
-                            pRequest->aModule = aOpt.GetFactoryName( eFactory );
-                        else
-                            pRequest->aOpenList.push_back( aOpt.GetFactoryEmptyDocumentURL( eFactory ) );
-                        bDocRequestSent = true;
-                    }
-                }
-
-                if ( !aCmdLineArgs->IsQuickstart() ) {
-                    bool bShowHelp = false;
-                    OUStringBuffer aHelpURLBuffer;
-                    if (aCmdLineArgs->IsHelpWriter()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://swriter/start");
-                    } else if (aCmdLineArgs->IsHelpCalc()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://scalc/start");
-                    } else if (aCmdLineArgs->IsHelpDraw()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://sdraw/start");
-                    } else if (aCmdLineArgs->IsHelpImpress()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://simpress/start");
-                    } else if (aCmdLineArgs->IsHelpBase()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://sdatabase/start");
-                    } else if (aCmdLineArgs->IsHelpBasic()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://sbasic/start");
-                    } else if (aCmdLineArgs->IsHelpMath()) {
-                        bShowHelp = true;
-                        aHelpURLBuffer.append("vnd.sun.star.help://smath/start");
-                    }
-                    if (bShowHelp) {
-                        aHelpURLBuffer.append("?Language=");
-                        aHelpURLBuffer.append(utl::ConfigManager::getLocale());
-#if defined UNX
-                        aHelpURLBuffer.append("&System=UNX");
-#elif defined WNT
-                        aHelpURLBuffer.appendAscii("&System=WIN");
-#endif
-                        ApplicationEvent* pAppEvent = new ApplicationEvent(
-                            ApplicationEvent::TYPE_OPENHELPURL,
-                            aHelpURLBuffer.makeStringAndClear());
-                        ImplPostForeignAppEvent( pAppEvent );
-                    }
-                }
-
-                if ( bDocRequestSent )
-                {
-                    // Send requests to dispatch watcher if we have at least one. The receiver
-                    // is responsible to delete the request after processing it.
-                    if ( aCmdLineArgs->HasModuleParam() )
-                    {
-                        SvtModuleOptions    aOpt;
-
-                        // Support command line parameters to start a module (as preselection)
-                        if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
-                            pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::WRITER );
-                        else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
-                            pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::CALC );
-                        else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
-                            pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::IMPRESS );
-                        else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
-                            pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::DRAW );
-                    }
-
-                    ImplPostProcessDocumentsEvent( pRequest );
-                }
-                else
-                {
-                    // delete not used request again
-                    delete pRequest;
-                    pRequest = nullptr;
-                }
-                if (aCmdLineArgs->IsEmpty())
-                {
-                    // no document was sent, just bring Office to front
-                    ApplicationEvent* pAppEvent =
-                        new ApplicationEvent(ApplicationEvent::TYPE_APPEAR);
-                    ImplPostForeignAppEvent( pAppEvent );
-                }
-            }
-
             // we don't need the mutex any longer...
             aGuard.clear();
             // wait for processing to finish
-            if (bDocRequestSent)
+            if (wait)
                 handler_->cProcessed.wait();
             // processing finished, inform the requesting end:
             n = aStreamPipe.write(
diff --git a/desktop/source/app/officeipcthread.hxx b/desktop/source/app/officeipcthread.hxx
index 55e5fc3..1d3b2cc 100644
--- a/desktop/source/app/officeipcthread.hxx
+++ b/desktop/source/app/officeipcthread.hxx
@@ -69,10 +69,13 @@ struct ProcessDocumentsRequest
 class DispatchWatcher;
 class IpcThread;
 class PipeIpcThread;
+class DbusIpcThread;
 
 class RequestHandler: public salhelper::SimpleReferenceObject
 {
+    friend IpcThread;
     friend PipeIpcThread;
+    friend DbusIpcThread;
 
   private:
     static rtl::Reference< RequestHandler > pGlobal;
diff --git a/desktop/unx/source/start.c b/desktop/unx/source/start.c
index a988fc8..3b23124 100644
--- a/desktop/unx/source/start.c
+++ b/desktop/unx/source/start.c
@@ -757,7 +757,7 @@ SAL_IMPLEMENT_MAIN_WITH_ARGS( argc, argv )
     if ( pUsePlugin && !strcmp(pUsePlugin, "svp") )
         args->bInhibitSplash = sal_True;
 
-    if ( !args->bInhibitPipe )
+    if ( !args->bInhibitPipe && getenv("LIBO_XDGAPP") == NULL )
     {
         int fd = 0;
         pPipePath = get_pipe_path( args->pAppPath );
commit ec655c8e8f6ff476fb70135927ce38d1b1000982
Author: Stephan Bergmann <sbergman at redhat.com>
Date:   Fri Apr 1 14:22:44 2016 +0200

    Prepare for using other IPC mechanisms besides an osl::Pipe
    
    Change-Id: Ie34330508563bef25185216bdc1dc3ae84d084d4

diff --git a/desktop/source/app/officeipcthread.cxx b/desktop/source/app/officeipcthread.cxx
index 891f021..c4f50f4 100644
--- a/desktop/source/app/officeipcthread.cxx
+++ b/desktop/source/app/officeipcthread.cxx
@@ -42,6 +42,8 @@
 #include <osl/file.hxx>
 #include <rtl/process.h>
 #include <tools/getprocessworkingdir.hxx>
+
+#include <cassert>
 #include <memory>
 
 using namespace desktop;
@@ -81,14 +83,6 @@ OString readStringFromPipe(osl::StreamPipe & pipe) {
 
 }
 
-// Type of pipe we use
-enum PipeMode
-{
-    PIPEMODE_DONTKNOW,
-    PIPEMODE_CREATED,
-    PIPEMODE_CONNECTED
-};
-
 namespace desktop
 {
 
@@ -357,20 +351,38 @@ throw( RuntimeException, std::exception )
 {
 }
 
-class PipeReaderThread: public salhelper::Thread {
+class IpcThread: public salhelper::Thread {
 public:
-    PipeReaderThread(RequestHandler & handler, osl::Pipe const & pipe):
-        Thread("PipeReader"), handler_(handler), pipe_(pipe)
-    {}
+    void start(RequestHandler * handler) {
+        handler_ = handler;
+        launch();
+    }
 
-    void close() { pipe_.close(); }
+    virtual void close() = 0;
+
+protected:
+    explicit IpcThread(char const * name): Thread(name), handler_(nullptr) {}
+
+    virtual ~IpcThread() {}
+
+    RequestHandler * handler_;
+};
+
+class PipeIpcThread: public IpcThread {
+public:
+    static RequestHandler::Status enable(rtl::Reference<IpcThread> * thread);
 
 private:
-    virtual ~PipeReaderThread() {}
+    explicit PipeIpcThread(osl::Pipe const & pipe):
+        IpcThread("PipeIPC"), pipe_(pipe)
+    {}
+
+    virtual ~PipeIpcThread() {}
 
     void execute() override;
 
-    RequestHandler & handler_;
+    void close() override { pipe_.close(); }
+
     osl::Pipe pipe_;
 };
 
@@ -450,6 +462,21 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
         return IPC_STATUS_OK;
     }
 
+    rtl::Reference<IpcThread> thread;
+    Status stat = PipeIpcThread::enable(&thread);
+    assert(thread.is() == (stat == IPC_STATUS_OK));
+    if (stat == IPC_STATUS_OK) {
+        pGlobal = new RequestHandler;
+        pGlobal->mIpcThread = thread;
+        pGlobal->mIpcThread->start(pGlobal.get());
+    }
+    return stat;
+}
+
+RequestHandler::Status PipeIpcThread::enable(rtl::Reference<IpcThread> * thread)
+{
+    assert(thread != nullptr);
+
     // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve
     // this information from a unotools implementation.
     OUString aUserInstallPath;
@@ -457,7 +484,7 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
     if (aLocateResult != utl::Bootstrap::PATH_EXISTS
         && aLocateResult != utl::Bootstrap::PATH_VALID)
     {
-        return IPC_STATUS_BOOTSTRAP_ERROR;
+        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
     }
 
     // Try to  determine if we are the first office or not! This should prevent multiple
@@ -469,9 +496,15 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
 
     // Check result to create a hash code from the user install path
     if ( aUserInstallPathHashCode.isEmpty() )
-        return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code!
+        return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code!
 
     osl::Pipe pipe;
+    enum PipeMode
+    {
+        PIPEMODE_DONTKNOW,
+        PIPEMODE_CREATED,
+        PIPEMODE_CONNECTED
+    };
     PipeMode nPipeMode = PIPEMODE_DONTKNOW;
 
     OUString aPipeIdent( "SingleOfficeIPC_" + aUserInstallPathHashCode );
@@ -506,7 +539,7 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
         {
             oslPipeError eReason = pipe.getError();
             if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_E_invalidError))
-                return IPC_STATUS_PIPE_ERROR;
+                return RequestHandler::IPC_STATUS_PIPE_ERROR;
 
             // Wait for second office to be ready
             TimeValue aTimeValue;
@@ -519,11 +552,9 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
 
     if ( nPipeMode == PIPEMODE_CREATED )
     {
-        // Seems we are the one and only, so start listening thread
-        pGlobal = new RequestHandler;
-        pGlobal->mPipeReaderThread = new PipeReaderThread(*pGlobal, pipe);
-        pGlobal->mPipeReaderThread->launch();
-        return IPC_STATUS_OK;
+        // Seems we are the one and only, so create listening thread
+        *thread = new PipeIpcThread(pipe);
+        return RequestHandler::IPC_STATUS_OK;
     }
     else
     {
@@ -542,7 +573,7 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
         {
             rtl_getAppCommandArg( i, &aUserInstallPath.pData );
             if (!addArgument(aArguments, ',', aUserInstallPath)) {
-                return IPC_STATUS_BOOTSTRAP_ERROR;
+                return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
             }
         }
         aArguments.append('\0');
@@ -551,16 +582,16 @@ RequestHandler::Status RequestHandler::Enable(bool ipc)
             aArguments.getStr(), aArguments.getLength());
         if (n != aArguments.getLength()) {
             SAL_INFO("desktop", "short write: " << n);
-            return IPC_STATUS_BOOTSTRAP_ERROR;
+            return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
         }
 
         if (readStringFromPipe(aStreamPipe) != PROCESSING_DONE)
         {
             // something went wrong
-            return IPC_STATUS_BOOTSTRAP_ERROR;
+            return RequestHandler::IPC_STATUS_BOOTSTRAP_ERROR;
         }
 
-        return IPC_STATUS_2ND_OFFICE;
+        return RequestHandler::IPC_STATUS_2ND_OFFICE;
     }
 }
 
@@ -574,8 +605,8 @@ void RequestHandler::Disable(bool join)
         pGlobal.clear();
 
         handler->mState = State::Downing;
-        if (handler->mPipeReaderThread.is()) {
-            handler->mPipeReaderThread->close();
+        if (handler->mIpcThread.is()) {
+            handler->mIpcThread->close();
         }
 
         // release mutex to avoid deadlocks
@@ -584,10 +615,10 @@ void RequestHandler::Disable(bool join)
         handler->cReady.set();
 
         // exit gracefully and join
-        if (join && handler->mPipeReaderThread.is())
+        if (join && handler->mIpcThread.is())
         {
-            handler->mPipeReaderThread->join();
-            handler->mPipeReaderThread.clear();
+            handler->mIpcThread->join();
+            handler->mIpcThread.clear();
         }
     }
 }
@@ -600,7 +631,7 @@ RequestHandler::RequestHandler() :
 
 RequestHandler::~RequestHandler()
 {
-    assert(!mPipeReaderThread.is());
+    assert(!mIpcThread.is());
 }
 
 void RequestHandler::SetReady()
@@ -625,8 +656,9 @@ void RequestHandler::WaitForReady()
     }
 }
 
-void PipeReaderThread::execute()
+void PipeIpcThread::execute()
 {
+    assert(handler_ != nullptr);
     do
     {
         osl::StreamPipe aStreamPipe;
@@ -639,16 +671,16 @@ void PipeReaderThread::execute()
             // bootstrap, that dialogs event loop might get events that are dispatched by this thread
             // we have to wait for cReady to be set by the real main loop.
             // only requests that don't dispatch events may be processed before cReady is set.
-            handler_.cReady.wait();
+            handler_->cReady.wait();
 
             // we might have decided to shutdown while we were sleeping
-            if (!handler_.pGlobal.is()) return;
+            if (!handler_->pGlobal.is()) return;
 
             // only lock the mutex when processing starts, othewise we deadlock when the office goes
             // down during wait
             osl::ClearableMutexGuard aGuard( RequestHandler::GetMutex() );
 
-            if ( handler_.mState == RequestHandler::State::Downing )
+            if ( handler_->mState == RequestHandler::State::Downing )
             {
                 break;
             }
@@ -731,8 +763,8 @@ void PipeReaderThread::execute()
 
                 ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
                     aCmdLineArgs->getCwdUrl());
-                handler_.cProcessed.reset();
-                pRequest->pcProcessed = &handler_.cProcessed;
+                handler_->cProcessed.reset();
+                pRequest->pcProcessed = &handler_->cProcessed;
 
                 // Print requests are not dependent on the --invisible cmdline argument as they are
                 // loaded with the "hidden" flag! So they are always checked.
@@ -872,7 +904,7 @@ void PipeReaderThread::execute()
             aGuard.clear();
             // wait for processing to finish
             if (bDocRequestSent)
-                handler_.cProcessed.wait();
+                handler_->cProcessed.wait();
             // processing finished, inform the requesting end:
             n = aStreamPipe.write(
                 PROCESSING_DONE, SAL_N_ELEMENTS(PROCESSING_DONE));
@@ -886,7 +918,7 @@ void PipeReaderThread::execute()
         {
             {
                 osl::MutexGuard aGuard( RequestHandler::GetMutex() );
-                if ( handler_.mState == RequestHandler::State::Downing )
+                if ( handler_->mState == RequestHandler::State::Downing )
                 {
                     break;
                 }
diff --git a/desktop/source/app/officeipcthread.hxx b/desktop/source/app/officeipcthread.hxx
index 7b154d5..55e5fc3 100644
--- a/desktop/source/app/officeipcthread.hxx
+++ b/desktop/source/app/officeipcthread.hxx
@@ -67,11 +67,12 @@ struct ProcessDocumentsRequest
 };
 
 class DispatchWatcher;
-class PipeReaderThread;
+class IpcThread;
+class PipeIpcThread;
 
 class RequestHandler: public salhelper::SimpleReferenceObject
 {
-    friend PipeReaderThread;
+    friend PipeIpcThread;
 
   private:
     static rtl::Reference< RequestHandler > pGlobal;
@@ -81,7 +82,7 @@ class RequestHandler: public salhelper::SimpleReferenceObject
     State                       mState;
     int                         mnPendingRequests;
     rtl::Reference<DispatchWatcher> mpDispatchWatcher;
-    rtl::Reference<PipeReaderThread> mPipeReaderThread;
+    rtl::Reference<IpcThread> mIpcThread;
 
     /* condition to be set when the request has been processed */
     ::osl::Condition cProcessed;


More information about the Libreoffice-commits mailing list