csxhelp/src/AppLauncherForCSXH.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:30:56 +0100
branchRCL_3
changeset 45 cbffe13eac63
parent 0 1f04cf54edd8
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201031 Kit: 201035

/*
* 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:  AppLauncherForCSXH class definition
*
*/


#include "AppLauncherForCSXH.h"
#include "CSXHAppUi.h"
#include <cshelp.rsg>

#include <e32std.h>
#include <apgtask.h>
#include <apgcli.h> 
#include <utf.h>
#include <aknnotewrappers.h> 
#include <AknGlobalNote.h>
#include "csxhconstants.h"
#include <e32std.h> 


const TInt KBackSlashesInPrefix = 3;
#ifndef __SERIES60_30__ 
	const TUid KUidBrowserApplication = { 0x10008D39 };
#else
	const TUid KUidBrowserApplication = { 0x1020724D };
#endif

const TInt KKeyBlockTime = 100000;  

enum TAppLaunchMode
            {
            ENoAppLaunch = 0,   
            EVSAMode = 1,
            ECmdMode = 2,
            EAppLaunchFromInternet = 3,
            };
enum TAppLauchParams
    {
    EParamsInvalid = 0,
    EParamsNoMsg,
    EParamsWithMsg,
    };


AppLauncherForCSXH* AppLauncherForCSXH::NewL()
    {
    AppLauncherForCSXH* self = new(ELeave) AppLauncherForCSXH();
    self->ConstructL();
    return self;
    }

AppLauncherForCSXH::AppLauncherForCSXH()
    {}
    
void AppLauncherForCSXH::ConstructL()
    {
    iTimer = CPeriodic::NewL( CActive::EPriorityStandard ); 
    }
    
AppLauncherForCSXH::~AppLauncherForCSXH()
    {
    if(iTimer)
        delete iTimer;      
    }

// --------------------------------------------------------------------------
// Launches an application based on the Application Launch Link URL
// --------------------------------------------------------------------------
TBool AppLauncherForCSXH::LaunchAppL(const TDesC& aUrl,const TDesC& aCurrentUrl)
    {
    switch(GetAppLaunchModeL(aUrl,aCurrentUrl))
        {
        case ENoAppLaunch:
            return EFalse;
        case EAppLaunchFromInternet:
            HandleAppLauchFromInternetL();
            return ETrue;
        case EVSAMode:
            {
            if(!LaunchApp(aUrl,ETrue))
                HandleFailedAppLauchL();
            return ETrue;
            }
        case ECmdMode:
            {
            if(!LaunchApp(aUrl,EFalse))
                HandleFailedAppLauchL();
            return ETrue;
            }   
        default:
            return EFalse;
        }
    }

TInt AppLauncherForCSXH::GetAppLaunchModeL(const TDesC& aUrl,const TDesC& aCurrentUrl)
    {
    TInt Position = aUrl.Find(_L("app://vsa@localhost/"));
    if(KErrNotFound != Position && 0 == Position)
        {
        return CheckAppLaunchFromInternetL(EVSAMode,aCurrentUrl);
        }
    
    Position = aUrl.Find(_L("app://cmd@localhost/"));
    if(KErrNotFound != Position && 0 == Position)
        {
        return CheckAppLaunchFromInternetL(ECmdMode,aCurrentUrl);
        }
    
    return ENoAppLaunch;    
    }

