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

Generated by: LCOV version 1.10