diff -r 000000000000 -r 522cd55cc3d7 locationcentre/lcutils/src/lcapplauncher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/locationcentre/lcutils/src/lcapplauncher.cpp Tue Feb 02 00:16:03 2010 +0200 @@ -0,0 +1,600 @@ +/* +* Copyright (c) 2007 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: Utility class which provides the Application, Service and File +* launching services to Location Centre. +* +*/ + + +// SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// USER INCLUDES +#include "lcapplauncher.h" +#include "lcipcparams.h" +#include "lcdebug.h" + +// CONSTANT DEFINITIONS +_LIT( KLcFourSpace, "4 " ); + +// Maximum value that the UID field can take in S60 +const TUint32 KUidMaxValue = 0xFFFFFFFF; + +// Application Server Service ID. This is the same valuw which AknAppService classes use +const TUid KLcLaunchAppServiceUid = { 0x101F887A }; + +// -------- Member functions of RLcLaunchAppService -------------------------- + +// --------------------------------------------------------- +// TUid RLcLaunchAppService::ServiceUid +// --------------------------------------------------------- +// +TUid RLcLaunchAppService::ServiceUid() const + { + return KLcLaunchAppServiceUid; + } + +// -------- Member functions of CLcLaunchAppService -------------------------- + +// --------------------------------------------------------------------------- +// CLcLaunchAppService* CLcLaunchAppService::NewL +// --------------------------------------------------------------------------- +// +CLcLaunchAppService* CLcLaunchAppService::NewL() + { + CLcLaunchAppService* self = new ( ELeave ) CLcLaunchAppService(); + return self; + } + +// --------------------------------------------------------------------------- +// CLcLaunchAppService::~CLcLaunchAppService +// --------------------------------------------------------------------------- +// +CLcLaunchAppService::~CLcLaunchAppService() + { + delete iMonitor; + iService.Close(); + } + +// --------------------------------------------------------------------------- +// Tvoid CLcLaunchAppService::ServerName +// --------------------------------------------------------------------------- +// +void CLcLaunchAppService::ServerName( TName& aServerName, + TUid aAppServerUid, + TUint aServerDifferentiator ) + { + _LIT(KServerNameFormat, "%08x_%08x_AppServer"); + aServerName.Format( KServerNameFormat, + aServerDifferentiator, + aAppServerUid ); + } + +// --------------------------------------------------------------------------- +// TUid RLcLaunchAppService::ServiceUid +// --------------------------------------------------------------------------- +// +TUint CLcLaunchAppService::GenerateServerDifferentiatorAndName( + TName& aServerName, + TUid aAppServerUid ) + { + TUint r; + FOREVER + { + r = Math::Random(); + if ( r == 0 ) + continue; + ServerName( aServerName, aAppServerUid, r ); + TFindServer find( aServerName ); + TFullName fullName; + if ( find.Next( fullName ) == KErrNone ) + { + continue; + } + break; + } + return r; + } + +// --------------------------------------------------------------------------- +// void CLcLaunchAppService::LaunchAppL +// --------------------------------------------------------------------------- +// +void CLcLaunchAppService::LaunchAppL( const TUid& aAppUid, + MAknServerAppExitObserver& aObserver, + const TDesC& aCmdLineArg ) + { + DEBUG("+ CLcLaunchAppService::LaunchAppL") + + CEikonEnv* eikEnv = CEikonEnv::Static(); + RWindowGroup& wg = eikEnv->RootWin(); + + TName notUsed; + const TUint differentiator = GenerateServerDifferentiatorAndName( notUsed, aAppUid ); + TRequestStatus requestStatusForRendezvous; + + RApaLsSession apa; + User::LeaveIfError( apa.Connect()); + CleanupClosePushL( apa ); + + // Check for the Application capabilities + TApaAppCapabilityBuf capabilityBuf; + User::LeaveIfError( apa.GetAppCapability( capabilityBuf, aAppUid )); + TApaAppCapability& caps = capabilityBuf(); + + // Launch only those applications can be embedded and will not be run the background + + if( caps.iLaunchInBackground || + caps.iEmbeddability == TApaAppCapability::ENotEmbeddable ) + { + User::Leave( KErrNotSupported ); + } + + TApaAppInfo info; + User::LeaveIfError( apa.GetAppInfo( info, aAppUid )); + + // Pack the command line arguments + CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); + cmdLine->SetExecutableNameL(info.iFullName); + cmdLine->SetServerRequiredL(differentiator); + + // Set the Command line arguments. + if ( aCmdLineArg.Length()) + { + // These arguments would be sent as Tail end arguments to the launched + // Application. Its left to the application to handle those + HBufC8* tailEnd = HBufC8::NewLC( aCmdLineArg.Length()); + tailEnd->Des().Copy( aCmdLineArg ); + + // The Tail end buffer is copied to the Command line structure. Hence, + // can delete this variable after the set operation succeeds. + cmdLine->SetTailEndL( tailEnd->Des()); + + CleanupStack::PopAndDestroy( tailEnd ); + } + + cmdLine->SetCommandL( EApaCommandRun ); + + // Window chain the client with the current application + const TInt parentWindowGroupID = wg.Identifier(); + if ( parentWindowGroupID ) + { + cmdLine->SetParentWindowGroupID( parentWindowGroupID ); + wg.AllowProcessToCreateChildWindowGroups( aAppUid ); + } + + // Launch the requested Application + TThreadId threadNotUsed; + User::LeaveIfError( apa.StartApp( *cmdLine, + threadNotUsed, + &requestStatusForRendezvous )); + + CleanupStack::PopAndDestroy(2, &apa); // cmdLine and apa + + CEikAppUi* appUi = eikEnv->EikAppUi(); + if ( appUi ) + { + appUi->DeactivateActiveViewL(); + } + + User::WaitForRequest( requestStatusForRendezvous ); + User::LeaveIfError( requestStatusForRendezvous.Int()); + + // Establish a connection to the running server + TName serverName; + ServerName( serverName, aAppUid, differentiator ); + + // Though the server had been successfully created the application + // has can shutdown before we can establish a connection. There is nothing + // that we can do here. Ignore the error. + iService.ConnectExistingByNameL(serverName ); + + // Set the observer for receiving notifications of the application exit. + iMonitor = CApaServerAppExitMonitor::NewL( iService, + aObserver, + CActive::EPriorityStandard ); + + DEBUG("- CLcLaunchAppService::LaunchAppL") + } + + +// ----- Member funtions for CLcAppLauncher ---------------------------------- + +// --------------------------------------------------------------------------- +// CLcAppLauncher::CLcAppLauncher +// --------------------------------------------------------------------------- +// +CLcAppLauncher::CLcAppLauncher() + { + // C++ Default constructor. No allocations or functions which can Leave + // should be called from here. + } + +// --------------------------------------------------------------------------- +// CLcAppLauncher::~CLcAppLauncher +// --------------------------------------------------------------------------- +// +CLcAppLauncher::~CLcAppLauncher() + { + + // Delete the Broswer launcher. + delete iBrowserLauncher; + + // Delete the document handler. + delete iDocHandler; + + // Delete the Application Service if it exists + delete iAppService; + } + +// --------------------------------------------------------------------------- +// CLcAppLauncher* CLcAppLauncher::NewL +// --------------------------------------------------------------------------- +// +EXPORT_C CLcAppLauncher* CLcAppLauncher::NewL() + { + CLcAppLauncher* self = NewLC(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CLcAppLauncher* CLcAppLauncher::NewLC +// --------------------------------------------------------------------------- +// +EXPORT_C CLcAppLauncher* CLcAppLauncher::NewLC() + { + // Symbian Two phased constructor. Leaves the object on the Clean-up + // stack. + CLcAppLauncher* self = new ( ELeave ) CLcAppLauncher(); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + +// --------------------------------------------------------------------------- +// void CLcAppLauncher::ConstructL +// --------------------------------------------------------------------------- +// +void CLcAppLauncher::ConstructL() + { + // Second phase of the two phase constructor. + iEnv = CEikonEnv::Static(); + } + +// --------------------------------------------------------------------------- +// void LcAppLauncher::LaunchLocationApplicationL +// --------------------------------------------------------------------------- +// +EXPORT_C void CLcAppLauncher::LaunchLocationApplicationL( + TInt aAppType, + const TDesC& aIdentifer, + TBool aStandAlone, + const TDesC& aCmdLineArg, + MLcAppExitObserver* aExitObserver ) + { + DEBUG("+ CLcLaunchAppService::LaunchLocationApplicationL") + + // Check for the validity of the request + + // Check if there is an outstanding Embedded launch request + if(( isEmbeddedLaunchOutstanding && !aStandAlone ) || + ( !aStandAlone && !iEnv )) + { + User::Leave( KErrNotSupported ); + } + + // At any instant of time this class can one outstanding Exit observer. + // There is currently no provision of storing a list of observers and + // mapping them correspondingly to each of the assciated applications + // Hence, Leave if there exists an Exit observer. + if (( aExitObserver && iExitObserver )) + { + User::Leave( KErrAlreadyExists ); + } + + // Launch the Applications based on their type and Mode of launching + switch ( aAppType ) + { + case ELcNativeApplication: + { + // Since the request is for a Native S60 application, the Identifer + // contains an UID. Obtain it using Lexer + TLex lexer( aIdentifer ); + TUint32 uidValue; + + User::LeaveIfError( lexer.BoundedVal( uidValue, EHex, KUidMaxValue )); + + if ( aStandAlone ) + { + // Launch the Location based Application based standalone mode + LaunchAppL( TUid::Uid( uidValue ), aCmdLineArg ); + } + else + { + // Launch Application in the chained mode + LaunchAppAsChainedL( TUid::Uid( uidValue ), aCmdLineArg, aExitObserver ); + } + + break; + } + case ELcWebUrl: + { + LaunchWebBroserL( aIdentifer, aStandAlone, aExitObserver ); + break; + } + case ELcDocument: + { + LaunchContentL( aIdentifer, aStandAlone, aExitObserver ); + break; + } + default: + { + User::Leave( KErrNotSupported ); + break; + } + } + + DEBUG("+ CLcLaunchAppService::LaunchLocationApplicationL") + } + +// --------------------------------------------------------------------------- +// void LcAppLauncher::LaunchAppL +// --------------------------------------------------------------------------- +// +void CLcAppLauncher::LaunchAppL( + TUid aApplicationUid, + const TDesC& aCmdLineArg ) + { + DEBUG("+ CLcAppLauncher::LaunchAppL") + + // Create the Session handle and connect to the Application architecture + // server. This is required to obtain the details of the application from + // the Application UID. + RApaLsSession lsSession; + User::LeaveIfError( lsSession.Connect() ); + CleanupClosePushL( lsSession ); + + // Get the Application's capability. + TApaAppCapabilityBuf capabilityBuf; + User::LeaveIfError( lsSession.GetAppCapability( capabilityBuf, aApplicationUid )); + TApaAppCapability& caps = capabilityBuf(); + + if ( caps.iEmbeddability == TApaAppCapability::EEmbeddableOnly || + caps.iEmbeddability == TApaAppCapability::EEmbeddableUiNotStandAlone ) + { + User::Leave( KErrNotSupported ); + } + + // Get the Application Information. + TApaAppInfo appInfo; + User::LeaveIfError( lsSession.GetAppInfo( appInfo, aApplicationUid ) ); + + // Fill the command line argument structure + CApaCommandLine* cmdLine = CApaCommandLine::NewLC(); + + // Set the Application name. + TFileName appName = appInfo.iFullName; + cmdLine->SetExecutableNameL( appName ); + + // Set the Command + if ( caps.iLaunchInBackground ) + { + cmdLine->SetCommandL( EApaCommandBackground ); + } + else + { + cmdLine->SetCommandL( EApaCommandRun ); + } + + // Set the Command line arguments. + if ( aCmdLineArg.Length()) + { + // These arguments would be sent as Tail end arguments to the launched + // Application. Its left to the application to handle those + HBufC8* tailEnd = HBufC8::NewLC( aCmdLineArg.Length()); + tailEnd->Des().Copy( aCmdLineArg ); + + // The Tail end buffer is copied to the Command line structure. Hence, + // can delete this variable after the set operation succeeds. + cmdLine->SetTailEndL( tailEnd->Des()); + + CleanupStack::PopAndDestroy( tailEnd ); + } + + // Start the Application + User::LeaveIfError( lsSession.StartApp( *cmdLine )); + + // Clean up all the allocated heap variables. + CleanupStack::PopAndDestroy( cmdLine ); + CleanupStack::PopAndDestroy(); //lsSession + + DEBUG("- CLcAppLauncher::LaunchAppL") + } + +// --------------------------------------------------------------------------- +// void LcAppLauncher::LaunchAppAsChainedL +// --------------------------------------------------------------------------- +// +void CLcAppLauncher::LaunchAppAsChainedL( + TUid aApplicationUid, + const TDesC& aCmdLineArg, + MLcAppExitObserver* aExitObserver ) + { + DEBUG("+ CLcAppLauncher::LaunchAppAsChainedL" ) + + // Createt the App service object and launch the application + CLcLaunchAppService* appService = CLcLaunchAppService::NewL(); + CleanupStack::PushL( appService ); + appService->LaunchAppL( aApplicationUid, *this, aCmdLineArg ); + CleanupStack::Pop( appService ); + + // Transfer the ownership to this class. + iAppService = appService; + isEmbeddedLaunchOutstanding = ETrue; + + // Store the Observer for future reference + iExitObserver = aExitObserver; + + DEBUG("- CLcAppLauncher::LaunchAppAsChainedL" ) + } + +// --------------------------------------------------------------------------- +// void LcAppLauncher::LaunchWebBroserL +// --------------------------------------------------------------------------- +// +void CLcAppLauncher::LaunchWebBroserL( const TDesC& aUrl, + TBool aStandAlone, + MLcAppExitObserver* aObserver ) + { + // The parameters need to be packed in the order specified by the browser. + // Parameters are separated by space + // 1st parameter: Type of the second parameter. In this case 4 to indicate + // that the second parameter is a URL. + // 2nd parameter: URL that needs to be launched in the browser. + // Since we have to pack "4 " before the URL name, the total length of + // the parameter string should be Length of the URL + 2. + HBufC* param = HBufC::NewLC(( 2 + aUrl.Length())); + param->Des().Append( KLcFourSpace ); + param->Des().Append( aUrl ); + + if ( aStandAlone ) + { + // The URL is launched in the Browser. Set the Browser UID as the UID + // of the application which needs to be launched. + const TInt KBrowserUid = 0x10008D39; + TUid id( TUid::Uid( KBrowserUid ) ); + + // Check if the Browser application is already running. Incase its + // running Open this URL in the browser. + TApaTaskList taskList( CEikonEnv::Static()->WsSession() ); + TApaTask task = taskList.FindApp( id ); + if ( task.Exists() ) + { + // The browser is running. Launch the URL. + HBufC8* param8 = HBufC8::NewLC( param->Length() ); + param8->Des().Append( *param ); + task.SendMessage( TUid::Uid( 0 ), *param8 ); // UID is not used + CleanupStack::PopAndDestroy(); + } + else + { + // The browser is not running. Start the browser application with + // the specified parameter. This is done by launching the browser with + // a document name as the URL. + RApaLsSession appArcSession; + + // Connect to the Application architecture server. + User::LeaveIfError( appArcSession.Connect()); + CleanupClosePushL( appArcSession ); + TThreadId id; + + // Start the browser with the URL + User::LeaveIfError( appArcSession.StartDocument( *param, + TUid::Uid( KBrowserUid ), + id )); + CleanupStack::PopAndDestroy( &appArcSession ); + } + } + else + { + + if ( !iBrowserLauncher ) + { + // Create the Browser instance + iBrowserLauncher = CSchemeHandler::NewL( aUrl ); + } + + // Launch the Web URL in a browser in the Embedded mode. + iBrowserLauncher->HandleUrlEmbeddedL(); + iBrowserLauncher->Observer( this ); + + // Set the Observer incase we need to notify the termination of the + // browser + aObserver ? ( iExitObserver = aObserver ) : NULL; + + isEmbeddedLaunchOutstanding = ETrue; + } + CleanupStack::PopAndDestroy( param ); // param + + } + +// --------------------------------------------------------------------------- +// void LcAppLauncher::LaunchContentL +// --------------------------------------------------------------------------- +// +void CLcAppLauncher::LaunchContentL( const TDesC& aFileName, + TBool aStandAlone, + MLcAppExitObserver* aObserver ) + { + if ( !iDocHandler ) + { + iDocHandler = CDocumentHandler::NewL(); + iDocHandler->SetExitObserver( this ); + } + + TDataType dataType; + if ( aStandAlone ) + { + // The return values are ignored since, the User Cancelling the event doesnt + // make any difference to the Client Application + User::LeaveIfError( iDocHandler->OpenFileL( aFileName, dataType )); + } + else + { + iExitObserver = aObserver; + // The return values are ignored since, the User Cancelling the event doesnt + // make any difference to the Client Application + User::LeaveIfError( iDocHandler->OpenFileEmbeddedL( aFileName, dataType )); + + isEmbeddedLaunchOutstanding = ETrue; + } + } + +// --------------------------------------------------------------------------- +// void LcAppLauncher::HandleServerAppExit +// --------------------------------------------------------------------------- +// +void CLcAppLauncher::HandleServerAppExit( TInt aReason ) + { + isEmbeddedLaunchOutstanding = EFalse; + + // Delete the App Service + delete iAppService; + iAppService = NULL; + + MLcAppExitObserver* observer = iExitObserver; + if ( observer ) + { + // Once the request has been issued we can NULLify the observer. Nullifying + // it before the actual callback to faciliate the launching of another app + // with an exit observer when the call is executed. + iExitObserver = NULL; + + TRAP_IGNORE( observer->HandleChainedLocationAppExitL( aReason )); + } + + MAknServerAppExitObserver::HandleServerAppExit( aReason ); + } + +// End of File +