TBool AppLauncherForCSXH::LaunchApp(const TDesC& aUrl, TBool aVSAMode)
    {
    iParam1.Copy(KEmptyString);
    iParam2.Copy(KEmptyString);
    iParam3.Copy(KEmptyString);
    iParam4.Copy(KEmptyString);
    
    switch(CheckMsgParams(aUrl))
        {
        case EParamsInvalid:
            return EFalse;
        case EParamsNoMsg:
            {
            ExtractTwoParams(aUrl);
            if(aVSAMode)
                {
                TInt32 AId,VId;
                GetUid(iParam1,AId);
                GetUid(iParam2,VId);                
                TRAPD(res,CCSXHAppUi::GetInstance()->AppLaunchL(AId,VId));
                return (res == KErrNone) ? ETrue : EFalse;  
                }
            else
                {
                return LaunchCmdApp(EFalse);
                }
            }
        case EParamsWithMsg:
            {
            ExtractFourParams(aUrl);
            if(aVSAMode)
                {
                TInt32 AId,VId,MId;
                GetUid(iParam1,AId);
                GetUid(iParam2,VId);
                GetUid(iParam3,MId);
                TRAPD(res,CCSXHAppUi::GetInstance()->AppLaunchL(AId,VId,MId,iParam4));
                return (res == KErrNone) ? ETrue : EFalse;  
                }
            else
                {
                return LaunchCmdApp(ETrue);
                }
            }
        default:
            return EFalse;
        }
    }
TBool AppLauncherForCSXH::LaunchCmdApp(TBool aParamsMode)
    {
    TRAPD(res,LaunchCmdAppL(aParamsMode));
    if(res != KErrNone)
        return EFalse;
    return ETrue;
    }
TBool AppLauncherForCSXH::LaunchCmdAppL(TBool aParamsMode)
    {
    /*valid cases
    app://cmd@localhost/APP_NAME/APP_UID
    app://cmd@localhost/APP_NAME/APP_UID/MSG_UID/Parameters
    */
    TApaTask task = GetCmdAppTask();
    if (task.Exists())
        {//App is already running
        if(aParamsMode)
            SendMsgToCmdAppTaskL(task);
        
        task.BringToForeground();
        return ETrue;
        }
    //Application has to be started
    CApaCommandLine* cmdLine=CApaCommandLine::NewLC();
    cmdLine->SetExecutableNameL(iParam1);
    cmdLine->SetCommandL(EApaCommandRun);
    
    RApaLsSession lsSession;
    User::LeaveIfError(lsSession.Connect());
    CleanupClosePushL(lsSession);
    User::LeaveIfError(lsSession.StartApp(*cmdLine));
    CleanupStack::PopAndDestroy(&lsSession);
    CleanupStack::PopAndDestroy(cmdLine);   
    if(aParamsMode)
        {
        iCount = 0; 
        TCallBack timer_Callback_to_terminateApp( Timer_Callback_to_TerminateApp,this );
        StartTimer(timer_Callback_to_terminateApp);    
        }
    
    return ETrue;
    }
    
TInt AppLauncherForCSXH::Timer_Callback_to_TerminateApp(TAny* aPtr)
    {
    return static_cast<AppLauncherForCSXH*>( aPtr )->SendMsgToApplication();
    }
        
TInt AppLauncherForCSXH::SendMsgToApplication()
    {
    //If parameters has to be passed then the following is required
    TApaTask cmdTask = GetCmdAppTask();
    if (cmdTask.Exists())
        {
        TRAPD(res,SendMsgToCmdAppTaskL(cmdTask));       
        if(res != KErrNone)
            return 0;
        cmdTask.BringToForeground();
        iTimer->Cancel();
        }
    else if(++iCount > 20)
        {
        iTimer->Cancel();       
        }
        return 0;       
    }   
        
TApaTask AppLauncherForCSXH::GetCmdAppTask()    
    {
    TInt32 AId;
    GetUid(iParam2,AId);
    TApaTaskList taskList(CCSXHAppUi::GetInstance()->GetWsSession());
    TUid KtestAppUid( TUid::Uid( AId ) ); 
    return taskList.FindApp(KtestAppUid);
    }
void AppLauncherForCSXH::SendMsgToCmdAppTaskL(TApaTask& aTask)
    {
    
    TInt32 MId;
    GetUid(iParam3,MId);
    TUid KtestMsgUid( TUid::Uid( MId ) ); 
    HBufC8* params = CnvUtfConverter::ConvertFromUnicodeToUtf8L(iParam4);
    CleanupStack::PushL(params);
    aTask.SendMessage (KtestMsgUid, *params); 
    CleanupStack::PopAndDestroy(params);
    }
    
