/*
* Copyright (c) 2007-2007 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "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: This Class provides the functionality to launch the application
*
*/
#include <apgcli.h>
#include <apacmdln.h>
#include <e32std.h>
#include <eikappui.h>
#include <eikenv.h>
#include <e32base.h>
#include <f32file.h>
//#include <documenthandler.h>
#include "launcher.h"
#include "launcherobserver.h"
#include "appmanagerservice.h"
_LIT(KBackground ,"Background");
_LIT(KChained,"Chained");
_LIT(KScheme,"s60uid://0x");
const TInt KDocMaxDigitsInHexString = 8; // 32 bits.
const TInt KLen = 2; // "//" for count these
// -----------------------------------------------------------------------------
// CLauncher::NewLC
// Returns the instance of CLauncher class.
// -----------------------------------------------------------------------------
CLauncher* CLauncher::NewL( RApaLsSession& aSession )
{
CLauncher* self = new ( ELeave )CLauncher( aSession );
return self;
}
// -----------------------------------------------------------------------------
// CLauncher::LaunchApplication
// This function Launch the Given Application
// -----------------------------------------------------------------------------
TThreadId CLauncher::LaunchApplicationL( const TDesC& aAppId,
const TDesC8& aCmdLine,
const TOptions& aOptions
)
{
TUid appUid;
TApaAppInfo appInfo;
//parse the application string
ParseAppIdL( aAppId, appUid );
if(!( (0==aOptions.iMode.CompareF( KChained ) || 0 == aOptions.iMode.CompareF( KStandalone ) ) && (0==aOptions.iPostion.CompareF( KBackground ) || 0 == aOptions.iPostion.CompareF( KForeground ) ) ) )
{
User::Leave( KErrArgument );
}
CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
//Setting Executable name
if( KErrNone == iApaLsSession.GetAppInfo( appInfo, appUid) )
{
cmdLine->SetExecutableNameL( appInfo.iFullName );
}
else
{
//Invalid UID
User::Leave( KErrArgument );
}
//Setting command Line Argument
if ( aCmdLine.Length() )
{
cmdLine->SetTailEndL( aCmdLine );
}
//Setting Document Name
if ( aOptions.iDocument.Length() )
{
CAppManagerService::ValidateFilePathL(aOptions.iDocument);
cmdLine->SetDocumentNameL( aOptions.iDocument );
}
//Set the Launchine Mode
if( 0 == aOptions.iMode.CompareF( KChained ) )
{
//Chianed mode doesn;t make any sense with background
if( 0 != aOptions.iPostion.CompareF( KBackground ) )
cmdLine->SetCommandL( EApaCommandRun );
else
User::Leave( KErrNotSupported );
SetChainedModeL( cmdLine, appUid );
}
else
{
//Setting the Launching postion means either background or foreground
if( 0 == aOptions.iPostion.CompareF( KBackground ) )
{
cmdLine->SetCommandL( EApaCommandBackground );
}
else
{
cmdLine->SetCommandL( EApaCommandRun );
}
}
// Launch the requested Application
TThreadId threadNotUsed;
TRequestStatus requestStatusForRendezvous;
User::LeaveIfError( iApaLsSession.StartApp( *cmdLine,
threadNotUsed,
&requestStatusForRendezvous ));
User::WaitForRequest( requestStatusForRendezvous );
User::LeaveIfError( requestStatusForRendezvous.Int());
CleanupStack::PopAndDestroy( cmdLine );
return threadNotUsed;
}
// -----------------------------------------------------------------------------
// CLauncher::LaunchDocumentL
// This function Launch the Given Document
// -----------------------------------------------------------------------------
TThreadId CLauncher::LaunchDocumentL(TDocument& aCriteria,
const TDesC8& aMimeType,
const TOptions& aOptions ,
TDesC& aFileName
)
{
TUid appUid;
TApaAppInfo appInfo;
TDataType dataType( aMimeType );
CApaCommandLine* cmdLine = CApaCommandLine::NewLC();
TFileName temp;
//Extracting Application Uid
if( 0 != aCriteria.iHandle.SubSessionHandle())
{
iApaLsSession.AppForDocument( aCriteria.iHandle,appUid,dataType);
cmdLine->SetCommandL( EApaCommandOpen );
cmdLine->SetFileByHandleL( aCriteria.iHandle );
}
else if (0 != aCriteria.iPath.CompareF(KNullDesC) )
{
CAppManagerService::ValidateFilePathL(aCriteria.iPath);
iApaLsSession.AppForDocument( aCriteria.iPath,appUid,dataType);
cmdLine->SetCommandL( EApaCommandOpen );
cmdLine->SetDocumentNameL(aCriteria.iPath );
}
else if ( 0 != aMimeType.CompareF( KNullDesC8 ) )
{
iApaLsSession.AppForDataType(dataType,appUid);
cmdLine->SetCommandL( EApaCommandCreate );
//This is the logic for handling the buffer right now we are not supported as
//underlying S60 classes showing memory leak and pecular behaviour with different
//buffer
/*if( 0 != aOptions.iBuffer.CompareF( KNullDesC8 ) )
{
__UHEAP_MARK;
CDocumentHandler *temp = CDocumentHandler::NewLC();
TRAPD (err, temp->SaveL(aOptions.iBuffer,dataType,KEntryAttNormal) );
temp->GetPath(aFileName);
__UHEAP_MARKEND;
CleanupStack::PopAndDestroy( );
}*/
//left to the launch application for setting
cmdLine->SetDocumentNameL( aFileName );
}
else
{
User::Leave(KErrArgument);
}
//extraction application path
if( KErrNone == iApaLsSession.GetAppInfo( appInfo, appUid) )
{
cmdLine->SetExecutableNameL( appInfo.iFullName );
}
else
{
User::Leave( KErrNotFound );
}
//Set the Launchine Mode
if( 0 == aOptions.iMode.CompareF( KChained ) )
{
SetChainedModeL( cmdLine ,appUid );
}
else if ( 0 != aOptions.iMode.CompareF( KStandalone ) ) //The only other mode is "Standalone"
{
User::Leave(KErrArgument);
}
// Launch the requested Application
TThreadId threadNotUsed;
TRequestStatus requestStatusForRendezvous;
User::LeaveIfError( iApaLsSession.StartApp( *cmdLine,
threadNotUsed,
&requestStatusForRendezvous ));
User::WaitForRequest( requestStatusForRendezvous );
User::LeaveIfError( requestStatusForRendezvous.Int());
CleanupStack::PopAndDestroy( cmdLine );
return threadNotUsed;
}
// -----------------------------------------------------------------------------
// CLauncher::LaunchDocumentL
// This function will parse the application ID string and return the UID
// -----------------------------------------------------------------------------
void CLauncher::ParseAppIdL( const TDesC & aSource ,TUid & aUid )
{
// Icoming string : s60uid://0x101f4d90 , output : 0x101f4d90
if( (aSource.Length() > KScheme.iTypeLength ) &&(0 == aSource.Mid(0,KScheme.iTypeLength).CompareF(KScheme) ) )
{
TChar a('/');
TInt offset = aSource.Locate(a);
TPtrC uiddata;
// To chk for pattern ://
if((0 != aSource.Mid(offset+1,1).Compare(_L("/"))) && (0 != aSource.Mid(offset-1,1).Compare(_L(":"))) )
User::LeaveIfError(KErrArgument);
TPtrC a1(aSource.Mid(offset+1,1));
TPtrC a2(aSource.Mid(offset-1,1));
TInt sourcelen = aSource.Length();
TInt off = offset + KLen;
TInt len = sourcelen -(off) ;
uiddata.Set(aSource.Mid(off,len));
TInt32 uidinint ;
User::LeaveIfError( ConvertHexStringToInt32(uiddata,uidinint) );
aUid.iUid = uidinint;
}
else
{
TUid empt(TUid::Null());
aUid.iUid = empt.iUid;
}
}
// -----------------------------------------------------------------------------
// CLauncher::ConvertHexStringToInt32
// This function will convert the Hax string into TInt32
// -----------------------------------------------------------------------------
TInt CLauncher::ConvertHexStringToInt32(const TDesC& aHexString,TInt32& aInt32 )
{
aInt32 = 0;
TInt pos = aHexString.LocateF( 'x' );
if ( pos == KErrNotFound )
{
pos = 0;
}
else
{
pos++;
}
if( ( aHexString.Length() - pos ) > KDocMaxDigitsInHexString )
{
return KErrArgument; // Error: value too big.
}
TPtrC hexStringPtr( aHexString.Mid( pos ) );
TInt64 value64;
if ( TLex( hexStringPtr ).Val( value64, EHex ) != KErrNone )
{
return KErrArgument; // Error: conversion failed.
}
aInt32 = value64;
return KErrNone;
}
// -----------------------------------------------------------------------------
// CLauncher::SetChainedModeL
// This function will set the application to launch in chained mode
// -----------------------------------------------------------------------------
void CLauncher::SetChainedModeL( CApaCommandLine* aCmdLine , const TUid& aAppUid )
{
CEikonEnv* eikEnv = CEikonEnv::Static();
if( !eikEnv )
{
//Console Based Application can not launch another application in
//chained mode
User::Leave( KErrNotSupported );
}
else
{
RWindowGroup& wg = eikEnv->RootWin();
CEikAppUi* appUi = eikEnv->EikAppUi();
// Window chain the client with the current application
const TInt parentWindowGroupID = wg.Identifier();
if ( parentWindowGroupID )
{
aCmdLine->SetParentWindowGroupID( parentWindowGroupID );
wg.AllowProcessToCreateChildWindowGroups( aAppUid );
}
if ( appUi )
{
appUi->DeactivateActiveViewL();
}
}
}
// -----------------------------------------------------------------------------
// CLauncher::CLauncher
// Constructor
// -----------------------------------------------------------------------------
CLauncher::CLauncher( RApaLsSession& aSession ): iApaLsSession( aSession )
{
}
// -----------------------------------------------------------------------------
// CLauncher::~CLauncher
// Destructor
// -----------------------------------------------------------------------------
CLauncher::~CLauncher( )
{
}