locationcentre/lcutils/src/lcapplauncher.cpp
changeset 0 522cd55cc3d7
child 6 91123d004e8f
--- /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
+