--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/httpfilters/uaproffilter/src/uaproffilter.cpp Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,671 @@
+/*
+* Copyright (c) 2003 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 class CHttpUAProfFilter.
+*
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "uaproffilter.h"
+
+#include <e32std.h>
+#include <etelmm.h>
+#include <mmtsy_names.h>
+
+#include <http/rhttptransaction.h>
+#include <http/rhttpconnectioninfo.h>
+#include <http/rhttpheaders.h>
+#include <httperr.h>
+
+#include <BrowserUiSDKCRKeys.h>
+#include <webutilsinternalcrkeys.h>//for the profile strings
+
+#include <cuseragent.h>
+#include <featmgr.h>
+#include <bldvariant.hrh>
+
+
+// Token for IMEI/SN code in UA-header.
+_LIT8( KImeiSnToken, "SN" );
+_LIT8( KSlash, "/" );
+
+// Space character.
+LOCAL_D const TUint8 KSpaceChar = ' ';
+
+// MACROS
+
+/// OOM test helper.
+//#define __TEST_OOM_IN_INSTALL
+/// OOM test helper.
+//#define __TEST_OOM_IN_MHFRUNL
+
+// CONSTANTS
+
+/// Initial buffer size for reading from Shared Data.
+LOCAL_D const TInt KSdReadBufSize = 128;
+/// profile
+_LIT8( KProfile, "profile" );
+/// x-wap-profile
+_LIT8( KXWapProfile, "x-wap-profile" );
+#if defined( _DEBUG )
+/// Panic name for UAProf Filter.
+_LIT( KUAProfFilter, "UAProfFilter" );
+#endif
+/// Length for imei code.
+LOCAL_D const TInt KImeiLength = 15;
+
+
+#if defined( __WINS__ )
+/// Dummy IMEI value for WINS emulator.
+_LIT( KEmulatorImei, "123456789012345" );
+#endif
+
+// ================= MEMBER FUNCTIONS ==========================================
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::InstallFilterL()
+// -----------------------------------------------------------------------------
+//
+CHttpUAProfFilterInterface* CHttpUAProfFilter::InstallFilterL( TAny* aSession )
+ {
+#ifdef __TEST_OOM_IN_INSTALL
+ __UHEAP_SETFAIL( RHeap::ETrueRandom, 40 );
+#endif /* def __TEST_OOM_IN_INSTALL */
+
+ __ASSERT_DEBUG( aSession, User::Panic( KUAProfFilter, KErrArgument ) );
+ RHTTPSession* session = REINTERPRET_CAST( RHTTPSession*, aSession );
+ CHttpUAProfFilter* filter = new (ELeave) CHttpUAProfFilter( *session );
+ CleanupStack::PushL( filter );
+ filter->ConstructL();
+ CleanupStack::Pop( filter );
+ return filter;
+
+#ifdef __TEST_OOM_IN_INSTALL
+ __UHEAP_SETFAIL( RHeap::ENone, 1 );
+#endif /* def __TEST_OOM_IN_INSTALL */
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::~CHttpUAProfFilter()
+// -----------------------------------------------------------------------------
+//
+CHttpUAProfFilter::~CHttpUAProfFilter()
+ {
+ // If we've been destroyed from the cleanup stack during creation
+ // of the object, it might still be loaded. So check. (Normally the
+ // delete is initiated by the 'delete this' in MHFUnload)
+ if( iLoadCount > 0)
+ {
+ // As we're already in a destructor, MHFUnload must not delete us
+ // again. So -1 value is set.
+ iLoadCount = -1;
+ iSession.FilterCollection().RemoveFilter( StringF( HTTP::EUserAgent ) );
+ }
+ // Make sure we don't close an unopened RStringF
+ if( iUaProf3GOpen )
+ {
+ iUaProf3G.Close();
+ }
+ if( iUaProfOpen )
+ {
+ iUaProf.Close();
+ }
+ if( iUaNameOpen )
+ {
+ iUaName.Close();
+ }
+ if ( iUaNameWithImeiOpen )
+ {
+ iUaNameWithImei.Close();
+ }
+ if( iUaNameMmsOpen )
+ {
+ iUaNameMms.Close();
+ }
+ if ( iUaNameMmsWithImeiOpen )
+ {
+ iUaNameMmsWithImei.Close();
+ }
+ iMobilePhone.Close();
+ iTelServer.Close();
+
+ if ( iNotifyHandler )
+ {
+ iNotifyHandler->StopListening();
+ }
+ delete iRepositoryBrowser;
+ delete iRepositoryCommonEngine;
+ delete iNotifyHandler;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::MHFRunL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::MHFRunL
+( RHTTPTransaction aTransaction, const THTTPEvent& aEvent )
+ {
+#ifdef __TEST_OOM_IN_MHFRUNL
+ __UHEAP_SETFAIL( RHeap::ETrueRandom, 30 );
+#endif /* def __TEST_OOM_IN_MHFRUNL */
+
+ switch( aEvent.iStatus )
+ {
+ case THTTPEvent::ESubmit:
+ {
+ SubmitL( aTransaction );
+ break;
+ }
+
+ default:
+ {
+ break;
+ }
+ }
+
+#ifdef __TEST_OOM_IN_MHFRUNL
+ __UHEAP_SETFAIL( RHeap::ENone, 1 );
+#endif /* def __TEST_OOM_IN_MHFRUNL */
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::MHFRunError()
+// -----------------------------------------------------------------------------
+//
+TInt CHttpUAProfFilter::MHFRunError
+( TInt /*aError*/, RHTTPTransaction aTransaction, const THTTPEvent& /*aEvent*/ )
+ {
+ aTransaction.Fail();
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::MHFSessionRunL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::MHFSessionRunL( const THTTPSessionEvent& /*aEvent*/ )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::MHFSessionRunError()
+// -----------------------------------------------------------------------------
+//
+TInt CHttpUAProfFilter::MHFSessionRunError
+( TInt aError, const THTTPSessionEvent& /*aEvent*/ )
+ {
+ return aError;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::MHFUnload()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::MHFUnload( RHTTPSession /*aSession*/,
+ THTTPFilterHandle /*aHandle*/ )
+ {
+ // We must be only registered on one session, as we register in our
+ // ConstructL and no-one else has a pointer to us. Therefore, we
+ // know we can be deleted at this point.
+ if( --iLoadCount == 0 )
+ {
+ delete this;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::MHFLoad()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::MHFLoad
+( RHTTPSession /*aSession*/, THTTPFilterHandle /*aHandle*/ )
+ {
+ ++iLoadCount;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::HandleNotifyInt()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::HandleNotifyInt(TUint32 aId, TInt aValue)
+ {
+ if ( aId == KBrowserIMEINotification )
+ {
+ TInt imeiSendingOn = aValue;
+ iImeiSendingOn = (imeiSendingOn != 0);
+ }
+ #ifdef _DEBUG
+ else
+ {
+ // This notification was not requested.
+ User::Panic( KUAProfFilter, KErrGeneral );
+ }
+ #endif
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::CHttpUAProfFilter()
+// -----------------------------------------------------------------------------
+//
+CHttpUAProfFilter::CHttpUAProfFilter( RHTTPSession aSession )
+: iUaProfOpen( EFalse ),
+ iUaProf3GOpen( EFalse ),
+ iUaNameOpen( EFalse ),
+ iUaNameWithImeiOpen( EFalse ),
+ iUaNameMmsOpen( EFalse ),
+ iUaNameMmsWithImeiOpen( EFalse ),
+ iSession( aSession ),
+ iStringPool( aSession.StringPool() ),
+ iStringTable( RHTTPSession::GetTable() ),
+ iImeiFeatureEnabled( EFalse ),
+ iImeiSendingOn( EFalse )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::ConstructL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::ConstructL()
+ {
+
+ //iRepositoryCommonEngine object will be created in OpenProfileString()
+ //iRepositoryBrowser object will be SetupImeiNotifyL()
+
+ // This filter is opened only on one session, so it is safe to pre-open
+ // the strings we are going to use.
+
+ // UAProf string.
+ OpenProfileStringsL(); // Uses iSdCli.
+
+ // If 2G/3G distinction is supported, prepare querying the network type.
+ // If no such distinction is made, we don't need RMobilePhone at all.
+ if ( iUaProf3GOpen )
+ {
+ User::LeaveIfError( iTelServer.Connect() );
+ User::LeaveIfError( iTelServer.LoadPhoneModule( KMmTsyModuleName ) );
+ TInt numPhones;
+ User::LeaveIfError( iTelServer.EnumeratePhones( numPhones ) );
+ if( numPhones <= 0 )
+ {
+ // Huh???
+ User::Leave( KErrCorrupt );
+ }
+ RTelServer::TPhoneInfo phoneInfo;
+ User::LeaveIfError( iTelServer.GetPhoneInfo( 0, phoneInfo ) );
+ User::LeaveIfError( iMobilePhone.Open( iTelServer, phoneInfo.iName ) );
+ User::LeaveIfError( iMobilePhone.Initialise() );
+ }
+
+ // Setup IMEI-notify stuff, ignore any errors.
+ // Expected error: Browser's INI file may not be present.
+ TRAP_IGNORE( SetupImeiNotifyL() );
+
+ // User Agent name string.
+ OpenUserAgentNameStringsL();
+
+ // Register filter.
+ iSession.FilterCollection().AddFilterL
+ (
+ *this,
+ THTTPEvent( THTTPEvent::ESubmit ), // submit event
+ MHTTPFilter::ETidyUp, // priority
+ StringF( HTTP::EUserAgent ) // name
+ );
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::SetupImeiNotifyL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::SetupImeiNotifyL()
+ {
+ // First check if this feature is enabled.
+ FeatureManager::InitializeLibL(); // Warning: no leaving...
+ iImeiFeatureEnabled =
+ FeatureManager::FeatureSupported( KFeatureIdBrowserIMEINotification );
+ FeatureManager::UnInitializeLib(); // ... until this point!
+
+ // If feature is enabled, query value and register for notification.
+ if ( iImeiFeatureEnabled )
+ {
+ TInt imeiSendingOn( 0 );
+
+ CRepository* iRepositoryBrowser = CRepository::NewL( KCRUidBrowser );
+ iRepositoryBrowser->Get( KBrowserIMEINotification, imeiSendingOn );
+ iImeiSendingOn = (imeiSendingOn != 0);
+ iNotifyHandler = CCenRepNotifyHandler::NewL(*this,
+ *iRepositoryBrowser,
+ CCenRepNotifyHandler::EIntKey,
+ KBrowserIMEINotification);
+ iNotifyHandler->StartListeningL();
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::SubmitL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::SubmitL( RHTTPTransaction aTransaction )
+ {
+ RHTTPHeaders headers( aTransaction.Request().GetHeaderCollection() );
+
+ // User-Agent: protocol independent header.
+
+ // First check if client is MMS.
+ TBool uaMms( EFalse );
+ RStringF uaClient = iStringPool.OpenFStringL( KUserAgentClientId );
+ CleanupClosePushL<RStringF>( uaClient );
+ THTTPHdrVal val;
+ if ( aTransaction.PropertySet().Property( uaClient, val ) &&
+ val.Type() == THTTPHdrVal::KTIntVal &&
+ val.Int() == KUserAgentCliMMS )
+ {
+ uaMms = ETrue;
+ }
+ CleanupStack::PopAndDestroy(); // Close uaClient.
+
+ // If IMEI-notify is on (implies that feature is supported), use that.
+ RStringF hdrVal;
+ if ( uaMms )
+ {
+ hdrVal = iImeiSendingOn ? iUaNameMmsWithImei : iUaNameMms;
+ }
+ else
+ {
+ hdrVal = iImeiSendingOn ? iUaNameWithImei : iUaName;
+ }
+ AddOrReplaceHeaderL( headers, StringF( HTTP::EUserAgent ), hdrVal );
+
+ // UAProf: protocol dependent.
+ RStringF xProfile;
+ THTTPHdrVal protocol;
+ TBool protocolExists = iSession.ConnectionInfo().Property
+ ( StringF( HTTP::EProtocol ), protocol );
+ if( protocolExists &&
+ protocol.Type() == THTTPHdrVal::KStrFVal &&
+ protocol.StrF() == StringF( HTTP::EWSP ) )
+ {
+ // It's WSP - set "Profile".
+ xProfile = iStringPool.OpenFStringL( KProfile );
+ }
+ else
+ {
+ // It's HTTP - set "x-wap-profile".
+ xProfile = iStringPool.OpenFStringL( KXWapProfile );
+ }
+ CleanupClosePushL<RStringF>( xProfile );
+ // Use 3G profile if:
+ // - we have such (i.e. feature is supported); and
+ // - network is 3G.
+ hdrVal = (iUaProf3GOpen && Is3gNetworkL()) ? iUaProf3G : iUaProf;
+ AddOrReplaceHeaderL( headers, xProfile, hdrVal );
+ CleanupStack::PopAndDestroy(); // close xProfile
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::AddOrReplaceHeaderL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::AddOrReplaceHeaderL
+( RHTTPHeaders& aHeaders, const RStringF& aName, const RStringF& aValue )
+ {
+ // Checking whether the header field is already set or not would be waste:
+ // that is executed inside RemoveField anyway.
+ (void)aHeaders.RemoveField( aName );
+ aHeaders.SetFieldL( aName, THTTPHdrVal( aValue ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::OpenUserAgentNameStringsL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::OpenUserAgentNameStringsL()
+ {
+ CUserAgent* usrAgnt = CUserAgent::NewL();
+ CleanupStack::PushL( usrAgnt );//C.S: 1
+
+ HBufC8* bufUA = usrAgnt->UserAgentL();
+ CleanupStack::PushL( bufUA );//C.S 2
+ if ( !bufUA || !bufUA->Length() )
+ {
+ // Reject empty value.
+ //User::Leave( KErrCorrupt );
+ User::Panic(_L("Improper UA string"), KErrCorrupt);
+ }
+ iUaName = iStringPool.OpenFStringL( *bufUA );
+ iUaNameOpen = ETrue;
+
+ //Read the MMS useragent string now
+ HBufC8* bufUAMMS = usrAgnt->MMSUserAgentL();
+ CleanupStack::PushL( bufUAMMS );//C.S 2
+ if ( !bufUAMMS || !bufUAMMS->Length() )
+ {
+ // Reject empty value.
+ //User::Leave( KErrCorrupt );
+ User::Panic(_L("Improper UA string"), KErrCorrupt);
+ }
+ iUaNameMms = iStringPool.OpenFStringL( *bufUAMMS );
+ iUaNameMmsOpen = ETrue;
+
+ if ( iImeiFeatureEnabled )
+ {
+ // User Agent name string with IMEI code.
+ TBuf<KImeiLength> imei16;
+ GetImeiL( imei16 );
+ HBufC8* imei8 = ConvertL( imei16 );
+ CleanupStack::PushL( imei8 );//C.S 2
+
+ // Add IMEI string to the UA-header.
+ TPtr8 ptrUA = bufUA->Des();
+ AddImeiToUserAgentL(ptrUA, *imei8);
+ iUaNameWithImei = iStringPool.OpenFStringL( *bufUA );
+ iUaNameWithImeiOpen = ETrue;
+
+ // Add IMEI string to the UA-MMS-header.
+ TPtr8 ptrUAMMS = bufUAMMS->Des();
+ AddImeiToUserAgentL(ptrUAMMS, *imei8);
+ iUaNameMmsWithImei = iStringPool.OpenFStringL( *bufUAMMS );
+ iUaNameMmsWithImeiOpen = ETrue;
+
+ CleanupStack::PopAndDestroy( imei8 );//C.S 2
+ }
+
+
+ CleanupStack::PopAndDestroy( bufUAMMS );
+ CleanupStack::PopAndDestroy( bufUA );
+ CleanupStack::PopAndDestroy( usrAgnt );//C.S 1 => OK
+ }
+
+void CHttpUAProfFilter::AddImeiToUserAgentL(TPtr8 &aUAStringPtr, const TDesC8& aImei)
+ {
+
+ TInt firstSpaceIndex = aUAStringPtr.Locate( TChar( KSpaceChar ) );
+
+ if ( firstSpaceIndex != KErrNotFound )
+ {
+ // Insert IMEI before first space, separated by '/'
+ aUAStringPtr.Insert( firstSpaceIndex++, KSlash);
+ aUAStringPtr.Insert( firstSpaceIndex, KImeiSnToken);
+ firstSpaceIndex += KImeiSnToken.iTypeLength;
+ aUAStringPtr.Insert( firstSpaceIndex, aImei );
+ }
+ else
+ {
+ // If there is no spaces, add IMEI to end of ENameMMS, separated by '/'
+ aUAStringPtr.Append( KSlash );
+ aUAStringPtr.Append( KImeiSnToken );
+ aUAStringPtr.Append( aImei );
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::OpenProfileStringsL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::OpenProfileStringsL()
+ {
+ // UAProf string.
+ TRAPD(err1,iRepositoryCommonEngine = CRepository::NewL( KCRUidWebUtils ));
+
+ if(KErrNone != err1)
+ User::Panic( _L("CHttpUAProfFilter"), err1 );
+
+ HBufC* buf16;
+
+ User::LeaveIfError( ReadSdString( KWebUtilsUaProf , buf16 ) );
+
+ CleanupStack::PushL( buf16 );
+ if ( !buf16 || !buf16->Length() )
+ {
+ // Reject empty value.
+ User::Leave( KErrCorrupt );
+ }
+ HBufC8* buf8 = ConvertL( *buf16 );
+ CleanupStack::PushL( buf8 );
+ iUaProf = iStringPool.OpenFStringL( *buf8 );
+ iUaProfOpen = ETrue;
+ CleanupStack::PopAndDestroy( 2, buf16 ); // buf8, buf16
+
+ // UAProf3G string. If missing/empty, not opened - this indicates that
+ // the 2G/3G distinction feature is not supported.
+ TInt err = ReadSdString( KWebUtilsUaProf3G, buf16 );
+
+ CleanupStack::PushL( buf16 );
+ if ( err && err != KErrNotFound )
+ {
+ // Error other than KErrNotFound, leave. KErrNotFound is OK, indicates
+ // that this key is missing -> feature is not supported.
+ User::Leave( err );
+ }
+ if ( buf16 && buf16->Length() )
+ {
+ buf8 = ConvertL( *buf16 );
+ CleanupStack::PushL( buf8 );
+ iUaProf3G = iStringPool.OpenFStringL( *buf8 );
+ iUaProf3GOpen = ETrue; // Also indicates that feature is supported.
+ CleanupStack::PopAndDestroy( buf8 );
+ }
+
+ CleanupStack::PopAndDestroy( buf16 );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::ConvertL()
+// -----------------------------------------------------------------------------
+//
+HBufC8* CHttpUAProfFilter::ConvertL( const TDesC16& aSrc )
+ {
+ HBufC8* buf = HBufC8::NewL( aSrc.Length() );
+ buf->Des().Copy( aSrc );
+ return buf;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::ReadSdString()
+// -----------------------------------------------------------------------------
+//
+TInt CHttpUAProfFilter::ReadSdString( const TUint32 aKey, HBufC*& aBuf )
+ {
+ // We don't know the size of the string we are going to read (and Shared
+ // data can't tell it). A trial-and-error method is used: we start with
+ // a fixed size buffer and retry with increasing buffer size until success.
+ TInt err( KErrTooBig );
+ TInt round = 0;
+ HBufC* buf = NULL;
+
+ while( err == KErrTooBig )
+ {
+ // Increase buffer size until returned data can fit.
+ delete buf;
+ ++round;
+ buf = HBufC::New( KSdReadBufSize * round );
+ if( buf )
+ {
+ TPtr bufP( buf->Des() );
+ err = iRepositoryCommonEngine->Get( aKey, bufP );
+ }
+ else
+ {
+ err = KErrNoMemory;
+ }
+ }
+
+ if( err )
+ {
+ delete buf;
+ buf = NULL; // Make lint happy.
+ }
+
+ aBuf = buf;
+ return err;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::GetImeiL()
+// -----------------------------------------------------------------------------
+//
+void CHttpUAProfFilter::GetImeiL( TDes& aBuf ) const
+ {
+ aBuf.Zero();
+
+ // Read IMEI on HW, use dummy under WINS
+#if !defined( __WINS__ )
+ TUint32 identityCaps;
+ User::LeaveIfError(iMobilePhone.GetIdentityCaps(identityCaps));
+ TBuf<RMobilePhone::KPhoneSerialNumberSize> serNumber;
+
+if (identityCaps & RMobilePhone::KCapsGetSerialNumber)
+ {
+ TRequestStatus status;
+ RMobilePhone::TMobilePhoneIdentityV1 mobilePhoneIdentity;
+ iMobilePhone.GetPhoneId(status, mobilePhoneIdentity);
+ User::WaitForRequest(status);
+ User::LeaveIfError(status.Int());
+ serNumber = mobilePhoneIdentity.iSerialNumber;
+ aBuf.Copy(serNumber);
+ }
+#else
+ aBuf.Copy( KEmulatorImei);
+#endif
+}
+
+// -----------------------------------------------------------------------------
+// CHttpUAProfFilter::Is3gNetworkL()
+// -----------------------------------------------------------------------------
+//
+TBool CHttpUAProfFilter::Is3gNetworkL() const
+ {
+ // This method must not be called if 2G/3G distinction is not supported;
+ // the RMobilePhone-related classes are not open in that case.
+ __ASSERT_DEBUG( iUaProf3GOpen, \
+ User::Panic( KUAProfFilter, KErrNotReady ) );
+ TBool is3g( EFalse );
+#if !defined( __WINS__ )
+ RMobilePhone::TMobilePhoneNetworkMode networkMode;
+ User::LeaveIfError( iMobilePhone.GetCurrentMode( networkMode ) );
+ if( networkMode == RMobilePhone::ENetworkModeCdma2000 ||
+ networkMode == RMobilePhone::ENetworkModeWcdma )
+ {
+ is3g = ETrue;
+ }
+#endif
+ return is3g;
+ }