--- /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 <apgcli.h>
+#include <apgtask.h>
+#include <eikenv.h>
+#include <lcappexitobserver.h>
+#include <SchemeHandler.h>
+#include <documenthandler.h>
+#include <e32math.h>
+#include <eikappui.h>
+#include <avkon.hrh>
+
+// 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
+