locationmanager/ReverseGeocode/src/clientengine.cpp
branchRCL_3
changeset 19 b73252188534
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/locationmanager/ReverseGeocode/src/clientengine.cpp	Thu Aug 19 10:20:41 2010 +0300
@@ -0,0 +1,673 @@
+/*
+* Copyright (c) 2006-2009 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: Implementation of HTTP Client Engine.
+*/
+
+//Symbian headers
+#include <http.h>
+#include <commdbconnpref.h>
+#include <connpref.h>
+#include <extendedconnpref.h>
+#include <commdb.h>
+#include <etel3rdparty.h>                // voice call notification
+#include <mmtsy_names.h>                 // kmmtsymodulename
+#include "locationmanagerdebug.h"
+#include "clientengine.h"
+
+// Used user agent for requests
+_LIT8(KUserAgent, "SimpleClient 1.0");
+
+// This client accepts all content types.
+_LIT8(KAccept, "*/*");
+
+// ----------------------------------------------------------------------------
+// CClientEngine::NewL()
+// ----------------------------------------------------------------------------
+CClientEngine* CClientEngine::NewL( MClientObserver& aObserver)
+    {
+    LOG("CClientEngine::NewL ,begin");
+    CClientEngine* self = CClientEngine::NewLC( aObserver);
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::NewLC()
+// ----------------------------------------------------------------------------
+CClientEngine* CClientEngine::NewLC(MClientObserver& aObserver)
+    {
+    LOG("CClientEngine::NewLC ,begin");
+    CClientEngine* self = new ( ELeave ) CClientEngine( aObserver);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::CClientEngine()
+// ----------------------------------------------------------------------------
+CClientEngine::CClientEngine( MClientObserver& aObserver): 
+                                CActive( CActive::EPriorityStandard ),
+                                iObserver( aObserver ),
+                                iConnectionSetupDone( EFalse ),
+                                iPrevProfileId( -1 ),
+                                iMobility(NULL),
+                                iTransactionOpen( EFalse ),
+                                iUri(NULL)
+    {
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::~CClientEngine()
+// ----------------------------------------------------------------------------
+CClientEngine::~CClientEngine()
+    {
+    LOG("CClientEngine::~CClientEngine ,begin");
+    Cancel();
+
+    if ( iTransactionOpen )
+        {
+        iTransaction.Close();
+        iTransactionOpen = EFalse;
+        }
+    
+    if ( iMobility )
+        {
+        iMobility->Cancel();
+        }
+    delete iMobility;
+    iMobility = NULL;
+    
+    if(iConnectionSetupDone)
+        {
+        iSession.Close();
+        iConnection.Close();
+        iSocketServ.Close();
+        }
+    delete iUri;
+    iUri = NULL;
+   
+	iCmManager.Close();
+
+    
+    // DON'T cose RMobilePhone object
+
+	LOG("CClientEngine::~CClientEngine ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::ConstructL()
+// ----------------------------------------------------------------------------
+void CClientEngine::ConstructL()
+  {
+  LOG("CClientEngine::ConstructL ,begin");
+  CActiveScheduler::Add(this);
+  iCmManager.OpenL();
+  LOG("CClientEngine::ConstructL ,end");
+  }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::CloseConnection()
+// ----------------------------------------------------------------------------
+void CClientEngine::CloseConnection()
+    {
+    LOG("CClientEngine::CloseConnection ,begin" );
+    if ( iTransactionOpen )
+        {
+        iTransaction.Close();
+        iTransactionOpen = EFalse;
+        }
+    
+    if ( iMobility )
+        {
+		iMobility->Cancel();
+		delete iMobility;
+		iMobility = NULL;
+        }
+
+    if(iConnectionSetupDone)
+        { 
+        iSession.Close();
+        iConnection.Close();
+        iSocketServ.Close();  
+           
+        iConnectionSetupDone = EFalse;
+        }
+	LOG("CClientEngine::CloseConnection ,end");
+    }
+
+
+// ----------------------------------------------------------------------------
+// CClientEngine::IsVisitorNetwork()
+// ----------------------------------------------------------------------------
+TBool CClientEngine::IsVisitorNetwork(const TMobileRoamingStatus& aRegNetworkStatus) const
+    {
+    LOG1("CClientEngine::IsVisitorNetwork. reg network status - %d",
+			(TInt) aRegNetworkStatus);
+        
+    return (aRegNetworkStatus == EMobileNationalRoaming ||
+        aRegNetworkStatus== EMobileInternationalRoaming);
+    
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::IsWlanOnly()
+// ----------------------------------------------------------------------------
+TBool CClientEngine::IsWlanOnly(const TMobileRoamingStatus& aRoamingStatus,
+                                const TCmGenConnSettings& aGenConnSettings) const
+    {
+    LOG1("CClientEngine::IsVisitorNetwork. reg network status - %d",(TInt) aRoamingStatus);
+    TBool wlanOnlyFlag = EFalse;
+    switch(aRoamingStatus)
+        {
+        case EMobileRegHomeNetwork:
+            LOG("Home network");
+            wlanOnlyFlag = (aGenConnSettings.iCellularDataUsageHome == ECmCellularDataUsageDisabled);
+            break;
+        case EMobileNationalRoaming:
+        case EMobileInternationalRoaming:
+            LOG("Visitor network");
+            wlanOnlyFlag = (aGenConnSettings.iCellularDataUsageVisitor == ECmCellularDataUsageDisabled);
+            break;
+        default:
+            break;
+        } // end of switch
+    LOG1("Wlan only flag - %d", wlanOnlyFlag ? 1 : 0);
+    return wlanOnlyFlag;
+    }
+
+
+// ----------------------------------------------------------------------------
+// CClientEngine::UeRegNetworkStatus()
+// ----------------------------------------------------------------------------
+TMobileRoamingStatus CClientEngine::UeRegNetworkStatus()
+    {
+    LOG("CClientEngine::UeRegNetworkStatus() ,begin");
+    TMobileRoamingStatus roamingStatus = EMobileNotRegistered;
+    if(iObserver.IsRegisteredAtHomeNetwork())
+        {
+        // home network.
+        roamingStatus = EMobileRegHomeNetwork;
+        LOG("UE registered in home network");
+        }
+    else
+        {
+        // roaming network
+        TBool homeNwInfoAvailableFlag = EFalse;
+        const RMobilePhone::TMobilePhoneNetworkInfoV1& homeNwInfo = 
+            iObserver.GetHomeNetworkInfo(homeNwInfoAvailableFlag);
+        if(homeNwInfoAvailableFlag)
+            {
+            RMobilePhone::TMobilePhoneNetworkCountryCode countryCode = 
+                        iObserver.GetCurrentRegisterNw().iCountryCode;
+            if(countryCode.Compare(homeNwInfo.iCountryCode) == 0)
+                {
+                // national roaming..
+                LOG("UE is in nation roaming");
+                roamingStatus = EMobileNationalRoaming;
+                }
+            else
+                {
+                // international roaming.
+                LOG("UE is in international roaming");
+                roamingStatus = EMobileInternationalRoaming;
+                }
+            }                
+        }
+    if(roamingStatus == EMobileNotRegistered)
+        {
+        LOG("UE is not registered with the network. Offline mode.");
+        }
+	LOG("CClientEngine::UeRegNetworkStatus ,end");
+    return roamingStatus;
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::IsDataConnectionAskAlwaysL()
+// ----------------------------------------------------------------------------
+TBool CClientEngine::IsDataConnectionAskAlwaysL() 
+    {
+    LOG("CClientEngine::IsDataConnectionAskAlwaysL ,begin");
+    TMobileRoamingStatus roamingStatus = UeRegNetworkStatus();
+        
+	TCmGenConnSettings genConnSettings;
+    TBool retVal = EFalse;
+	iCmManager.ReadGenConnSettingsL(genConnSettings);
+
+    LOG1("wlan usage - %d", genConnSettings.iUsageOfWlan);
+    LOG1("Home usage - %d", genConnSettings.iCellularDataUsageHome);
+    LOG1("Visitor usage - %d", genConnSettings.iCellularDataUsageVisitor);
+    
+	if((IsWlanOnly(roamingStatus, genConnSettings) && genConnSettings.iUsageOfWlan == ECmUsageOfWlanManual) // wlan
+		|| (roamingStatus == EMobileRegHomeNetwork &&  // home
+        		genConnSettings.iCellularDataUsageHome == ECmCellularDataUsageConfirm)
+		|| (IsVisitorNetwork(roamingStatus) &&  // roaming
+    		 genConnSettings.iCellularDataUsageVisitor == ECmCellularDataUsageConfirm)
+		)
+		{
+		retVal = ETrue;
+		}
+	LOG("CClientEngine::IsDataConnectionAskAlwaysL ,end");
+	return retVal;
+	}
+
+// ----------------------------------------------------------------------------
+// CClientEngine::SetupConnectionL()
+// ----------------------------------------------------------------------------
+void CClientEngine::SetupConnectionL( const TConnectionOption aOption )
+    {
+	LOG("CClientEngine::SetupConnectionL ,begin");
+	if ( aOption == ESilent && IsDataConnectionAskAlwaysL())
+		{
+		LOG("Silent mode. connection setup is asked always.");
+        if ( iConnectionSetupDone )
+            {
+            LOG("Already connected. Close the connection\n");
+            CloseConnection();
+            }
+		User::Leave(KErrNotSupported);
+		}
+    if ( iConnectionSetupDone )
+        {
+        // Connection setup is done
+        LOG("Already connected.\n");
+        User::Leave(KErrAlreadyExists);
+        }
+ 
+	
+    LOG1("SetupConnectionL: connection option: %d\n", aOption );
+       
+    // Open HTTP Session
+    iSession.OpenL();
+    User::LeaveIfError(iSocketServ.Connect());
+    User::LeaveIfError(iConnection.Open(iSocketServ));
+    
+    if ( aOption == ESilent )
+        {
+        // Create overrides
+        TConnPrefList prefList;
+        TExtendedConnPref prefs;
+        prefs.SetSnapPurpose( CMManager::ESnapPurposeInternet );
+        prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent );
+        prefList.AppendL( &prefs );
+        
+        iConnection.Start(prefList, iStatus);
+        }
+    else
+        {
+        iConnection.Start( iStatus );
+        }
+   
+    
+    SetActive();
+	LOG("CClientEngine::SetupConnectionL ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::SetHeaderL()
+// ----------------------------------------------------------------------------
+void CClientEngine::SetHeaderL( RHTTPHeaders aHeaders, TInt aHdrField, const TDesC8& aHdrValue )
+    {
+    LOG("CClientEngine::SetHeaderL ,begin");
+    RStringF valStr = iSession.StringPool().OpenFStringL( aHdrValue );
+    CleanupClosePushL( valStr );
+    THTTPHdrVal val(valStr);
+    aHeaders.SetFieldL( iSession.StringPool().StringF( aHdrField, RHTTPSession::GetTable()), val);
+    CleanupStack::PopAndDestroy();  // valStr
+    LOG("CClientEngine::SetHeaderL ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::IssueHTTPGetL()
+// ----------------------------------------------------------------------------
+void CClientEngine::IssueHTTPGetL( const TDesC8& aUri, const TConnectionOption aOption )
+    {
+    LOG("CClientEngine::IssueHTTPGetL ,begin");
+    if ( IsActive() )
+        {
+        // If there is some request in pending state
+        // return with out further processing
+        // Should we leave here !?
+        LOG("Client engine is already active");
+        return;
+        }
+    
+    delete iUri;
+    iUri = NULL;
+
+    iUri = aUri.AllocL();
+
+    // Create HTTP connection
+    TRAPD( err, SetupConnectionL( aOption ) );
+    //If the Err is KErrNone, It will lead to RunL and
+    //hence jump to the DoHTTPGetL() from there.
+    
+    if( err == KErrAlreadyExists )
+        {
+        DoHTTPGetL();
+        }
+    else if( err != KErrNone )
+        {
+        LOG("Connection failure. Leaving.");
+        iObserver.ClientEvent( EHttpConnectionFailure );
+        User::Leave(err);
+        }
+    iEngineState = EGet;
+ 	LOG("CClientEngine::IssueHTTPGetL ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::DoHTTPGetL()
+// ----------------------------------------------------------------------------
+void CClientEngine::DoHTTPGetL()
+    {
+    LOG("CClientEngine::DoHTTPGetL ,begin");
+    // Parse string to URI (as defined in RFC2396)
+    TUriParser8 uri;
+    uri.Parse( *iUri );
+    
+    // Get request method string for HTTP GET
+    RStringF method = iSession.StringPool().StringF( HTTP::EGET,RHTTPSession::GetTable() );
+    
+    // Open transaction with previous method and parsed uri. This class will
+    // receive transaction events in MHFRunL and MHFRunError.
+    iTransaction = iSession.OpenTransactionL( uri, *this, method );
+    iTransactionOpen = ETrue;
+    
+    // Set headers for request; user agent and accepted content type
+    RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
+    SetHeaderL( hdr, HTTP::EUserAgent, KUserAgent );
+    SetHeaderL( hdr, HTTP::EAccept, KAccept );
+    
+    // Submit the transaction. After this the framework will give transaction
+    // events via MHFRunL and MHFRunError.
+    iTransaction.SubmitL();
+    
+    iObserver.ClientEvent( EHttpConnecting );
+	LOG("CClientEngine::DoHTTPGetL ,end");
+}
+
+// ----------------------------------------------------------------------------
+// CClientEngine::CancelTransaction()
+// ----------------------------------------------------------------------------
+void CClientEngine::CancelTransaction()
+    {
+    LOG("CClientEngine::CancelTransaction ,begin");
+    iEngineState = EIdle;
+    delete iUri; 
+    iUri = NULL;
+    
+    // Close() also cancels transaction (Cancel() can also be used but
+    // resources allocated by transaction must be still freed with Close())
+    if( iTransactionOpen )
+        {
+        iTransaction.Close();
+        iTransactionOpen = EFalse;
+
+        iObserver.ClientEvent( EHttpTxCancelled );
+        }
+	LOG("CClientEngine::CancelTransaction ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::MHFRunL()
+// ----------------------------------------------------------------------------
+void CClientEngine::MHFRunL( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
+    {
+    LOG("CClientEngine::MHFRunL ,begin");
+    switch ( aEvent.iStatus )
+        {
+        case THTTPEvent::EGotResponseHeaders:
+            {
+            // HTTP response headers have been received. Use
+            // aTransaction.Response() to get the response. However, it's not
+            // necessary to do anything with the response when this event occurs.
+            iObserver.ClientEvent( EHttpHdrReceived );
+            break;
+            }
+        case THTTPEvent::EGotResponseBodyData:
+            {
+            // Part (or all) of response's body data received. Use
+            // aTransaction.Response().Body()->GetNextDataPart() to get the actual
+            // body data.
+        
+            // Get the body data supplier
+            MHTTPDataSupplier* body = aTransaction.Response().Body();
+            TPtrC8 dataChunk;
+        
+            // GetNextDataPart() returns ETrue, if the received part is the last
+            // one.
+            TBool isLast = body->GetNextDataPart(dataChunk);
+            iObserver.ClientBodyReceived(dataChunk);
+        
+            iObserver.ClientEvent( EHttpBytesReceieved );
+
+            // NOTE: isLast may not be ETrue even if last data part received.
+            // (e.g. multipart response without content length field)
+            // Use EResponseComplete to reliably determine when body is completely
+            // received.
+            if( isLast )
+                {
+                iObserver.ClientEvent( EHttpBodyReceieved );
+                }
+            // Always remember to release the body data.
+            body->ReleaseData();
+            break;
+            }
+        case THTTPEvent::EResponseComplete:
+            {
+            // Indicates that header & body of response is completely received.
+            // No further action here needed.
+
+            iObserver.ClientEvent( EHttpTxCompleted );
+            break;
+            }
+        case THTTPEvent::ESucceeded:
+            {
+            // Indicates that transaction succeeded.
+            iObserver.ClientEvent( EHttpTxSuccess );
+            // Transaction can be closed now. It's not needed anymore.
+            aTransaction.Close();
+            iTransactionOpen = EFalse;
+            break;
+            }
+        case THTTPEvent::EFailed:
+            {
+            // Transaction completed with failure.
+            iObserver.ClientEvent( EHttpTxFailed );
+            aTransaction.Close();
+            iTransactionOpen = EFalse;
+            break;
+            }
+        default:
+            // There are more events in THTTPEvent, but they are not usually
+            // needed. However, event status smaller than zero should be handled
+            // correctly since it's error.
+            {
+            if ( aEvent.iStatus < 0 )
+                {
+                iObserver.ClientEvent( EHttpConnectionFailure );
+                // Close the transaction on errors
+                aTransaction.Close();
+                iTransactionOpen = EFalse;
+                }
+                break;
+            }
+        }
+	LOG("CClientEngine::MHFRunL ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::MHFRunError()
+// ----------------------------------------------------------------------------
+TInt CClientEngine::MHFRunError( TInt /*aError*/, RHTTPTransaction /*aTransaction*/, const THTTPEvent& /*aEvent*/ )
+    {
+    LOG("CClientEngine::MHFRunError ,begin");
+    // Just notify about the error and return KErrNone.
+    CloseConnection();
+    iObserver.ClientEvent(EHttpMhfRunError);
+    return KErrNone;
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::PreferredCarrierAvailable()
+// ----------------------------------------------------------------------------
+void CClientEngine::PreferredCarrierAvailable( TAccessPointInfo /*aOldAPInfo*/,
+                                               TAccessPointInfo /*aNewAPInfo*/,
+                                               TBool /*aIsUpgrade*/,
+                                               TBool aIsSeamless )
+    {
+    LOG("CClientEngine::PreferredCarrierAvailable ,begin");
+    if( !aIsSeamless && iMobility)
+        {
+        iMobility->MigrateToPreferredCarrier();
+        }
+	LOG("CClientEngine::PreferredCarrierAvailable ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::NewCarrierActive()
+// ----------------------------------------------------------------------------
+void CClientEngine::NewCarrierActive( TAccessPointInfo /*aNewAPInfo*/,
+                                      TBool aIsSeamless )
+    {
+    LOG("CClientEngine::NewCarrierActive ,begin");
+    if( !aIsSeamless && iMobility)
+        {
+        iMobility->NewCarrierAccepted();
+        }
+	LOG("CClientEngine::NewCarrierActive ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::Error()
+// ----------------------------------------------------------------------------
+void CClientEngine::Error(TInt /*aError*/)
+    {
+    LOG("CClientEngine::Error");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::DoCancel()
+// ----------------------------------------------------------------------------
+void CClientEngine::DoCancel()
+    {
+    LOG("CClientEngine::DoCancel");
+    iConnection.Stop();
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::DoCancel()
+// ----------------------------------------------------------------------------
+TInt  CClientEngine::RunError(TInt /*aError*/)
+    {
+    LOG("CClientEngine::RunError");
+    // Just notify about the error and return KErrNone.
+    CloseConnection();
+    iObserver.ClientEvent( EHttpTxFailed );
+    return KErrNone;
+    }
+// ----------------------------------------------------------------------------
+// CClientEngine::RunL()
+// ----------------------------------------------------------------------------
+void CClientEngine::RunL()
+    {
+    LOG1("CClientEngine::RunL: error is: %d\n", iStatus.Int() );
+    TInt statusCode = iStatus.Int();
+    if ( statusCode == KErrNone )
+        {
+        // Connection done ok
+        iConnectionSetupDone = ETrue;
+        
+        RStringPool strPool = iSession.StringPool();
+
+        // Remove first session properties just in case.
+        RHTTPConnectionInfo connInfo = iSession.ConnectionInfo();
+        
+        // Clear RConnection and Socket Server instances
+        connInfo.RemoveProperty(strPool.StringF(HTTP::EHttpSocketServ,RHTTPSession::GetTable()));
+        connInfo.RemoveProperty(strPool.StringF(HTTP::EHttpSocketConnection,RHTTPSession::GetTable()));
+        
+        // Clear the proxy settings
+        connInfo.RemoveProperty(strPool.StringF(HTTP::EProxyUsage,RHTTPSession::GetTable()));
+        connInfo.RemoveProperty(strPool.StringF(HTTP::EProxyAddress,RHTTPSession::GetTable()));
+        
+        // RConnection and Socket Server
+        connInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketServ, 
+                                        RHTTPSession::GetTable()), 
+                                THTTPHdrVal (iSocketServ.Handle()) );
+        
+        TInt connPtr1 = REINTERPRET_CAST(TInt, &iConnection);
+        connInfo.SetPropertyL ( strPool.StringF(HTTP::EHttpSocketConnection, 
+                                RHTTPSession::GetTable() ), THTTPHdrVal (connPtr1) );    
+
+        // Register for mobility API
+		if(iMobility)
+			{
+	        delete iMobility;
+			iMobility = NULL ;
+			}
+        iMobility = CActiveCommsMobilityApiExt::NewL( iConnection, *this );
+        // Start selected HTTP action
+        switch( iEngineState )
+            {
+            case EIdle:
+                {
+                //
+                CancelTransaction();
+                break;
+                }
+            case EGet:
+               {
+               DoHTTPGetL();
+               break;
+               }
+            };
+        }
+    else
+        {
+        //handle error
+        if ( statusCode == KErrPermissionDenied )
+            {
+            iObserver.ClientEvent( EHttpAuthFailed );
+            }
+        else
+            {
+            //Throw some general Transaction falure error!
+            iObserver.ClientEvent( EHttpTxFailed );
+            }
+        CloseConnection();
+        }
+	LOG("CClientEngine::RunL ,end");
+    }
+
+// ----------------------------------------------------------------------------
+// CClientEngine::SilentConnectionAllowed()
+// ----------------------------------------------------------------------------
+TBool CClientEngine::SilentConnectionAllowed()
+    {
+    LOG("CClientEngine::SilentConnectionAllowed ,begin");
+    TBool retVal = EFalse;
+	TRAPD(err, retVal = IsDataConnectionAskAlwaysL());
+	if(err == KErrNone)
+		{
+		// data connection is always ask... Silent connection is not allowed
+		retVal = !retVal;
+		}
+	LOG1("CClientEngine::SilentConnectionAllowed ,end. Ret - %d", retVal);
+    return retVal;
+    }
+
+// End of file
+