void AppLauncherForCSXH::HandleFailedAppLauchL()
    {
    HBufC* ErrorMessage = CCSXHAppUi::GetCoeEnv()->AllocReadResourceLC(
    				R_QTN_HELP_NOTE_UNABLE_TO_LAUNCH_APP);      
    CAknGlobalNote* note = CAknGlobalNote::NewLC();
    note->ShowNoteL(EAknGlobalInformationNote, *ErrorMessage);
    CleanupStack::PopAndDestroy(note); 
    CleanupStack::PopAndDestroy(ErrorMessage); 
    }
void AppLauncherForCSXH::HandleAppLauchFromInternetL()
    {
    HBufC* ErrorMessage = CCSXHAppUi::GetCoeEnv()->AllocReadResourceLC(
    				R_QTN_HELP_NOTE_APP_LAUNCH_NOT_ALLOWED);
    CAknGlobalNote* note = CAknGlobalNote::NewLC();
    note->ShowNoteL(EAknGlobalInformationNote, *ErrorMessage);
    CleanupStack::PopAndDestroy(note); 
    CleanupStack::PopAndDestroy(ErrorMessage);        
    }

TInt AppLauncherForCSXH::CheckAppLaunchFromInternetL(TInt aCurrentMode,const TDesC& /*aCurrentUrl*/ )
    {
       
    return aCurrentMode; 
    //BrowserNG is lauched for Externalhyperlinks, 
    //All the security issues are addresed by BrowserNG,    
    
    /*(0 == aCurrentUrl.Find(KFileUrlPrefix) ) ? 
                    aCurrentMode : EAppLaunchFromInternet;*/
    }

TInt AppLauncherForCSXH::CheckMsgParams(const TDesC& aUrl)
    {
    /*
    The following are valid cases
    app://vsa@localhost/APP_UID/VIEW_UID
    app://vsa@localhost/APP_UID/VIEW_UID/MSG_UID/Parameters
    app://cmd@localhost/APP_NAME/APP_UID
    app://cmd@localhost/APP_NAME/APP_UID/MSG_UID/Parameters
    
    That is, it should have exactly 4 backslashes or 
    >= 6 backslashes (considering the possibility that parameters
    can have embedded backslashes)
    */
    TBuf<KBackSlashLength> backSlash(KBackSlash);
    TInt count = 0;
    
    for(TInt i = 0 ; i < aUrl.Length() ; ++i)
        {
        if(KErrNotFound != backSlash.Find(&aUrl[i],KBackSlashLength))
            ++count;
        }
    
    if(count == 4)
        return EParamsNoMsg;
    else if (count >=6)
        return EParamsWithMsg;
    else    
        return EParamsInvalid;
    }

void AppLauncherForCSXH::ExtractTwoParams(const TDesC& aUrl)
    {
    /*Will be called for the following cases
    app://vsa@localhost/APP_UID/VIEW_UID
    app://cmd@localhost/APP_NAME/APP_UID
    */
    iParam1.Copy(KEmptyString);
    iParam2.Copy(KEmptyString);
    
    TBuf<KBackSlashLength> backSlash(KBackSlash);
    TInt count = 0;
    TInt pos;
    
    for(pos = 0; pos < aUrl.Length() ; ++pos)
        {
        if(KErrNotFound != backSlash.Find(&aUrl[pos],KBackSlashLength))
            ++count;
        if(count == KBackSlashesInPrefix)
            break;
        }
    TPtrC16 url = aUrl.Mid(pos + 1);
    pos = url.Find(KBackSlash);
    iParam1 = url.Left(pos);
    iParam2 = url.Mid(pos + 1);
    }

