LCOV - code coverage report
Current view: top level - desktop/source/app - officeipcthread.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 183 485 37.7 %
Date: 2015-06-13 12:38:46 Functions: 23 41 56.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <config_features.h>
      21             : #include <config_version.h>
      22             : 
      23             : #include "app.hxx"
      24             : #include "officeipcthread.hxx"
      25             : #include "cmdlineargs.hxx"
      26             : #include "dispatchwatcher.hxx"
      27             : #include <boost/scoped_ptr.hpp>
      28             : #include <stdio.h>
      29             : #include <osl/process.h>
      30             : #include <sal/log.hxx>
      31             : #include <unotools/bootstrap.hxx>
      32             : #include <vcl/svapp.hxx>
      33             : #include <vcl/help.hxx>
      34             : #include <unotools/configmgr.hxx>
      35             : #include <osl/thread.hxx>
      36             : #include <rtl/digest.h>
      37             : #include <rtl/ustrbuf.hxx>
      38             : #include <rtl/instance.hxx>
      39             : #include <osl/conditn.hxx>
      40             : #include <unotools/moduleoptions.hxx>
      41             : #include <rtl/bootstrap.hxx>
      42             : #include <rtl/strbuf.hxx>
      43             : #include <comphelper/lok.hxx>
      44             : #include <comphelper/processfactory.hxx>
      45             : #include <cppuhelper/supportsservice.hxx>
      46             : #include <osl/file.hxx>
      47             : #include <rtl/process.h>
      48             : #include <tools/getprocessworkingdir.hxx>
      49             : #include <boost/scoped_array.hpp>
      50             : 
      51             : using namespace desktop;
      52             : using namespace ::com::sun::star::uno;
      53             : using namespace ::com::sun::star::lang;
      54             : using namespace ::com::sun::star::frame;
      55             : 
      56             : namespace {
      57             : 
      58             : #if HAVE_FEATURE_DESKTOP || defined(ANDROID)
      59             : 
      60             : static char const ARGUMENT_PREFIX[] = "InternalIPC::Arguments";
      61             : static char const SEND_ARGUMENTS[] = "InternalIPC::SendArguments";
      62             : static char const PROCESSING_DONE[] = "InternalIPC::ProcessingDone";
      63             : 
      64             : // Receives packets from the pipe until a packet ends in a NUL character (that
      65             : // will not be included in the returned string) or it cannot read anything (due
      66             : // to error or closed pipe, in which case an empty string will be returned to
      67             : // signal failure):
      68           0 : OString readStringFromPipe(osl::StreamPipe & pipe) {
      69           0 :     for (OStringBuffer str;;) {
      70             :         char buf[1024];
      71           0 :         sal_Int32 n = pipe.recv(buf, SAL_N_ELEMENTS(buf));
      72           0 :         if (n <= 0) {
      73           0 :             return "";
      74             :         }
      75           0 :         bool end = false;
      76           0 :         if (buf[n - 1] == '\0') {
      77           0 :             end = true;
      78           0 :             --n;
      79             :         }
      80           0 :         str.append(buf, n);
      81             :             //TODO: how does OStringBuffer.append handle overflow?
      82           0 :         if (end) {
      83           0 :             return str.makeStringAndClear();
      84             :         }
      85           0 :     }
      86             : }
      87             : 
      88             : #endif
      89             : 
      90             : }
      91             : 
      92             : // Type of pipe we use
      93             : enum PipeMode
      94             : {
      95             :     PIPEMODE_DONTKNOW,
      96             :     PIPEMODE_CREATED,
      97             :     PIPEMODE_CONNECTED
      98             : };
      99             : 
     100             : namespace desktop
     101             : {
     102             : 
     103             : namespace {
     104             : 
     105             : #if HAVE_FEATURE_DESKTOP || defined(ANDROID)
     106             : 
     107             : class Parser: public CommandLineArgs::Supplier {
     108             : public:
     109           0 :     explicit Parser(OString const & input): m_input(input) {
     110           0 :         if (!m_input.match(ARGUMENT_PREFIX) ||
     111           0 :             m_input.getLength() == RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX))
     112             :         {
     113           0 :             throw CommandLineArgs::Supplier::Exception();
     114             :         }
     115           0 :         m_index = RTL_CONSTASCII_LENGTH(ARGUMENT_PREFIX);
     116           0 :         switch (m_input[m_index++]) {
     117             :         case '0':
     118           0 :             break;
     119             :         case '1':
     120             :             {
     121           0 :                 OUString url;
     122           0 :                 if (!next(&url, false)) {
     123           0 :                     throw CommandLineArgs::Supplier::Exception();
     124             :                 }
     125           0 :                 m_cwdUrl.reset(url);
     126           0 :                 break;
     127             :             }
     128             :         case '2':
     129             :             {
     130           0 :                 OUString path;
     131           0 :                 if (!next(&path, false)) {
     132           0 :                     throw CommandLineArgs::Supplier::Exception();
     133             :                 }
     134           0 :                 OUString url;
     135           0 :                 if (osl::FileBase::getFileURLFromSystemPath(path, url) ==
     136             :                     osl::FileBase::E_None)
     137             :                 {
     138           0 :                     m_cwdUrl.reset(url);
     139             :                 }
     140           0 :                 break;
     141             :             }
     142             :         default:
     143           0 :             throw CommandLineArgs::Supplier::Exception();
     144             :         }
     145           0 :     }
     146             : 
     147           0 :     virtual ~Parser() {}
     148             : 
     149           0 :     virtual boost::optional< OUString > getCwdUrl() SAL_OVERRIDE { return m_cwdUrl; }
     150             : 
     151           0 :     virtual bool next(OUString * argument) SAL_OVERRIDE { return next(argument, true); }
     152             : 
     153             : private:
     154           0 :     bool next(OUString * argument, bool prefix) {
     155             :         OSL_ASSERT(argument != NULL);
     156           0 :         if (m_index < m_input.getLength()) {
     157           0 :             if (prefix) {
     158           0 :                 if (m_input[m_index] != ',') {
     159           0 :                     throw CommandLineArgs::Supplier::Exception();
     160             :                 }
     161           0 :                 ++m_index;
     162             :             }
     163           0 :             OStringBuffer b;
     164           0 :             while (m_index < m_input.getLength()) {
     165           0 :                 char c = m_input[m_index];
     166           0 :                 if (c == ',') {
     167           0 :                     break;
     168             :                 }
     169           0 :                 ++m_index;
     170           0 :                 if (c == '\\') {
     171           0 :                     if (m_index < m_input.getLength()) {
     172           0 :                         c = m_input[m_index++];
     173           0 :                         switch (c) {
     174             :                         case '0':
     175           0 :                             c = '\0';
     176           0 :                             break;
     177             :                         case ',':
     178             :                         case '\\':
     179           0 :                             break;
     180             :                         default:
     181           0 :                             throw CommandLineArgs::Supplier::Exception();
     182             :                         }
     183             :                     } else {
     184           0 :                         throw CommandLineArgs::Supplier::Exception();
     185             :                     }
     186             :                 }
     187           0 :                 b.append(c);
     188             :             }
     189           0 :             OString b2(b.makeStringAndClear());
     190           0 :             if (!rtl_convertStringToUString(
     191             :                     &argument->pData, b2.getStr(), b2.getLength(),
     192             :                     RTL_TEXTENCODING_UTF8,
     193             :                     (RTL_TEXTTOUNICODE_FLAGS_UNDEFINED_ERROR |
     194             :                      RTL_TEXTTOUNICODE_FLAGS_MBUNDEFINED_ERROR |
     195           0 :                      RTL_TEXTTOUNICODE_FLAGS_INVALID_ERROR)))
     196             :             {
     197           0 :                 throw CommandLineArgs::Supplier::Exception();
     198             :             }
     199           0 :             return true;
     200             :         } else {
     201           0 :             return false;
     202             :         }
     203             :     }
     204             : 
     205             :     boost::optional< OUString > m_cwdUrl;
     206             :     OString m_input;
     207             :     sal_Int32 m_index;
     208             : };
     209             : 
     210           0 : bool addArgument(OStringBuffer &rArguments, char prefix,
     211             :     const OUString &rArgument)
     212             : {
     213           0 :     OString utf8;
     214           0 :     if (!rArgument.convertToString(
     215             :             &utf8, RTL_TEXTENCODING_UTF8,
     216             :             (RTL_UNICODETOTEXT_FLAGS_UNDEFINED_ERROR |
     217           0 :              RTL_UNICODETOTEXT_FLAGS_INVALID_ERROR)))
     218             :     {
     219           0 :         return false;
     220             :     }
     221           0 :     rArguments.append(prefix);
     222           0 :     for (sal_Int32 i = 0; i < utf8.getLength(); ++i) {
     223           0 :         char c = utf8[i];
     224           0 :         switch (c) {
     225             :         case '\0':
     226           0 :             rArguments.append("\\0");
     227           0 :             break;
     228             :         case ',':
     229           0 :             rArguments.append("\\,");
     230           0 :             break;
     231             :         case '\\':
     232           0 :             rArguments.append("\\\\");
     233           0 :             break;
     234             :         default:
     235           0 :             rArguments.append(c);
     236           0 :             break;
     237             :         }
     238             :     }
     239           0 :     return true;
     240             : }
     241             : 
     242             : #endif
     243             : 
     244             : }
     245             : 
     246         116 : rtl::Reference< OfficeIPCThread > OfficeIPCThread::pGlobalOfficeIPCThread;
     247             :     namespace { struct Security : public rtl::Static<osl::Security, Security> {}; }
     248             : 
     249             : // Turns a string in aMsg such as file:///home/foo/.libreoffice/3
     250             : // Into a hex string of well known length ff132a86...
     251         115 : OUString CreateMD5FromString( const OUString& aMsg )
     252             : {
     253             : #if (OSL_DEBUG_LEVEL > 2)
     254             :     fprintf( stderr, "create md5 from '%s'\n",
     255             :              OUStringToOString (aMsg, RTL_TEXTENCODING_UTF8).getStr() );
     256             : #endif
     257             : 
     258         115 :     rtlDigest handle = rtl_digest_create( rtl_Digest_AlgorithmMD5 );
     259         115 :     if ( handle )
     260             :     {
     261         115 :         const sal_uInt8* pData = reinterpret_cast<const sal_uInt8*>(aMsg.getStr());
     262         115 :         sal_uInt32       nSize = ( aMsg.getLength() * sizeof( sal_Unicode ));
     263         115 :         sal_uInt32       nMD5KeyLen = rtl_digest_queryLength( handle );
     264         115 :         boost::scoped_array<sal_uInt8> pMD5KeyBuffer(new sal_uInt8[ nMD5KeyLen ]);
     265             : 
     266         115 :         rtl_digest_init( handle, pData, nSize );
     267         115 :         rtl_digest_update( handle, pData, nSize );
     268         115 :         rtl_digest_get( handle, pMD5KeyBuffer.get(), nMD5KeyLen );
     269         115 :         rtl_digest_destroy( handle );
     270             : 
     271             :         // Create hex-value string from the MD5 value to keep the string size minimal
     272         230 :         OUStringBuffer aBuffer( nMD5KeyLen * 2 + 1 );
     273        1955 :         for ( sal_uInt32 i = 0; i < nMD5KeyLen; i++ )
     274        1840 :             aBuffer.append( (sal_Int32)pMD5KeyBuffer[i], 16 );
     275             : 
     276         230 :         return aBuffer.makeStringAndClear();
     277             :     }
     278             : 
     279           0 :     return OUString();
     280             : }
     281             : 
     282             : class ProcessEventsClass_Impl
     283             : {
     284             : public:
     285             :     DECL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void* pEvent );
     286             :     DECL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void* pEvent );
     287             : };
     288             : 
     289           0 : IMPL_STATIC_LINK( ProcessEventsClass_Impl, CallEvent, void*, pEvent )
     290             : {
     291             :     // Application events are processed by the Desktop::HandleAppEvent implementation.
     292           0 :     Desktop::HandleAppEvent( *static_cast<ApplicationEvent*>(pEvent) );
     293           0 :     delete static_cast<ApplicationEvent*>(pEvent);
     294           0 :     return 0;
     295             : }
     296             : 
     297           0 : IMPL_STATIC_LINK( ProcessEventsClass_Impl, ProcessDocumentsEvent, void*, pEvent )
     298             : {
     299             :     // Documents requests are processed by the OfficeIPCThread implementation
     300           0 :     ProcessDocumentsRequest* pDocsRequest = static_cast<ProcessDocumentsRequest*>(pEvent);
     301             : 
     302           0 :     if ( pDocsRequest )
     303             :     {
     304           0 :         OfficeIPCThread::ExecuteCmdLineRequests( *pDocsRequest );
     305           0 :         delete pDocsRequest;
     306             :     }
     307           0 :     return 0;
     308             : }
     309             : 
     310           0 : void ImplPostForeignAppEvent( ApplicationEvent* pEvent )
     311             : {
     312           0 :     Application::PostUserEvent( LINK( NULL, ProcessEventsClass_Impl, CallEvent ), pEvent );
     313           0 : }
     314             : 
     315           0 : void ImplPostProcessDocumentsEvent( ProcessDocumentsRequest* pEvent )
     316             : {
     317           0 :     Application::PostUserEvent( LINK( NULL, ProcessEventsClass_Impl, ProcessDocumentsEvent ), pEvent );
     318           0 : }
     319             : 
     320           0 : oslSignalAction SAL_CALL SalMainPipeExchangeSignal_impl(void* /*pData*/, oslSignalInfo* pInfo)
     321             : {
     322           0 :     if( pInfo->Signal == osl_Signal_Terminate )
     323           0 :         OfficeIPCThread::DisableOfficeIPCThread(false);
     324           0 :     return osl_Signal_ActCallNextHdl;
     325             : }
     326             : 
     327             : 
     328             : 
     329             : // The OfficeIPCThreadController implementation is a bookkeeper for all pending requests
     330             : // that were created by the OfficeIPCThread. The requests are waiting to be processed by
     331             : // our framework loadComponentFromURL function (e.g. open/print request).
     332             : // During shutdown the framework is asking OfficeIPCThreadController about pending requests.
     333             : // If there are pending requests framework has to stop the shutdown process. It is waiting
     334             : // for these requests because framework is not able to handle shutdown and open a document
     335             : // concurrently.
     336             : 
     337             : 
     338             : // XServiceInfo
     339          64 : OUString SAL_CALL OfficeIPCThreadController::getImplementationName()
     340             : throw ( RuntimeException, std::exception )
     341             : {
     342          64 :     return OUString( "com.sun.star.comp.OfficeIPCThreadController" );
     343             : }
     344             : 
     345           0 : sal_Bool OfficeIPCThreadController::supportsService(
     346             :     OUString const & ServiceName) throw (css::uno::RuntimeException, std::exception)
     347             : {
     348           0 :     return cppu::supportsService(this, ServiceName);
     349             : }
     350             : 
     351           0 : Sequence< OUString > SAL_CALL OfficeIPCThreadController::getSupportedServiceNames()
     352             : throw ( RuntimeException, std::exception )
     353             : {
     354           0 :     Sequence< OUString > aSeq( 0 );
     355           0 :     return aSeq;
     356             : }
     357             : 
     358             : // XEventListener
     359           0 : void SAL_CALL OfficeIPCThreadController::disposing( const EventObject& )
     360             : throw( RuntimeException, std::exception )
     361             : {
     362           0 : }
     363             : 
     364             : // XTerminateListener
     365          63 : void SAL_CALL OfficeIPCThreadController::queryTermination( const EventObject& )
     366             : throw( TerminationVetoException, RuntimeException, std::exception )
     367             : {
     368             :     // Desktop ask about pending request through our office ipc pipe. We have to
     369             :     // be sure that no pending request is waiting because framework is not able to
     370             :     // handle shutdown and open a document concurrently.
     371             : 
     372          63 :     if ( OfficeIPCThread::AreRequestsPending() )
     373           0 :         throw TerminationVetoException();
     374             :     else
     375          63 :         OfficeIPCThread::SetDowning();
     376          63 : }
     377             : 
     378          63 : void SAL_CALL OfficeIPCThreadController::notifyTermination( const EventObject& )
     379             : throw( RuntimeException, std::exception )
     380             : {
     381          63 : }
     382             : 
     383             : namespace
     384             : {
     385             :     class theOfficeIPCThreadMutex
     386             :         : public rtl::Static<osl::Mutex, theOfficeIPCThreadMutex> {};
     387             : }
     388             : 
     389         605 : ::osl::Mutex& OfficeIPCThread::GetMutex()
     390             : {
     391         605 :     return theOfficeIPCThreadMutex::get();
     392             : }
     393             : 
     394          63 : void OfficeIPCThread::SetDowning()
     395             : {
     396             :     // We have the order to block all incoming requests. Framework
     397             :     // wants to shutdown and we have to make sure that no loading/printing
     398             :     // requests are executed anymore.
     399          63 :     ::osl::MutexGuard   aGuard( GetMutex() );
     400             : 
     401          63 :     if ( pGlobalOfficeIPCThread.is() )
     402          63 :         pGlobalOfficeIPCThread->mbDowning = true;
     403          63 : }
     404             : 
     405             : static bool s_bInEnableRequests = false;
     406             : 
     407          64 : void OfficeIPCThread::EnableRequests( bool i_bEnable )
     408             : {
     409             :     // switch between just queueing the requests and executing them
     410          64 :     ::osl::MutexGuard   aGuard( GetMutex() );
     411             : 
     412          64 :     if ( pGlobalOfficeIPCThread.is() )
     413             :     {
     414          64 :         s_bInEnableRequests = true;
     415          64 :         pGlobalOfficeIPCThread->mbRequestsEnabled = i_bEnable;
     416          64 :         if( i_bEnable )
     417             :         {
     418             :             // hit the compiler over the head
     419          64 :             ProcessDocumentsRequest aEmptyReq = ProcessDocumentsRequest( boost::optional< OUString >() );
     420             :             // trigger already queued requests
     421          64 :             OfficeIPCThread::ExecuteCmdLineRequests( aEmptyReq );
     422             :         }
     423          64 :         s_bInEnableRequests = false;
     424          64 :     }
     425          64 : }
     426             : 
     427          63 : bool OfficeIPCThread::AreRequestsPending()
     428             : {
     429             :     // Give info about pending requests
     430          63 :     ::osl::MutexGuard   aGuard( GetMutex() );
     431          63 :     if ( pGlobalOfficeIPCThread.is() )
     432          63 :         return ( pGlobalOfficeIPCThread->mnPendingRequests > 0 );
     433             :     else
     434           0 :         return false;
     435             : }
     436             : 
     437           1 : void OfficeIPCThread::RequestsCompleted( int nCount )
     438             : {
     439             :     // Remove nCount pending requests from our internal counter
     440           1 :     ::osl::MutexGuard   aGuard( GetMutex() );
     441           1 :     if ( pGlobalOfficeIPCThread.is() )
     442             :     {
     443           1 :         if ( pGlobalOfficeIPCThread->mnPendingRequests > 0 )
     444           1 :             pGlobalOfficeIPCThread->mnPendingRequests -= nCount;
     445           1 :     }
     446           1 : }
     447             : 
     448         117 : OfficeIPCThread::Status OfficeIPCThread::EnableOfficeIPCThread()
     449             : {
     450         117 :     ::osl::MutexGuard   aGuard( GetMutex() );
     451             : 
     452         117 :     if( pGlobalOfficeIPCThread.is() )
     453           1 :         return IPC_STATUS_OK;
     454             : 
     455             : #if HAVE_FEATURE_DESKTOP || defined(ANDROID)
     456         232 :     OUString aUserInstallPath;
     457         232 :     OUString aDummy;
     458             : 
     459         232 :     rtl::Reference< OfficeIPCThread > pThread(new OfficeIPCThread);
     460             : 
     461         116 :     PipeMode nPipeMode = PIPEMODE_DONTKNOW;
     462             : 
     463             : #ifndef ANDROID // On Android it might be that we still for some reason need the pipe?
     464             : 
     465             :     // In LibreOfficeKit-based programs we want to be totally independent from any other LibreOffice
     466             :     // instance or LOKit-using program. Certainly no need for any IPC pipes by definition, as we
     467             :     // don't have any reason to do any IPC. Why we even call this EnableOfficeIPCThread function
     468             :     // from LibreOfficeKit's lo_initialize() I am not completely sure, but that code, and this, is
     469             :     // such horrible crack that I don't want to change it too much.
     470             : 
     471         116 :     if (comphelper::LibreOfficeKit::isActive())
     472             :     {
     473             :         // Setting nPipeMode to PIPEMODE_CREATED causes the trivial path to be taken below, starting
     474             :         // the listeing thread. (Which will immediately finish, see the execute() function, but what
     475             :         // the heck...)
     476           1 :         nPipeMode = PIPEMODE_CREATED;
     477             :     }
     478             :     else
     479             : #endif
     480             :     {
     481             :         // The name of the named pipe is created with the hashcode of the user installation directory (without /user). We have to retrieve
     482             :         // this information from a unotools implementation.
     483         115 :         ::utl::Bootstrap::PathStatus aLocateResult = ::utl::Bootstrap::locateUserInstallation( aUserInstallPath );
     484         115 :         if ( aLocateResult == ::utl::Bootstrap::PATH_EXISTS || aLocateResult == ::utl::Bootstrap::PATH_VALID)
     485         115 :             aDummy = aUserInstallPath;
     486             :         else
     487             :         {
     488           0 :             return IPC_STATUS_BOOTSTRAP_ERROR;
     489             :         }
     490             : 
     491             :         // Try to  determine if we are the first office or not! This should prevent multiple
     492             :         // access to the user directory !
     493             :         // First we try to create our pipe if this fails we try to connect. We have to do this
     494             :         // in a loop because the other office can crash or shutdown between createPipe
     495             :         // and connectPipe!!
     496             : 
     497         115 :         OUString            aIniName;
     498             : 
     499         115 :         osl_getExecutableFile( &aIniName.pData );
     500             : 
     501         115 :         sal_uInt32     lastIndex = aIniName.lastIndexOf('/');
     502         115 :         if ( lastIndex > 0 )
     503             :         {
     504         115 :             aIniName    = aIniName.copy( 0, lastIndex+1 );
     505         115 :             aIniName    += "perftune";
     506             :     #if defined(WNT)
     507             :             aIniName    += ".ini";
     508             :     #else
     509         115 :             aIniName    += "rc";
     510             :     #endif
     511             :         }
     512             : 
     513         230 :         ::rtl::Bootstrap aPerfTuneIniFile( aIniName );
     514             : 
     515         230 :         OUString aDefault( "0" );
     516         230 :         OUString aPreloadData;
     517             : 
     518         115 :         aPerfTuneIniFile.getFrom( OUString( "FastPipeCommunication" ), aPreloadData, aDefault );
     519             : 
     520             : 
     521         230 :         OUString aUserInstallPathHashCode;
     522             : 
     523         115 :         if ( aPreloadData == "1" )
     524             :         {
     525             :             sal_Char    szBuffer[32];
     526           0 :             sprintf( szBuffer, "%d", LIBO_VERSION_MAJOR * 10000 + LIBO_VERSION_MINOR * 100 + LIBO_VERSION_MICRO * 1 );
     527           0 :             aUserInstallPathHashCode = OUString( szBuffer, strlen(szBuffer), osl_getThreadTextEncoding() );
     528             :         }
     529             :         else
     530         115 :             aUserInstallPathHashCode = CreateMD5FromString( aDummy );
     531             : 
     532             : 
     533             :         // Check result to create a hash code from the user install path
     534         115 :         if ( aUserInstallPathHashCode.isEmpty() )
     535           0 :             return IPC_STATUS_BOOTSTRAP_ERROR; // Something completely broken, we cannot create a valid hash code!
     536             : 
     537         230 :         OUString aPipeIdent( "SingleOfficeIPC_" + aUserInstallPathHashCode );
     538             : 
     539         115 :         do
     540             :         {
     541         115 :             osl::Security &rSecurity = Security::get();
     542             : 
     543             :             // Try to create pipe
     544         115 :             if ( pThread->maPipe.create( aPipeIdent.getStr(), osl_Pipe_CREATE, rSecurity ))
     545             :             {
     546             :                 // Pipe created
     547         115 :                 nPipeMode = PIPEMODE_CREATED;
     548             :             }
     549           0 :             else if( pThread->maPipe.create( aPipeIdent.getStr(), osl_Pipe_OPEN, rSecurity )) // Creation not successful, now we try to connect
     550             :             {
     551           0 :                 osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle());
     552           0 :                 if (readStringFromPipe(aStreamPipe) == SEND_ARGUMENTS)
     553             :                 {
     554             :                     // Pipe connected to first office
     555           0 :                     nPipeMode = PIPEMODE_CONNECTED;
     556             :                 }
     557             :                 else
     558             :                 {
     559             :                     // Pipe connection failed (other office exited or crashed)
     560             :                     TimeValue tval;
     561           0 :                     tval.Seconds = 0;
     562           0 :                     tval.Nanosec = 500000000;
     563           0 :                     salhelper::Thread::wait( tval );
     564           0 :                 }
     565             :             }
     566             :             else
     567             :             {
     568           0 :                 oslPipeError eReason = pThread->maPipe.getError();
     569           0 :                 if ((eReason == osl_Pipe_E_ConnectionRefused) || (eReason == osl_Pipe_E_invalidError))
     570           0 :                     return IPC_STATUS_PIPE_ERROR;
     571             : 
     572             :                 // Wait for second office to be ready
     573             :                 TimeValue aTimeValue;
     574           0 :                 aTimeValue.Seconds = 0;
     575           0 :                 aTimeValue.Nanosec = 10000000; // 10ms
     576           0 :                 salhelper::Thread::wait( aTimeValue );
     577             :             }
     578             : 
     579         115 :         } while ( nPipeMode == PIPEMODE_DONTKNOW );
     580             :     }
     581             : 
     582         116 :     if ( nPipeMode == PIPEMODE_CREATED )
     583             :     {
     584             :         // Seems we are the one and only, so start listening thread
     585         116 :         pGlobalOfficeIPCThread = pThread;
     586         116 :         pThread->launch();
     587             :     }
     588             :     else
     589             :     {
     590             :         // Seems another office is running. Pipe arguments to it and self terminate
     591           0 :         osl::StreamPipe aStreamPipe(pThread->maPipe.getHandle());
     592             : 
     593           0 :         OStringBuffer aArguments(ARGUMENT_PREFIX);
     594           0 :         OUString cwdUrl;
     595           0 :         if (!(tools::getProcessWorkingDir(cwdUrl) &&
     596           0 :               addArgument(aArguments, '1', cwdUrl)))
     597             :         {
     598           0 :             aArguments.append('0');
     599             :         }
     600           0 :         sal_uInt32 nCount = rtl_getAppCommandArgCount();
     601           0 :         for( sal_uInt32 i=0; i < nCount; i++ )
     602             :         {
     603           0 :             rtl_getAppCommandArg( i, &aDummy.pData );
     604           0 :             if (!addArgument(aArguments, ',', aDummy)) {
     605           0 :                 return IPC_STATUS_BOOTSTRAP_ERROR;
     606             :             }
     607             :         }
     608           0 :         aArguments.append('\0');
     609             :         // finally, write the string onto the pipe
     610             :         sal_Int32 n = aStreamPipe.write(
     611           0 :             aArguments.getStr(), aArguments.getLength());
     612           0 :         if (n != aArguments.getLength()) {
     613             :             SAL_INFO("desktop", "short write: " << n);
     614           0 :             return IPC_STATUS_BOOTSTRAP_ERROR;
     615             :         }
     616             : 
     617           0 :         if (readStringFromPipe(aStreamPipe) != PROCESSING_DONE)
     618             :         {
     619             :             // something went wrong
     620           0 :             return IPC_STATUS_BOOTSTRAP_ERROR;
     621             :         }
     622             : 
     623           0 :         return IPC_STATUS_2ND_OFFICE;
     624             :     }
     625             : #else
     626             :     rtl::Reference< OfficeIPCThread > pThread(new OfficeIPCThread);
     627             :     pGlobalOfficeIPCThread = pThread;
     628             :     pThread->launch();
     629             : #endif
     630         233 :     return IPC_STATUS_OK;
     631             : }
     632             : 
     633         116 : void OfficeIPCThread::DisableOfficeIPCThread(bool join)
     634             : {
     635         116 :     osl::ClearableMutexGuard aMutex( GetMutex() );
     636             : 
     637         116 :     if( pGlobalOfficeIPCThread.is() )
     638             :     {
     639             :         rtl::Reference< OfficeIPCThread > pOfficeIPCThread(
     640         116 :             pGlobalOfficeIPCThread);
     641         116 :         pGlobalOfficeIPCThread.clear();
     642             : 
     643         116 :         pOfficeIPCThread->mbDowning = true;
     644         116 :         pOfficeIPCThread->maPipe.close();
     645             : 
     646             :         // release mutex to avoid deadlocks
     647         116 :         aMutex.clear();
     648             : 
     649         116 :         OfficeIPCThread::SetReady(pOfficeIPCThread);
     650             : 
     651             :         // exit gracefully and join
     652         116 :         if (join)
     653             :         {
     654         116 :             pOfficeIPCThread->join();
     655         116 :         }
     656         116 :     }
     657         116 : }
     658             : 
     659         116 : OfficeIPCThread::OfficeIPCThread() :
     660             :     Thread( "OfficeIPCThread" ),
     661             :     mbDowning( false ),
     662             :     mbRequestsEnabled( false ),
     663             :     mnPendingRequests( 0 ),
     664         116 :     mpDispatchWatcher( 0 )
     665             : {
     666         116 : }
     667             : 
     668         348 : OfficeIPCThread::~OfficeIPCThread()
     669             : {
     670         116 :     ::osl::ClearableMutexGuard  aGuard( GetMutex() );
     671             : 
     672         116 :     if ( mpDispatchWatcher )
     673          64 :         mpDispatchWatcher->release();
     674         116 :     maPipe.close();
     675         116 :     pGlobalOfficeIPCThread.clear();
     676         232 : }
     677             : 
     678         180 : void OfficeIPCThread::SetReady(
     679             :     rtl::Reference< OfficeIPCThread > const & pThread)
     680             : {
     681             :     rtl::Reference< OfficeIPCThread > const & t(
     682         180 :         pThread.is() ? pThread : pGlobalOfficeIPCThread);
     683         180 :     if (t.is())
     684             :     {
     685         180 :         t->cReady.set();
     686             :     }
     687         180 : }
     688             : 
     689           1 : void OfficeIPCThread::WaitForReady(
     690             :     rtl::Reference< OfficeIPCThread > const & pThread)
     691             : 
     692             : {
     693             :     rtl::Reference< OfficeIPCThread > const & t(
     694           1 :         pThread.is() ? pThread : pGlobalOfficeIPCThread);
     695           1 :     if (t.is())
     696             :     {
     697           1 :         t->cReady.wait();
     698             :     }
     699           1 : }
     700             : 
     701           1 : bool OfficeIPCThread::IsEnabled()
     702             : {
     703           1 :     return pGlobalOfficeIPCThread.is();
     704             : }
     705             : 
     706         116 : void OfficeIPCThread::execute()
     707             : {
     708             : #if HAVE_FEATURE_DESKTOP || defined(ANDROID)
     709             : 
     710             : #ifndef ANDROID
     711         116 :     if (comphelper::LibreOfficeKit::isActive())
     712           1 :         return;
     713             : #endif
     714             : 
     715           0 :     do
     716             :     {
     717         115 :         osl::StreamPipe aStreamPipe;
     718         115 :         oslPipeError nError = maPipe.accept( aStreamPipe );
     719             : 
     720             : 
     721         115 :         if( nError == osl_Pipe_E_None )
     722             :         {
     723             :             // if we receive a request while the office is displaying some dialog or error during
     724             :             // bootstrap, that dialogs event loop might get events that are dispatched by this thread
     725             :             // we have to wait for cReady to be set by the real main loop.
     726             :             // only reqests that dont dispatch events may be processed before cReady is set.
     727         115 :             cReady.wait();
     728             : 
     729             :             // we might have decided to shutdown while we were sleeping
     730         115 :             if (!pGlobalOfficeIPCThread.is()) return;
     731             : 
     732             :             // only lock the mutex when processing starts, othewise we deadlock when the office goes
     733             :             // down during wait
     734           0 :             osl::ClearableMutexGuard aGuard( GetMutex() );
     735             : 
     736           0 :             if ( mbDowning )
     737             :             {
     738           0 :                 break;
     739             :             }
     740             : 
     741             :             // notify client we're ready to process its args:
     742             :             sal_Int32 n = aStreamPipe.write(
     743           0 :                 SEND_ARGUMENTS, SAL_N_ELEMENTS(SEND_ARGUMENTS));
     744             :                 // incl. terminating NUL
     745           0 :             if (n != SAL_N_ELEMENTS(SEND_ARGUMENTS)) {
     746             :                 SAL_WARN("desktop", "short write: " << n);
     747           0 :                 continue;
     748             :             }
     749             : 
     750           0 :             OString aArguments = readStringFromPipe(aStreamPipe);
     751             : 
     752             :             // Is this a lookup message from another application? if so, ignore
     753           0 :             if (aArguments.isEmpty())
     754           0 :                 continue;
     755             : 
     756           0 :             boost::scoped_ptr< CommandLineArgs > aCmdLineArgs;
     757             :             try
     758             :             {
     759           0 :                 Parser p(aArguments);
     760           0 :                 aCmdLineArgs.reset( new CommandLineArgs( p ) );
     761             :             }
     762           0 :             catch ( const CommandLineArgs::Supplier::Exception & )
     763             :             {
     764             : #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
     765             :                 fprintf( stderr, "Error in received command line arguments\n" );
     766             : #endif
     767           0 :                 continue;
     768             :             }
     769             : 
     770           0 :             bool bDocRequestSent = false;
     771             : 
     772           0 :             OUString aUnknown( aCmdLineArgs->GetUnknown() );
     773           0 :             if ( !aUnknown.isEmpty() || aCmdLineArgs->IsHelp() )
     774             :             {
     775             :                 ApplicationEvent* pAppEvent =
     776           0 :                     new ApplicationEvent(ApplicationEvent::TYPE_HELP, aUnknown);
     777           0 :                 ImplPostForeignAppEvent( pAppEvent );
     778             :             }
     779           0 :             else if ( aCmdLineArgs->IsVersion() )
     780             :             {
     781             :                 ApplicationEvent* pAppEvent =
     782           0 :                     new ApplicationEvent(ApplicationEvent::TYPE_VERSION);
     783           0 :                 ImplPostForeignAppEvent( pAppEvent );
     784             :             }
     785             :             else
     786             :             {
     787           0 :                 const CommandLineArgs &rCurrentCmdLineArgs = Desktop::GetCommandLineArgs();
     788             : 
     789           0 :                 if ( aCmdLineArgs->IsQuickstart() )
     790             :                 {
     791             :                     // we have to use application event, because we have to start quickstart service in main thread!!
     792             :                     ApplicationEvent* pAppEvent =
     793           0 :                         new ApplicationEvent(ApplicationEvent::TYPE_QUICKSTART);
     794           0 :                     ImplPostForeignAppEvent( pAppEvent );
     795             :                 }
     796             : 
     797             :                 // handle request for acceptor
     798             :                 std::vector< OUString > const & accept = aCmdLineArgs->
     799           0 :                     GetAccept();
     800           0 :                 for (std::vector< OUString >::const_iterator i(accept.begin());
     801           0 :                      i != accept.end(); ++i)
     802             :                 {
     803             :                     ApplicationEvent* pAppEvent = new ApplicationEvent(
     804           0 :                         ApplicationEvent::TYPE_ACCEPT, *i);
     805           0 :                     ImplPostForeignAppEvent( pAppEvent );
     806             :                 }
     807             :                 // handle acceptor removal
     808             :                 std::vector< OUString > const & unaccept = aCmdLineArgs->
     809           0 :                     GetUnaccept();
     810           0 :                 for (std::vector< OUString >::const_iterator i(
     811           0 :                          unaccept.begin());
     812           0 :                      i != unaccept.end(); ++i)
     813             :                 {
     814             :                     ApplicationEvent* pAppEvent = new ApplicationEvent(
     815           0 :                         ApplicationEvent::TYPE_UNACCEPT, *i);
     816           0 :                     ImplPostForeignAppEvent( pAppEvent );
     817             :                 }
     818             : 
     819             :                 ProcessDocumentsRequest* pRequest = new ProcessDocumentsRequest(
     820           0 :                     aCmdLineArgs->getCwdUrl());
     821           0 :                 cProcessed.reset();
     822           0 :                 pRequest->pcProcessed = &cProcessed;
     823             : 
     824             :                 // Print requests are not dependent on the --invisible cmdline argument as they are
     825             :                 // loaded with the "hidden" flag! So they are always checked.
     826           0 :                 pRequest->aPrintList = aCmdLineArgs->GetPrintList();
     827           0 :                 bDocRequestSent |= !pRequest->aPrintList.empty();
     828           0 :                 pRequest->aPrintToList = aCmdLineArgs->GetPrintToList();
     829           0 :                 pRequest->aPrinterName = aCmdLineArgs->GetPrinterName();
     830           0 :                 bDocRequestSent |= !( pRequest->aPrintToList.empty() || pRequest->aPrinterName.isEmpty() );
     831             : 
     832           0 :                 if ( !rCurrentCmdLineArgs.IsInvisible() )
     833             :                 {
     834             :                     // Read cmdline args that can open/create documents. As they would open a window
     835             :                     // they are only allowed if the "--invisible" is currently not used!
     836           0 :                     pRequest->aOpenList = aCmdLineArgs->GetOpenList();
     837           0 :                     bDocRequestSent |= !pRequest->aOpenList.empty();
     838           0 :                     pRequest->aViewList = aCmdLineArgs->GetViewList();
     839           0 :                     bDocRequestSent |= !pRequest->aViewList.empty();
     840           0 :                     pRequest->aStartList = aCmdLineArgs->GetStartList();
     841           0 :                     bDocRequestSent |= !pRequest->aStartList.empty();
     842           0 :                     pRequest->aForceOpenList = aCmdLineArgs->GetForceOpenList();
     843           0 :                     bDocRequestSent |= !pRequest->aForceOpenList.empty();
     844           0 :                     pRequest->aForceNewList = aCmdLineArgs->GetForceNewList();
     845           0 :                     bDocRequestSent |= !pRequest->aForceNewList.empty();
     846             : 
     847             :                     // Special command line args to create an empty document for a given module
     848             : 
     849             :                     // #i18338# (lo)
     850             :                     // we only do this if no document was specified on the command line,
     851             :                     // since this would be inconsistent with the behaviour of
     852             :                     // the first process, see OpenClients() (call to OpenDefault()) in app.cxx
     853           0 :                     if ( aCmdLineArgs->HasModuleParam() && !bDocRequestSent )
     854             :                     {
     855           0 :                         SvtModuleOptions aOpt;
     856           0 :                         SvtModuleOptions::EFactory eFactory = SvtModuleOptions::EFactory::WRITER;
     857           0 :                         if ( aCmdLineArgs->IsWriter() )
     858           0 :                             eFactory = SvtModuleOptions::EFactory::WRITER;
     859           0 :                         else if ( aCmdLineArgs->IsCalc() )
     860           0 :                             eFactory = SvtModuleOptions::EFactory::CALC;
     861           0 :                         else if ( aCmdLineArgs->IsDraw() )
     862           0 :                             eFactory = SvtModuleOptions::EFactory::DRAW;
     863           0 :                         else if ( aCmdLineArgs->IsImpress() )
     864           0 :                             eFactory = SvtModuleOptions::EFactory::IMPRESS;
     865           0 :                         else if ( aCmdLineArgs->IsBase() )
     866           0 :                             eFactory = SvtModuleOptions::EFactory::DATABASE;
     867           0 :                         else if ( aCmdLineArgs->IsMath() )
     868           0 :                             eFactory = SvtModuleOptions::EFactory::MATH;
     869           0 :                         else if ( aCmdLineArgs->IsGlobal() )
     870           0 :                             eFactory = SvtModuleOptions::EFactory::WRITERGLOBAL;
     871           0 :                         else if ( aCmdLineArgs->IsWeb() )
     872           0 :                             eFactory = SvtModuleOptions::EFactory::WRITERWEB;
     873             : 
     874           0 :                         if ( !pRequest->aOpenList.empty() )
     875           0 :                             pRequest->aModule = aOpt.GetFactoryName( eFactory );
     876             :                         else
     877           0 :                             pRequest->aOpenList.push_back( aOpt.GetFactoryEmptyDocumentURL( eFactory ) );
     878           0 :                         bDocRequestSent = true;
     879             :                     }
     880             :                 }
     881             : 
     882           0 :                 if ( !aCmdLineArgs->IsQuickstart() ) {
     883           0 :                     bool bShowHelp = false;
     884           0 :                     OUStringBuffer aHelpURLBuffer;
     885           0 :                     if (aCmdLineArgs->IsHelpWriter()) {
     886           0 :                         bShowHelp = true;
     887           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://swriter/start");
     888           0 :                     } else if (aCmdLineArgs->IsHelpCalc()) {
     889           0 :                         bShowHelp = true;
     890           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://scalc/start");
     891           0 :                     } else if (aCmdLineArgs->IsHelpDraw()) {
     892           0 :                         bShowHelp = true;
     893           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdraw/start");
     894           0 :                     } else if (aCmdLineArgs->IsHelpImpress()) {
     895           0 :                         bShowHelp = true;
     896           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://simpress/start");
     897           0 :                     } else if (aCmdLineArgs->IsHelpBase()) {
     898           0 :                         bShowHelp = true;
     899           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://sdatabase/start");
     900           0 :                     } else if (aCmdLineArgs->IsHelpBasic()) {
     901           0 :                         bShowHelp = true;
     902           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://sbasic/start");
     903           0 :                     } else if (aCmdLineArgs->IsHelpMath()) {
     904           0 :                         bShowHelp = true;
     905           0 :                         aHelpURLBuffer.appendAscii("vnd.sun.star.help://smath/start");
     906             :                     }
     907           0 :                     if (bShowHelp) {
     908           0 :                         aHelpURLBuffer.appendAscii("?Language=");
     909           0 :                         aHelpURLBuffer.append(utl::ConfigManager::getLocale());
     910             : #if defined UNX
     911           0 :                         aHelpURLBuffer.appendAscii("&System=UNX");
     912             : #elif defined WNT
     913             :                         aHelpURLBuffer.appendAscii("&System=WIN");
     914             : #endif
     915             :                         ApplicationEvent* pAppEvent = new ApplicationEvent(
     916             :                             ApplicationEvent::TYPE_OPENHELPURL,
     917           0 :                             aHelpURLBuffer.makeStringAndClear());
     918           0 :                         ImplPostForeignAppEvent( pAppEvent );
     919           0 :                     }
     920             :                 }
     921             : 
     922           0 :                 if ( bDocRequestSent )
     923             :                 {
     924             :                     // Send requests to dispatch watcher if we have at least one. The receiver
     925             :                     // is responsible to delete the request after processing it.
     926           0 :                     if ( aCmdLineArgs->HasModuleParam() )
     927             :                     {
     928           0 :                         SvtModuleOptions    aOpt;
     929             : 
     930             :                         // Support command line parameters to start a module (as preselection)
     931           0 :                         if ( aCmdLineArgs->IsWriter() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::WRITER ) )
     932           0 :                             pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::WRITER );
     933           0 :                         else if ( aCmdLineArgs->IsCalc() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::CALC ) )
     934           0 :                             pRequest->aModule = aOpt.GetFactoryName( SvtModuleOptions::EFactory::CALC );
     935           0 :                         else if ( aCmdLineArgs->IsImpress() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::IMPRESS ) )
     936           0 :                             pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::IMPRESS );
     937           0 :                         else if ( aCmdLineArgs->IsDraw() && aOpt.IsModuleInstalled( SvtModuleOptions::EModule::DRAW ) )
     938           0 :                             pRequest->aModule= aOpt.GetFactoryName( SvtModuleOptions::EFactory::DRAW );
     939             :                     }
     940             : 
     941           0 :                     ImplPostProcessDocumentsEvent( pRequest );
     942             :                 }
     943             :                 else
     944             :                 {
     945             :                     // delete not used request again
     946           0 :                     delete pRequest;
     947           0 :                     pRequest = NULL;
     948             :                 }
     949           0 :                 if (aArguments.equalsL(RTL_CONSTASCII_STRINGPARAM("-tofront")) ||
     950           0 :                     aCmdLineArgs->IsEmpty())
     951             :                 {
     952             :                     // no document was sent, just bring Office to front
     953             :                     ApplicationEvent* pAppEvent =
     954           0 :                         new ApplicationEvent(ApplicationEvent::TYPE_APPEAR);
     955           0 :                     ImplPostForeignAppEvent( pAppEvent );
     956             :                 }
     957             :             }
     958             : 
     959             :             // we don't need the mutex any longer...
     960           0 :             aGuard.clear();
     961             :             // wait for processing to finish
     962           0 :             if (bDocRequestSent)
     963           0 :                 cProcessed.wait();
     964             :             // processing finished, inform the requesting end:
     965             :             n = aStreamPipe.write(
     966           0 :                 PROCESSING_DONE, SAL_N_ELEMENTS(PROCESSING_DONE));
     967             :                 // incl. terminating NUL
     968           0 :             if (n != SAL_N_ELEMENTS(PROCESSING_DONE)) {
     969             :                 SAL_WARN("desktop", "short write: " << n);
     970           0 :                 continue;
     971           0 :             }
     972             :         }
     973             :         else
     974             :         {
     975             :             {
     976           0 :                 osl::MutexGuard aGuard( GetMutex() );
     977           0 :                 if ( mbDowning )
     978             :                 {
     979           0 :                     break;
     980           0 :                 }
     981             :             }
     982             : 
     983             : #if (OSL_DEBUG_LEVEL > 1) || defined DBG_UTIL
     984             :             fprintf( stderr, "Error on accept: %d\n", (int)nError );
     985             : #endif
     986             :             TimeValue tval;
     987           0 :             tval.Seconds = 1;
     988           0 :             tval.Nanosec = 0;
     989           0 :             salhelper::Thread::wait( tval );
     990           0 :         }
     991           0 :     } while( schedule() );
     992             : #endif
     993             : }
     994             : 
     995         520 : static void AddToDispatchList(
     996             :     DispatchWatcher::DispatchList& rDispatchList,
     997             :     boost::optional< OUString > const & cwdUrl,
     998             :     std::vector< OUString > const & aRequestList,
     999             :     DispatchWatcher::RequestType nType,
    1000             :     const OUString& aParam,
    1001             :     const OUString& aFactory )
    1002             : {
    1003        1563 :     for (std::vector< OUString >::const_iterator i(aRequestList.begin());
    1004        1042 :          i != aRequestList.end(); ++i)
    1005             :     {
    1006             :         rDispatchList.push_back(
    1007           1 :             DispatchWatcher::DispatchRequest( nType, *i, cwdUrl, aParam, aFactory ));
    1008             :     }
    1009         520 : }
    1010             : 
    1011          65 : static void AddConversionsToDispatchList(
    1012             :     DispatchWatcher::DispatchList& rDispatchList,
    1013             :     boost::optional< OUString > const & cwdUrl,
    1014             :     std::vector< OUString > const & rRequestList,
    1015             :     const OUString& rParam,
    1016             :     const OUString& rPrinterName,
    1017             :     const OUString& rFactory,
    1018             :     const OUString& rParamOut,
    1019             :     const bool isTextCat )
    1020             : {
    1021             :     DispatchWatcher::RequestType nType;
    1022          65 :     OUString aParam( rParam );
    1023             : 
    1024          65 :     if( !rParam.isEmpty() )
    1025             :     {
    1026           0 :         nType = ( isTextCat ) ? DispatchWatcher::REQUEST_CAT : DispatchWatcher::REQUEST_CONVERSION;
    1027           0 :         aParam = rParam;
    1028             :     }
    1029             :     else
    1030             :     {
    1031          65 :         nType = DispatchWatcher::REQUEST_BATCHPRINT;
    1032          65 :         aParam = rPrinterName;
    1033             :     }
    1034             : 
    1035         130 :     OUString aOutDir( rParamOut.trim() );
    1036         130 :     OUString aPWD;
    1037          65 :     ::tools::getProcessWorkingDir( aPWD );
    1038             : 
    1039          65 :     if( !::osl::FileBase::getAbsoluteFileURL( aPWD, rParamOut, aOutDir ) )
    1040           0 :         ::osl::FileBase::getSystemPathFromFileURL( aOutDir, aOutDir );
    1041             : 
    1042          65 :     if( !rParamOut.trim().isEmpty() )
    1043             :     {
    1044           0 :         aParam += ";";
    1045           0 :         aParam += aOutDir;
    1046             :     }
    1047             :     else
    1048             :     {
    1049          65 :         ::osl::FileBase::getSystemPathFromFileURL( aPWD, aPWD );
    1050          65 :         aParam += ";" + aPWD;
    1051             :     }
    1052             : 
    1053         195 :     for (std::vector< OUString >::const_iterator i(rRequestList.begin());
    1054         130 :          i != rRequestList.end(); ++i)
    1055             :     {
    1056             :         rDispatchList.push_back(
    1057           0 :             DispatchWatcher::DispatchRequest( nType, *i, cwdUrl, aParam, rFactory ));
    1058          65 :     }
    1059          65 : }
    1060             : 
    1061             : 
    1062          65 : bool OfficeIPCThread::ExecuteCmdLineRequests( ProcessDocumentsRequest& aRequest )
    1063             : {
    1064             :     // protect the dispatch list
    1065          65 :     osl::ClearableMutexGuard aGuard( GetMutex() );
    1066             : 
    1067          65 :     static DispatchWatcher::DispatchList    aDispatchList;
    1068             : 
    1069         130 :     OUString aEmpty;
    1070             :     // Create dispatch list for dispatch watcher
    1071          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aInFilter, DispatchWatcher::REQUEST_INFILTER, aEmpty, aRequest.aModule );
    1072          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aOpenList, DispatchWatcher::REQUEST_OPEN, aEmpty, aRequest.aModule );
    1073          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aViewList, DispatchWatcher::REQUEST_VIEW, aEmpty, aRequest.aModule );
    1074          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aStartList, DispatchWatcher::REQUEST_START, aEmpty, aRequest.aModule );
    1075          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintList, DispatchWatcher::REQUEST_PRINT, aEmpty, aRequest.aModule );
    1076          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aPrintToList, DispatchWatcher::REQUEST_PRINTTO, aRequest.aPrinterName, aRequest.aModule );
    1077          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceOpenList, DispatchWatcher::REQUEST_FORCEOPEN, aEmpty, aRequest.aModule );
    1078          65 :     AddToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aForceNewList, DispatchWatcher::REQUEST_FORCENEW, aEmpty, aRequest.aModule );
    1079          65 :     AddConversionsToDispatchList( aDispatchList, aRequest.aCwdUrl, aRequest.aConversionList, aRequest.aConversionParams, aRequest.aPrinterName, aRequest.aModule, aRequest.aConversionOut, aRequest.bTextCat );
    1080          65 :     bool bShutdown( false );
    1081             : 
    1082          65 :     if ( pGlobalOfficeIPCThread.is() )
    1083             :     {
    1084          65 :         if( ! pGlobalOfficeIPCThread->AreRequestsEnabled() )
    1085           0 :             return bShutdown;
    1086             : 
    1087          65 :         pGlobalOfficeIPCThread->mnPendingRequests += aDispatchList.size();
    1088          65 :         if ( !pGlobalOfficeIPCThread->mpDispatchWatcher )
    1089             :         {
    1090          64 :             pGlobalOfficeIPCThread->mpDispatchWatcher = DispatchWatcher::GetDispatchWatcher();
    1091          64 :             pGlobalOfficeIPCThread->mpDispatchWatcher->acquire();
    1092             :         }
    1093             : 
    1094             :         // copy for execute
    1095          65 :         DispatchWatcher::DispatchList aTempList( aDispatchList );
    1096          65 :         aDispatchList.clear();
    1097             : 
    1098          65 :         aGuard.clear();
    1099             : 
    1100             :         // Execute dispatch requests
    1101          65 :         bShutdown = pGlobalOfficeIPCThread->mpDispatchWatcher->executeDispatchRequests( aTempList, s_bInEnableRequests );
    1102             : 
    1103             :         // set processed flag
    1104          65 :         if (aRequest.pcProcessed != NULL)
    1105           0 :             aRequest.pcProcessed->set();
    1106             :     }
    1107             : 
    1108         130 :     return bShutdown;
    1109             : }
    1110             : 
    1111         348 : }
    1112             : 
    1113             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11