diff -r cad71a31b7fc -r e36f3802f733 srsf/vcommandhandler/src/vcommandrunnable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/srsf/vcommandhandler/src/vcommandrunnable.cpp Wed Sep 01 12:29:17 2010 +0100 @@ -0,0 +1,268 @@ +/* +* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Implementation of the CVCommandRunnable class +* +*/ + + + +#include +#include "rubydebug.h" + +#include +#include +#include +#include +#include + +/** +* The version of the streamed data protocol +* It is rather likely, that the format of the data streamed changes in the future. +* Using the protocol version, the code can check if it knows how to parse the +* input stream +*/ +const TInt32 KVCRunnableProtocolVersion = 2; + +/** +* @leave KErrOverflow if aArguments is longer, than KMaxVCArgumentLength +* @leave KErrArgument if aAppUid is KNullUidValue +*/ +EXPORT_C CVCRunnable* CVCRunnable::NewL( TUid aAppUid, const TDesC8& aArguments ) + { + CVCRunnable* self = new ( ELeave ) CVCRunnable; + CleanupStack::PushL( self ); + self->ConstructL( aAppUid, aArguments ); + CleanupStack::Pop( self ); + return self; + } + +/** +* Factory function +* @param aExeName Exe-file to start. Can be full or partical name according to +* the RProcess::Create rules. Cannot be KNullDesC +* @param aArguments Command line to pass to the application. This object makes +* a copy of the passed string +* @leave KErrOverflow if aArguments is longer, than KMaxVCArgumentLength or +* aExeName is longer, than KMaxOsName +* @leave KErrUndeflow if aExeName is empty +*/ +EXPORT_C CVCRunnable* CVCRunnable::NewL( const TDesC& aExeName, const TDesC8& aArguments ) + { + CVCRunnable* self = new( ELeave ) CVCRunnable; + CleanupStack::PushL( self ); + self->ConstructL( aExeName, aArguments); + CleanupStack::Pop( self ); + return self; + } + +/** +* Copy the existing CVRunnable +*/ +EXPORT_C CVCRunnable* CVCRunnable::NewL( const CVCRunnable& aOriginal ) + { + CVCRunnable* self = new (ELeave) CVCRunnable; + CleanupStack::PushL( self ); + if( aOriginal.Uid() == KNullUid ) + { + self->ConstructL( aOriginal.ExeName(), aOriginal.Arguments() ); + } + else + { + self->ConstructL( aOriginal.Uid(), aOriginal.Arguments() ); + } + CleanupStack::Pop( self ); + return self; + } + +/** +* Internalizes from stream +* values are read in the same order as ExternalizeL wrote them +*/ +EXPORT_C CVCRunnable* CVCRunnable::NewL( RReadStream &aStream ) + { + CVCRunnable* self = new (ELeave) CVCRunnable; + CleanupStack::PushL( self ); + self->ConstructL( aStream ); + CleanupStack::Pop( self ); + return self; + } + +void CVCRunnable::ConstructL( RReadStream &aStream ) + { + TInt32 ver; + aStream >> ver; + __ASSERT_ALWAYS( ver == KVCRunnableProtocolVersion, User::Leave( KErrNotSupported ) ); + iExeUid = TUid::Uid( aStream.ReadInt32L() ); + iArguments = HBufC8::NewL( aStream.ReadInt32L() ); + TPtr8 pArguments = iArguments->Des(); + aStream >> pArguments; + TInt exeNameLength = aStream.ReadInt32L(); + if( exeNameLength > 0 ) + { + iExeName = HBufC::NewL( exeNameLength ); + TPtr pExeName = iExeName->Des(); + aStream >> pExeName; + } + } + +void CVCRunnable::ConstructL( TUid aAppUid, const TDesC8& aArguments ) + { + __ASSERT_ALWAYS( aArguments.Length() <= KMaxVCArgumentLength, User::Leave( KErrOverflow) ); + __ASSERT_ALWAYS( aAppUid != KNullUid, User::Leave( KErrArgument ) ); + iExeUid = TUid::Uid( aAppUid.iUid ); + iArguments = HBufC8::NewL( aArguments.Length() ); + *iArguments = aArguments; + } + +void CVCRunnable::ConstructL( const TDesC& aExeName, const TDesC8& aArguments ) + { + __ASSERT_ALWAYS( aArguments.Length() <= KMaxVCArgumentLength, User::Leave( KErrOverflow) ); + __ASSERT_ALWAYS( aExeName.Length() <= KMaxFileName, User::Leave( KErrOverflow ) ); + __ASSERT_ALWAYS( aExeName.Length() > 0, User::Leave( KErrUnderflow ) ); + iExeName = HBufC::NewL( aExeName.Length() ); + *iExeName = aExeName; + iArguments = HBufC8::NewL( aArguments.Length() ); + *iArguments = aArguments; + } + +EXPORT_C CVCRunnable::~CVCRunnable() + { + delete iExeName; + delete iArguments; + } + +/** + * Saves the object to stream. + * The current format is as follows: + * + * + * + */ +EXPORT_C void CVCRunnable::ExternalizeL( RWriteStream &aStream ) const + { + aStream << KVCRunnableProtocolVersion; + aStream << iExeUid.iUid; + aStream << static_cast( iArguments->Length() ); + aStream << *iArguments; + if( iExeName ) + { + aStream << static_cast( iExeName->Length() ); + aStream << *iExeName; + } + else + { + aStream << static_cast( 0 ); + } + } + +EXPORT_C TBool CVCRunnable::operator==( const CVCRunnable& aRunnable ) const + { + return ( + ( Uid() == aRunnable.Uid()) && + ( Arguments() == aRunnable.Arguments() ) && + ( ExeName() == aRunnable.ExeName() ) + ); + } + + +/** +* @return The uid of the application to be started +*/ +EXPORT_C const TUid CVCRunnable::Uid() const + { + return iExeUid; + } + +/** +* @return The filename of the application to be started. KNullDesC if there is none +*/ +EXPORT_C const TDesC& CVCRunnable::ExeName() const + { + if( iExeName ) + { + return *iExeName; + } + else + { + return KNullDesC; + } + } + +/** +* The arguments to be passed to the application +*/ +EXPORT_C const TDesC8& CVCRunnable::Arguments() const + { + return *iArguments; + } + +/** +* Run the command. In case of aAppUid specified during the construction +* application is started via the RApaLsSession::StartApp, otherwise +* via the RProcess::Create +* @leave System-wide error code. In particular KErrNotFound if there is +* no such app in the system +*/ +EXPORT_C void CVCRunnable::ExecuteL() const + { + RUBY_DEBUG_BLOCK( "CVCRunnable::ExecuteL" ); + if( iExeName ) + { + RProcess process; + CleanupClosePushL( process ); + // Convert arguments into system_number_of_bits-bit descriptor + // (needed for exe, not needed for GUI apps) + HBufC* arguments = HBufC::NewLC( iArguments->Length() ); + arguments->Des().Copy( *iArguments ); + + User::LeaveIfError( process.Create( *iExeName, *arguments) ); + process.Resume(); + + CleanupStack::PopAndDestroy( arguments ); + CleanupStack::PopAndDestroy( &process ); + } + else + { + const TUid KLogsUID3 = { 270486741 };//101F4CD5 + //In case logs.exe run in background [EDCN-84B68Q] + //todo: General support for this kind of case, + // eg, add "view" keyworkd in defaultvoicecommands.xml... + if ( iExeUid == KLogsUID3 ) + { + TApaTaskList taskList( CCoeEnv::Static()->WsSession() ); + TApaTask task = taskList.FindApp( iExeUid ); + if( task.Exists() ) //Logs already open. Request it to + { //activate the correct view + task.SendMessage( iExeUid, *iArguments ); + return; + } + } + + TApaAppInfo appInfo; + RApaLsSession apaLsSession; + CleanupClosePushL( apaLsSession ); + User::LeaveIfError( apaLsSession.Connect() ); + User::LeaveIfError( apaLsSession.GetAppInfo( appInfo, iExeUid ) ); + + CApaCommandLine* apaCommandLine = CApaCommandLine::NewLC(); + apaCommandLine->SetExecutableNameL( appInfo.iFullName ); + apaCommandLine->SetTailEndL( *iArguments ); + User::LeaveIfError( apaLsSession.StartApp( *apaCommandLine ) ); + + CleanupStack::PopAndDestroy( apaCommandLine ); + CleanupStack::PopAndDestroy( &apaLsSession ); + } + } + +//End of file