void AppLauncherForCSXH::ExtractFourParams(const TDesC& aUrl)
    {
    /*Will be called for the following cases
    app://vsa@localhost/APP_UID/VIEW_UID/MSG_UID/Parameters
    app://cmd@localhost/APP_NAME/APP_UID/MSG_UID/Parameters
    */
    iParam1.Copy(KEmptyString);
    iParam2.Copy(KEmptyString);
    iParam3.Copy(KEmptyString);
    iParam4.Copy(KEmptyString);
    
    TBuf<KBackSlashLength> backSlash(KBackSlash);
    TInt count = 0;
    TInt pos;
    
    for(pos = 0; pos < aUrl.Length() ; ++pos)
        {
        if(KErrNotFound != backSlash.Find(&aUrl[pos],KBackSlashLength))
            ++count;
        if(count == KBackSlashesInPrefix)
            break;
        }
        
    TPtrC16 url = aUrl.Mid(pos + 1);
    pos = url.Find(KBackSlash);
    iParam1 = url.Left(pos);
    
    TPtrC16 url2 = url.Mid(pos + 1);
    pos = url2.Find(KBackSlash);
    iParam2 = url2.Left(pos);

    TPtrC16 url3 = url2.Mid(pos + 1);
    pos = url3.Find(KBackSlash);
    iParam3 = url3.Left(pos);
    
    iParam4 = url3.Mid(pos+1);
    }

void AppLauncherForCSXH::GetUid(TPtrC aUid, TInt32& aResult)
    {
    TInt hexPos = aUid.Find(_L("x"));
    if(KErrNotFound == hexPos)
        TLex(aUid).Val(aResult); 
    else
        {       
        TPtrC16 uidt = aUid.Mid(hexPos+1);
        TInt64 res;
        //During this operation sometimes values exceed TInt32, but the end result is always
        //fits into TInt32
        TLex(uidt).Val(res,EHex); 
        aResult = res;
        }
    }

void AppLauncherForCSXH::LaunchBrowserNGL(const TDesC& aUrl)
    {    
    _LIT( KBrowserCmdFetchUrl, "4 " );
    HBufC* param = HBufC::NewLC( KBrowserCmdFetchUrl().Length() + 
                                 aUrl.Length() );
	TPtr paramPtr = param->Des();
    paramPtr.Copy( KBrowserCmdFetchUrl );
    paramPtr.Append( aUrl );
    
    if(!SendMsgToBrowserNGL(param))
	    {    
		RApaLsSession appArcSession;
	    User::LeaveIfError( appArcSession.Connect() );
	    CleanupClosePushL<RApaLsSession>( appArcSession );
	    
	    TThreadId id;
	    User::LeaveIfError
	        (
	            appArcSession.StartDocument(*param,KUidBrowserApplication,id )
	        );
	    CleanupStack::PopAndDestroy( &appArcSession );
	    }
	    
	CleanupStack::PopAndDestroy( param );
    }
    
TBool AppLauncherForCSXH::SendMsgToBrowserNGL(const HBufC* aUrl)
    {
    TApaTaskList taskList(CCSXHAppUi::GetInstance()->GetWsSession());
    TApaTask task = taskList.FindApp(KUidBrowserApplication);       
    if(task.Exists())
        {   
        // 8-bit buffer is required.
        HBufC8* param8 = HBufC8::NewLC( aUrl->Length() );
        param8->Des().Copy( *aUrl );
        task.SendMessage( TUid::Uid( 0 ), *param8 ); // Uid is not used
        CleanupStack::PopAndDestroy( param8 );
        return ETrue;           
        }
    else
        return EFalse;
    }
    
void AppLauncherForCSXH::StartTimer(TCallBack aCallBack)
    {
    if( iTimer->IsActive() )
        {
            iTimer->Cancel();
        }

    iTimer->Start(
        TTimeIntervalMicroSeconds32( KKeyBlockTime ),
        TTimeIntervalMicroSeconds32( KKeyBlockTime ),
        aCallBack );
    }