browserutilities/browsertelservice/src/BrowserTelService.cpp
changeset 0 dd21522fd290
child 25 0ed94ceaa377
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/browsertelservice/src/BrowserTelService.cpp	Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,2899 @@
+/*
+* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+*
+*/
+
+
+// INCLUDE FILES
+#include <BrowserTelService.rsg>
+#include <coemain.h>
+#include    <data_caging_path_literals.hrh>
+
+// For phonebook API
+#include <CPbkContactItem.h>    // Phonebook Contact
+#include <CPbkContactEngine.h>  // Phonebook Engine
+#include <CPbkFieldsInfo.h>     // Phonebook field types
+#include <RPbkViewResourceFile.h>
+#include <CPbkContactEditorDlg.h>   // Phonebook editor
+// For searching a matching number from contact's db
+#include <TPbkContactItemField.h>
+#include <CNTFLDST.H>
+
+#include <FeatMgr.h>
+// 
+#include <txtrich.h>
+#include <badesca.h>
+#include <miutset.h>
+#include <s32strm.h>
+
+// For email API
+#include <sendui.h>
+#include <CMessageData.h>
+#include <TSendingCapabilities.h>
+#include <SenduiMtmUids.h>
+ 
+// For BaflUtils
+#include <bautils.h>
+
+// Stringloader
+#include <StringLoader.h>
+
+// TApaTask, TApaTaskList
+#include <apgtask.h>
+
+// Connection management
+#include <in_sock.h>
+#include <es_enum.h>
+
+#include <ApUtils.h>
+#include <APDataHandler.h>
+#include <ApAccessPointItem.h>
+#include <commdb.h>
+
+#include <f32file.h>
+// Const file name for make call
+#include <mmtsy_names.h>
+
+#include <BrowserUiSDKCRKeys.h>
+#include <centralrepository.h>
+
+#include <nwx_status.h>
+
+#include <DialUtils.h>
+
+#include "BrowserTelService.h"
+#include "BrowserTelServiceDlgs.h"
+#include "TelServiceLogger.h"
+
+#include "BrowserUtilitiesVariant.hrh" // KBrowserUtilitiesMailtoSchemeToMmsEditor
+
+const TInt KParseArrayAllocation = 10;
+const TInt KTimerDelay = 2500000;
+
+_LIT( KValidDTMFChars,"w/p*#0123456789ABCDabcd," );
+_LIT( KDTMFWaitChars, "/wp,*#" );
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+_LIT( KDTMFInvalidWaitChars, "/," );
+_LIT( KDTMFValidPause, "p" );
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+// load resource file
+_LIT( KResourceFileName, "Z:browsertelservice.RSC" ); 
+
+// Path of the temp file
+_LIT(KTempDrive, "d:");
+_LIT( KTempPath, "\\system\\temp\\" );
+
+// The library to be loaded.
+_LIT( KDialUtilsLoadLib, "DialUtils.dll" );
+
+const TInt KKimonoBase = 26000;
+
+/*
+ This is a conversion table from browsertelservice internal
+ error codes to global and localized error ids.
+ {local error code, global error id}
+ Exception is KErrArgument-NW_STAT_WTAI_INVALID_ARGUMENT pair, because
+ case of wrong dtmf sequence has no WTAI correspondent error code.
+*/
+const TInt KErrorConvTable[][2] = 
+    {
+    {KErrInvocationError, NW_STAT_WTAI_INVOCATIONERROR},
+    {KErrNoCallActive, NW_STAT_WTAI_NOCALLACTIVE},
+    {KErrUserNoAnswer, NW_STAT_WTAI_NOANSWER},
+    {KErrNoService, NW_STAT_WTAI_NOSERVICE},
+    {KErrUserBusy, NW_STAT_WTAI_USERBUSY},
+    {KErrPBPhoneBookFull, NW_STAT_WTAI_PHONEBOOKFULL},
+    {KErrPBWriteError, NW_STAT_WTAI_PBWRITEERROR},
+    {KErrPBNumberTooLong, NW_STAT_WTAI_PBNUMBERTOOLONG},
+    {KErrPBNameTooLong, NW_STAT_WTAI_PBNAMETOOLONG},
+    {KErrUnspecified, NW_STAT_WTAI_UNSPECIFIED_ERROR},
+    {KErrArgument,NW_STAT_WTAI_INVALID_ARGUMENT},
+    {KErrEtelBusyDetected, NW_STAT_WTAI_USERBUSY},
+    {KErrEtelNoAnswer, NW_STAT_WTAI_NOANSWER},
+    {0,0}
+    };
+
+// ================= MEMBER FUNCTIONS =======================
+
+//-----------------------------------------------------------------------------
+// CBrowserTelService::NewLC()
+//-----------------------------------------------------------------------------
+//
+EXPORT_C CBrowserTelService* CBrowserTelService::NewLC(
+							MBrowserTelServiceObserver* aObserver )
+	{
+    CBrowserTelService* self = new( ELeave ) CBrowserTelService;
+    CleanupStack::PushL( self );
+    self->ConstructL( aObserver );
+    return self;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::NewL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C CBrowserTelService* CBrowserTelService::NewL(
+							MBrowserTelServiceObserver* aObserver )
+	{
+    CBrowserTelService* self = CBrowserTelService::NewLC( aObserver );
+    CleanupStack::Pop();
+    return self;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ConstructL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::ConstructL( MBrowserTelServiceObserver* aObserver )
+	{
+    TELSERVICE_CREATE;
+
+	iServiceHandler = NULL;
+	
+    SetState( EIdle );
+    
+    if( aObserver )
+		{
+        iObserverList.Append( aObserver );
+		}
+
+    iSynch = EFalse;
+	iIdle = CIdle::NewL( CActive::EPriorityIdle );
+
+    // Prepare telservice logger.
+    TELSERVICE_CREATE;
+	
+	// Resouce file loading
+    TParse* fileParser = new (ELeave) TParse;
+    CleanupStack::PushL( fileParser );
+    
+    fileParser->Set( KResourceFileName, &KDC_RESOURCE_FILES_DIR, NULL ); 
+    iResourceFileName = fileParser->FullName();
+    iResourceLoader.OpenL( iResourceFileName );
+    iResourceOpened = ETrue;
+
+    CleanupStack::PopAndDestroy( fileParser ); // fileParser	
+
+    iErrorUi = CErrorUI::NewL();
+
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__    
+    iDialData = CAiwDialData::NewL();
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+    CActiveScheduler::Add( this );
+	}
+
+//---------------------------------------------------------------------------------------
+// Default C++ constructor
+//---------------------------------------------------------------------------------------
+//
+CBrowserTelService::CBrowserTelService() 
+:   CActive( EPriorityNormal ), 
+    iResourceFileName( KNullDesC ), 
+    iResourceLoader( *CCoeEnv::Static() ),
+    iResourceOpened( EFalse )
+	{
+	}
+
+//---------------------------------------------------------------------------------------
+// Destructor
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C CBrowserTelService::~CBrowserTelService()
+	{
+    TELSERVICE_ENTERFN( "~CBrowserTelService()" )
+
+	delete iServiceHandler;
+    iServiceHandler = NULL;
+
+    // Cancel all current activity
+    Cancel();
+
+    // Close all open sessions
+    CloseAllSessions();
+
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__    
+	if (iDialData)
+			{
+			delete iDialData;
+			}
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+			
+    if( iSendableDTMFNumbers )
+        {
+        iSendableDTMFNumbers->ResetAndDestroy();
+        delete iSendableDTMFNumbers;
+        }
+
+    if( iDlgDTMFNumbers )
+        {
+        iDlgDTMFNumbers->ResetAndDestroy();
+        delete iDlgDTMFNumbers;
+        }
+
+    // Empty the observer list
+    iObserverList.Reset();
+/*
+	if ( iResourceFileOffset )
+        {
+		CCoeEnv::Static()->DeleteResourceFile( iResourceFileOffset );
+		}
+	 */
+    if ( iResourceOpened )
+        {
+        iResourceLoader.Close();
+        iResourceOpened = EFalse;
+        }
+    
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+    
+    if( iDTMFNumber )
+        {
+        delete iDTMFNumber;
+        iDTMFNumber = NULL;
+        }
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+	delete iIdle;
+    delete iErrorUi;
+
+    TELSERVICE_LEAVEFN( "~CBrowserTelService()" )
+    TELSERVICE_DELETE
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::InitializeL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C HBufC* CBrowserTelService::ParsePhoneNumberL( TDes* aNumber )
+    {
+    TELSERVICE_WRITE( "ParsePhoneNumberL()" )
+    return FindAndRipDTMFSequenceL( aNumber );
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::MakeCall()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::MakeCall( TDesC& aNumber, 
+										    TBool aSendDTMFAlwaysConfirm )
+	{
+    TELSERVICE_ENTERFN( "MakeCall() synchronous" )
+       
+    TInt retVal( KErrNone );
+
+    iRetVal = KErrNone;
+
+    // Flag to indicate that synchronous method was called
+    iSynch = ETrue;
+    TRAP( retVal, MakeCallL( aNumber, aSendDTMFAlwaysConfirm ) );
+
+    if( retVal != KErrNone )
+		{
+        ErrorHandler( retVal );
+
+        retVal = KErrCancel;
+        }
+    iSynch = EFalse;
+
+    TELSERVICE_LEAVEFN( "MakeCall() synchronous" )
+    return retVal;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::MakeCall()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C void CBrowserTelService::MakeCall( TRequestStatus& aStatus, 
+										    TDesC& aNumber, 
+										    TBool aSendDTMFAlwaysConfirm )
+	{
+    TELSERVICE_ENTERFN( "MakeCall() asynchronous" )
+
+    iRetVal = KErrNone;
+    
+    aStatus = KRequestPending;
+    iUserRequestStatus = &aStatus;
+    iSynch = EFalse;
+
+    TRAPD( err, MakeCall( aNumber, aSendDTMFAlwaysConfirm ) );
+
+    TELSERVICE_WRITE_FORMAT( "Asynch makecall start: %d", err )
+
+    if( err )
+        {
+        ErrorHandler( err );
+
+        User::RequestComplete( iUserRequestStatus, err );
+
+        CleanupBuffers();
+        }
+
+    TELSERVICE_LEAVEFN( "MakeCall() asynchronous" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::CancelMakeCall()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C void CBrowserTelService::CancelMakeCall()
+	{
+    TELSERVICE_ENTERFN( "CancelMakeCall()" )
+  
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+
+    // There is no ongoing request
+
+#else //  __BROWSER_TEL_SERVICES_CALLUI__
+
+    Cancel();
+    SetStateIdleAndNotifyObservers();
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+    TELSERVICE_LEAVEFN( "CancelMakeCall()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::MakeCallL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::MakeCallL( TDesC& aNumber, TBool aSendDTMFAlwaysConfirm, TBool voipCall )
+    {
+    iDTMFAlwaysConfirm = aSendDTMFAlwaysConfirm;
+    iRetVal = KErrNone;
+
+    if( State() != EIdle )
+		{
+        return;
+        }
+
+    if( aNumber.Length() == 0 )
+        {
+        User::Leave( KErrInvocationError );
+        }
+
+
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+    if( aNumber.Length() > AIWDialDataExt::KMaximumPhoneNumberLength )
+        {
+        User::Leave( KErrPBNumberTooLong );
+        }
+
+    HBufC* orgNumber = HBufC::NewLC( AIWDialDataExt::KMaximumPhoneNumberLength );
+#else // __BROWSER_TEL_SERVICES_CALLUI__
+
+    if( aNumber.Length() > RMobilePhone::KMaxMobileTelNumberSize )
+        {
+        User::Leave( KErrPBNumberTooLong );
+        }
+
+    HBufC* orgNumber = HBufC::NewLC( RMobilePhone::KMaxMobileTelNumberSize );
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+    
+    orgNumber->Des().Copy( aNumber );
+
+    if( FeatureManager::FeatureSupported( KFeatureIdJapanPrefixChange ) )
+        {
+        RLibrary dialUtils;
+        if( dialUtils.Load( KDialUtilsLoadLib ) == KErrNone )
+            {
+            CleanupClosePushL( dialUtils );
+
+            // Call function CreateDialUtilsFactoryL()
+            TInt res = dialUtils.Lookup( 1 )();
+            CDialUtilsFactory * dialUtilsFactory = 
+                reinterpret_cast< CDialUtilsFactory * >( res );
+
+            // This way the library is not needed at the linking time.
+            // Create Dial Utils (see that the function deletes the factory
+            // instance):
+            CDialUtilsApi* dialUtilsApi = dialUtilsFactory->CDialUtilsApiLD();
+            dialUtilsFactory = NULL;
+
+            // Then use the Dial Utils API, for example:
+            if( dialUtilsApi->CheckNumber( *orgNumber ) == KErrOverflow )
+                // no we have the converted number
+                {
+                User::Leave( KErrPBNumberTooLong );
+                }
+
+            delete dialUtilsApi;
+            CleanupStack::PopAndDestroy( &dialUtils );
+            }
+        }
+
+    // Handle postd format
+    TPtr orgNumberPtr( orgNumber->Des() );    
+    HBufC* postdParm = FindPostdParmL( orgNumberPtr );
+    
+    if(voipCall)
+    {
+    	FindAndRipVoipParametersL( orgNumberPtr );
+    }
+    
+        
+    // Rip URI parameters from Tel URI, in order to that
+    // number validation and DTMF works as earlier
+    // Parameters will be added back in later phase
+    HBufC* params = FindAndRipURIParametersL( orgNumberPtr );
+    CleanupStack::PushL( params );
+
+    HBufC* number = ValidateNumberL( *orgNumber );
+    CleanupStack::PushL( number );
+    
+    TPtr numberPtr = number->Des();
+    iDTMFNumber= FindAndRipDTMFSequenceL( &numberPtr );
+
+    TBool isPostd(EFalse);
+    if ( ! iDTMFNumber )
+        {
+        iDTMFNumber = postdParm; 
+        if ( iDTMFNumber )
+            {
+            isPostd = ETrue; 
+            }
+        }
+    else 
+        {
+        delete postdParm;     
+        }
+#ifndef __BROWSER_TEL_SERVICES_CALLUI__
+
+    iSendableDTMFNumbers = ParseDTMFSequencesL( iDTMFNumber );
+    iDlgDTMFNumbers = ParseDTMFSequencesForDlgL( iDTMFNumber );
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+    if( ShowDialogL( *number, EConfirmMakeCall ) )
+        {            
+
+#ifndef __WINS__
+        DisconnectActiveCSDConnectionL();
+#endif
+
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+
+        HBufC* temp = NULL;
+        if( iDTMFNumber )
+            {
+            // Confirm the user (s)he wants to send the DTMF
+            if( SendDMFConfQueryL( iDTMFNumber->Des() ) )
+                {
+                if ( !isPostd )
+                    {                    
+                    // Add iDTMFNumber to number
+                    temp = HBufC::NewLC( number->Length() + iDTMFNumber->Length() );
+                    temp->Des().Copy( number->Des() );
+                    temp->Des().Append( iDTMFNumber->Des() );
+                    }
+                else 
+                    {
+                    // Add p+iDTMFNumber to number for postd
+                    temp = HBufC::NewLC( number->Length() + iDTMFNumber->Length() + 1 /*for the 'p' character*/ );
+                    temp->Des().Copy( number->Des() );
+                    temp->Des().Append( 'p' );
+                    temp->Des().Append( iDTMFNumber->Des() );                        
+                    }
+                }
+            else
+                {
+                // Call number without dtmf
+                temp = number->AllocLC();
+                }
+            }
+        else
+            {
+            temp = number->AllocLC();
+            }
+
+        temp = temp->ReAllocL( temp->Length() + params->Length() );
+        CleanupStack::Pop( temp ); // location may have changed, update cleanupstack
+        CleanupStack::PushL( temp );
+        temp->Des().Append( *params );  
+
+        // ... and make the call
+        DoMakeCallL( *temp, voipCall );
+
+        CleanupStack::PopAndDestroy( temp ); // temp
+
+#else // __BROWSER_TEL_SERVICES_CALLUI__
+
+        // ... and make the call
+        DoMakeCallL( *number, voipCall );
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+        }
+    else
+        {
+        User::Leave( KErrCancel );
+        }
+
+    CleanupStack::PopAndDestroy( 3 );   // orgNumber, params, number
+    }
+
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendDMFConfQueryL()
+//---------------------------------------------------------------------------------------
+//
+TBool CBrowserTelService::SendDMFConfQueryL( const TDesC& aDTMF )
+    {
+    TBool retVal( EFalse );
+
+
+    TELSERVICE_ENTERFN( "SendDMFConfQueryL()" )
+
+    if( 0 == aDTMF.Length() )
+        {
+        return retVal;
+        }
+
+    CRepository* repository = CRepository::NewL( KCRUidBrowser );
+    CleanupStack::PushL (repository );
+    repository->Get( KBrowserConfirmedDTMFOnce, iConfirmedOnce );    
+        
+    TELSERVICE_WRITE( "display send dtmf dialog" )
+
+    if( iDTMFAlwaysConfirm )
+        {
+        retVal = ShowDialogL( aDTMF, EConfirmSendDTMF );
+        }
+    else if( iDTMFAlwaysConfirm == EFalse && 
+             iConfirmedOnce == EFalse )
+        {
+        retVal = ShowDialogL( aDTMF, 
+							  EConfirmSendDTMF );
+        iConfirmedOnce = ETrue;
+        repository->Set( KBrowserConfirmedDTMFOnce, iConfirmedOnce ); 		
+        }
+
+    CleanupStack::PopAndDestroy( repository ); 
+    
+    return retVal;
+    }
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::CleanupBuffs()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::CleanupBuffers()
+    {
+    if( iSendableDTMFNumbers )
+        {
+        iSendableDTMFNumbers->ResetAndDestroy();
+        delete iSendableDTMFNumbers;
+		iSendableDTMFNumbers = NULL;
+        }
+
+    if( iDlgDTMFNumbers )
+        {
+        iDlgDTMFNumbers->ResetAndDestroy();
+        delete iDlgDTMFNumbers;
+		iDlgDTMFNumbers = NULL;
+        }
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::DoMakeCallL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::DoMakeCallL( TDesC& aNumber, TBool voipCall )
+	{
+    TELSERVICE_ENTERFN( "DoMakeCallL()" )
+   
+#ifndef __BROWSER_TEL_SERVICES_CALLUI__
+
+    RTelServer::TPhoneInfo info;
+    RPhone::TLineInfo lineInfo;
+	
+    // Connect to the telephony server and load the TSY.
+    User::LeaveIfError( iRTelServer.Connect() );
+    User::LeaveIfError( iRTelServer.LoadPhoneModule( KMmTsyModuleName ) );
+    // Get the details for the first (and only) phone.
+    User::LeaveIfError( iRTelServer.GetPhoneInfo( 0, info ) );
+    // Open the phone.
+    User::LeaveIfError( iRPhone.Open( iRTelServer, info.iName ) );
+    // Get the information for the voice line, line 0.
+    User::LeaveIfError( iRPhone.GetLineInfo( 0, lineInfo ) );
+    // Open the line. iName will now be "VoiceLine1".
+    User::LeaveIfError( iRLine.Open( iRPhone, KMmTsyVoice1LineName ) );     
+	TInt count;
+	// Gets the number of calls opened from a line.	
+	User::LeaveIfError( iRLine.EnumerateCall( count ) );
+	if ( count > 2 )
+		{
+		HBufC* text = StringLoader::LoadL(
+			R_TEXT_CALL_NOT_ALLOWED, 
+			 CEikonEnv::Static() );
+		CleanupStack::PushL( text );
+		TDialerDialogs::ErrorNoteL( *text );
+		CleanupStack::PopAndDestroy();// text
+		User::Leave( KErrNone );		
+		}
+
+	// Open a new phone call.
+    User::LeaveIfError( iRCall.OpenNewCall( iRLine ) );
+
+    // Initialize state
+    SetState( EDialing );
+
+    // Actually dial the specified number.
+    iRCall.Dial( iStatus, aNumber );
+    SetActive();
+
+    NotifyObservers();
+
+    if( iSynch )
+		{
+        TELSERVICE_WRITE( "starting DoMakeCallL wait loop" )
+		iWait.Start();  // start the wait loop. DoMakeCallL() method won't 
+						// return until iWait->AsyncStop() is called in RunL()
+        TELSERVICE_WRITE( "DoMakeCallL wait loop stopped" )
+
+        if( iRetVal == KErrNone )
+            {
+            if( HandleInternalSendDTMFL() )
+                {
+                TELSERVICE_WRITE( "starting HandleInternalSendDTMFL wait loop" )
+                iInternalDTMFWaitStarted = ETrue;
+                iWait.Start();
+				iRAdvGsmPhone.Close();
+                TELSERVICE_WRITE( "HandleInternalSendDTMFL wait loop stopped" )
+
+                if( iWaitDlg )
+                    {
+                    iWaitDlg->ProcessFinishedL();
+                    }
+                iInternalDTMFWaitStarted = EFalse;
+                }
+            }
+        else
+            {
+            User::Leave( iRetVal );
+		    }
+	    }
+
+#else // __BROWSER_TEL_SERVICES_CALLUI__
+
+	if(!iServiceHandler)
+		{
+    	iServiceHandler = CAiwServiceHandler::NewL();
+		}
+    iServiceHandler->AttachL( R_BROWSERTELSERVICES_MENU_AIW_INTERESTS );
+
+
+    CAiwGenericParamList& paramList = iServiceHandler->InParamListL();
+    CAiwGenericParamList& output = iServiceHandler->OutParamListL();
+
+    TPtrC number = aNumber;
+
+    iDialData->SetPhoneNumberL( number );
+    if( !voipCall )
+    {
+    	iDialData->SetCallType( CAiwDialData::EAIWVideo );
+    }
+    else
+    {
+    	iDialData->SetCallType( CAiwDialData::EAIWVoiP );
+    }
+    iDialData->FillInParamListL( paramList );
+
+    iServiceHandler->ExecuteServiceCmdL(
+                    KAiwCmdCall,
+                    paramList,
+                    output,
+                    0,      // No options used.
+                    this ); //
+
+    if( iSynch )
+        {
+        iWait.Start();
+        }
+ 
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+    TELSERVICE_LEAVEFN( "DoMakeCallL()" )
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendDTMFL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::SendDTMFL( TDesC& aNumber, TBool aSendDTMFAlwaysConfirm )
+    {
+    iDTMFAlwaysConfirm = aSendDTMFAlwaysConfirm;
+
+    iRetVal = KErrNone;
+	CheckIsThereActivateVoiceCallOnL();
+
+    if( State() == EConnected )
+	    {
+        CheckDTMFNumberL( aNumber );
+
+        // Set flag to indicate that synchronous method was called
+        iSynch = ETrue;
+
+        delete iSendableDTMFNumbers;
+        iSendableDTMFNumbers = NULL;
+
+        delete iDlgDTMFNumbers;
+        iDlgDTMFNumbers = NULL;
+
+        iSendableDTMFNumbers = ParseDTMFSequencesL( &aNumber );
+        iDlgDTMFNumbers = ParseDTMFSequencesForDlgL( &aNumber );
+
+        if( HandleInternalSendDTMFL() )
+            {
+            TELSERVICE_WRITE( "starting HandleInternalSendDTMFL wait loop" )
+            iInternalDTMFWaitStarted = ETrue;
+            iWait.Start();
+            TELSERVICE_WRITE( "HandleInternalSendDTMFL wait loop stopped" )
+
+            if( iWaitDlg )
+                {
+                iWaitDlg->ProcessFinishedL();
+                }
+            iInternalDTMFWaitStarted = EFalse;
+            }
+
+        // Unset flag
+        iSynch = EFalse;
+	    }
+    else    // no active voice connection 
+		{
+        User::Leave( KErrNoCallActive );
+		}
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendDTMFL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::SendDTMFL( TRequestStatus& aStatus,TDesC& aNumber, 
+						            TBool aSendDTMFAlwaysConfirm )
+    {
+    iDTMFAlwaysConfirm = aSendDTMFAlwaysConfirm;
+
+    aStatus = KRequestPending;
+    iUserRequestStatus = &aStatus;
+	CheckIsThereActivateVoiceCallOnL();
+	
+    if( State() == EConnected )
+		{
+        CheckDTMFNumberL( aNumber );
+
+        if( iSendableDTMFNumbers )
+            {
+            iSendableDTMFNumbers->ResetAndDestroy();
+            }
+        delete iSendableDTMFNumbers;
+        iSendableDTMFNumbers = NULL;
+
+        if( iDlgDTMFNumbers )
+            {
+            iDlgDTMFNumbers->ResetAndDestroy();
+            }
+        delete iDlgDTMFNumbers;
+        iDlgDTMFNumbers = NULL;
+
+        iSendableDTMFNumbers = ParseDTMFSequencesL( &aNumber );
+        iDlgDTMFNumbers = ParseDTMFSequencesForDlgL( &aNumber );
+
+        HandleInternalSendDTMFL();
+		}
+    else    // no active voice connection 
+		{
+        User::Leave( KErrNoCallActive );
+		}
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::DoSendDTMFL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::DoSendDTMFL( TDesC& aNumber )
+	{
+    TELSERVICE_ENTERFN( "DoSendDTMFL()" )
+
+    CheckIsThereActivateVoiceCallOnL();
+    
+    if( State() == EConnected )
+		{
+        // Cancel any outstanding requests
+        Cancel();
+
+        RTelServer::TPhoneInfo info;
+        User::LeaveIfError( iRTelServer.GetPhoneInfo( 0, info ) );
+        User::LeaveIfError( iRAdvGsmPhone.Open( iRTelServer, info.iName ) );
+        
+        // Set state
+        SetState( EDialingDTMF );
+        // Notify the observer
+        NotifyObservers();
+
+        // Send DTMF tones
+        if( aNumber.Length() )
+            {
+            iRAdvGsmPhone.SendDTMFTones( iStatus, aNumber );
+            }
+        else
+            {
+            TRequestStatus* status = &iStatus;
+            User::RequestComplete( status, KErrNone );
+            }
+
+        SetActive();
+
+        if( iSynch )
+			{
+            iWait.Start();  // start the wait loop. DoSendDTMFL() 
+							// method won't return 
+                            // until iWait->AsyncStop() is called in RunL() 
+			}
+		}
+    else
+        {
+        User::Leave( KErrCancel );
+        }
+
+    TELSERVICE_LEAVEFN( "DoSendDTMFL()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ValidateNumberL()
+//---------------------------------------------------------------------------------------
+//
+HBufC* CBrowserTelService::ValidateNumberL( TDesC& aNumber )
+	{
+    TELSERVICE_ENTERFN( "ValidateNumberL()" )
+
+    HBufC* buf = HBufC::NewLC( aNumber.Length() );
+    TPtr ptr = buf->Des();
+	ptr.Copy( aNumber );
+
+    for( TInt i = 0; i < ptr.Length(); i++ )
+        {
+        TChar currentChar = ptr[i];
+
+        if( currentChar.IsSpace() )
+            {
+            ptr.Delete( i, 1 );
+            i--;
+            }
+        else if( !currentChar.IsDigit() )
+            {
+            if( currentChar == '+' )
+                {
+                if( i != 0 )
+                    {
+                    User::Leave( KErrInvocationError );
+                    }
+                }
+            else
+                {
+                currentChar.UpperCase();
+
+                switch( currentChar )
+                    {
+                    case '*':
+                    case '#':
+                    case 'A':
+                    case 'B':
+                    case 'C':
+                    case 'D':
+                    case 'P':
+                    case 'W':
+                    case ',':
+                    case '/':
+                        if( i == 0 )
+                            {
+                            User::Leave( KErrInvocationError );
+                            }
+                        break;
+						
+					case '.': 
+					case '-':
+					case '(':
+					case ')':
+                        {
+			            ptr.Delete( i, 1 );
+						i--;
+                        }
+						break; 
+
+                    default:
+                        // invalid character in the phone number
+                        {
+                        User::Leave( KErrInvocationError );
+                        }
+                        break;
+                    }
+                }
+            }
+        }
+
+    CleanupStack::Pop( buf );   // buf
+
+    TELSERVICE_LEAVEFN( "ValidateNumberL()" )
+	return buf;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::FindAndHandlePostdL()
+//---------------------------------------------------------------------------------------
+//
+HBufC* CBrowserTelService::FindPostdParmL( TDes& aNumber )
+    {
+    TELSERVICE_ENTERFN( "FindPostdParmL()" )
+    
+    HBufC* buf = NULL;    
+    _LIT( KPostd, ";postd=" ); 
+    TInt ret = aNumber.Find( KPostd );
+    if ( ret != KErrNotFound )
+        {
+        buf = aNumber.Mid( ret + KPostd().Length() ).AllocL(); 
+        aNumber.SetLength ( ret );
+        }
+    TELSERVICE_LEAVEFN( "FindPostdParmL()" )
+    return buf;            
+    }
+
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::FindAndRipDTMFSequenceL()
+//---------------------------------------------------------------------------------------
+//
+HBufC* CBrowserTelService::FindAndRipDTMFSequenceL( TDes* aNumber )
+    {
+    TELSERVICE_ENTERFN( "FindAndRipDTMFSequnceL()" )
+
+    HBufC* buf = NULL;    
+
+	TPtrC waitChars;
+	waitChars.Set( KDTMFWaitChars );
+
+    // Look for the first DTMF-wait char and extract the
+    // dtmf string from the phonenumber
+    for( TInt i = 0; i < aNumber->Length(); i++ )
+        {
+        if( ( waitChars.Locate( (*aNumber)[i] ) != KErrNotFound ) )
+            {
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+
+            buf = aNumber->Mid(i).AllocL();
+            aNumber->Delete( i, buf->Length() );
+
+            // Remove all the invalid wait chars from 
+            // the sequence which is not accepted by CallUi
+	        TPtrC invalidWaitChars;
+	        invalidWaitChars.Set( KDTMFInvalidWaitChars );
+
+            for( TInt j = 0; j < buf->Length(); j++ )
+                {
+                if( ( invalidWaitChars.Locate( (*buf)[j] ) != KErrNotFound ) )
+                    {
+                    TPtr ptr = buf->Des();
+                    ptr.Replace( j, 1,KDTMFValidPause() );
+                    }
+                }
+
+#else // __BROWSER_TEL_SERVICES_CALLUI__
+
+            if( (*aNumber)[i] == '#' ||
+                (*aNumber)[i] == '*' )
+                // these chars are parts of the dtms sequence
+                {
+                buf = aNumber->Mid(i).AllocL();
+                aNumber->Delete( i, buf->Length() );
+                }
+            else
+                {
+                // +1 -> wait char is not part of the dtmf sequence
+                buf = aNumber->Mid(i+1).AllocL();
+                aNumber->Delete( i, buf->Length() + 1);
+                }
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+            break;
+            }
+        }
+    TELSERVICE_LEAVEFN( "FindAndRipDTMFSequenceL()" )
+    return buf;    
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::FindAndRipURIParametersL()
+//---------------------------------------------------------------------------------------
+//
+HBufC* CBrowserTelService::FindAndRipURIParametersL( TDes& aNumber )
+    {
+    TELSERVICE_ENTERFN( "FindAndRipURIParametersL()" )
+
+    HBufC* buf = NULL;    
+    TInt offset = aNumber.Locate( TChar( ';' ) );
+    if( offset > 0 ) // Separator is not allowed to be a first char
+        {
+        __ASSERT_DEBUG( offset <= aNumber.Length(), User::Leave( KErrGeneral ) );
+        buf = aNumber.Mid( offset ).AllocL();         
+        aNumber.SetLength( offset );           
+        }
+    else
+        {
+        buf = HBufC::NewL( 0 );
+        }
+
+    TELSERVICE_LEAVEFN( "FindAndRipURIParametersL()" )
+    return buf;    
+    }
+    
+    
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::FindAndRipVoipParametersL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::FindAndRipVoipParametersL( TDes& aNumber )
+    {
+    TELSERVICE_ENTERFN( "FindAndRipVoipParametersL()" )
+
+    HBufC* buf = NULL;    
+    TInt offset = aNumber.Locate( TChar( '@' ) );
+    if( offset > 0 ) // Separator is not allowed to be a first char
+        {
+        __ASSERT_DEBUG( offset <= aNumber.Length(), User::Leave( KErrGeneral ) );
+        buf = aNumber.Mid( offset ).AllocL();         
+        aNumber.SetLength( offset );           
+        }
+    else
+        {
+        buf = HBufC::NewL( 0 );
+        }
+
+    TELSERVICE_LEAVEFN( "FindAndRipVoipParametersL()" )
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ValidateDTMFNumberL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::ValidateDTMFNumberL( TDes* aNumber )
+    {
+    TELSERVICE_ENTERFN( "ValidateDTMFNumberL()" )
+
+    TPtrC validDTMFChars;
+    validDTMFChars.Set( KValidDTMFChars );
+
+    if( aNumber )
+        {
+        for( TInt i = 0; i < aNumber->Length(); i++ )
+            {
+            if( ( validDTMFChars.Locate( (*aNumber)[i] ) == KErrNotFound ) )
+                {
+                // Invalid character found, remove it!
+                aNumber->Delete( i, 1 );
+                i--;
+                }
+            }
+        }
+    TELSERVICE_LEAVEFN( "ValidateDTMFNumberL()" )
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ParseDTMFSequencesForDlg()
+//---------------------------------------------------------------------------------------
+//
+CArrayPtrFlat<HBufC>* CBrowserTelService::ParseDTMFSequencesForDlgL(
+										  const TDesC* aDTMFString )
+    {
+    TELSERVICE_ENTERFN( "ParseDTMFSequencesForDlgL()" )
+    CArrayPtrFlat<HBufC>* parsedArray = NULL;
+    
+    if( aDTMFString )
+    {
+    parsedArray = new ( ELeave ) CArrayPtrFlat<HBufC>( KParseArrayAllocation ); 
+    
+    TLex dtmfSequence( *aDTMFString );
+
+    TChar previousChar = dtmfSequence.Peek();   // first char
+
+    while( !dtmfSequence.Eos() )
+        {
+        //
+        if ( dtmfSequence.Offset() ) // if not at start of line
+            {
+            TChar nextChar = dtmfSequence.Peek();
+            if( nextChar == '/' || nextChar == 'w' || nextChar == 'p' ||
+				nextChar == ',' )
+                {
+                // if the previous wait char was either 'w' or '/' then skip it
+                // and mark new extraction mark.
+                if( previousChar == 'w' || previousChar == '/' )
+                    {
+                    dtmfSequence.Mark();
+                    }
+                else
+                    {
+                    parsedArray->AppendL(
+						dtmfSequence.RemainderFromMark().Alloc() );
+                    dtmfSequence.Mark();            
+                    }
+                }
+            previousChar = nextChar;
+            }
+    
+        dtmfSequence.Inc();
+        }
+
+    parsedArray->AppendL( dtmfSequence.RemainderFromMark().Alloc() );
+    }
+    TELSERVICE_LEAVEFN( "ParseDTMFSequencesForDlgL()" )
+    return parsedArray;
+    }
+
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ParseDTMFSequencesForDlg()
+//---------------------------------------------------------------------------------------
+//
+CArrayPtrFlat<HBufC>* CBrowserTelService::ParseDTMFSequencesL(
+									const TDesC* aDTMFString )
+    {
+    TELSERVICE_ENTERFN( "ParseDTFMSequencesL()" )
+    CArrayPtrFlat<HBufC>* parsedArray = NULL;
+
+    if( aDTMFString )
+		{		
+		parsedArray = new ( ELeave ) CArrayPtrFlat<HBufC>( 
+			KParseArrayAllocation );
+        CleanupStack::PushL( parsedArray );
+    
+		TLex dtmfSequence( *aDTMFString );
+
+		TChar previousChar = dtmfSequence.Peek();   // first char
+
+		while( !dtmfSequence.Eos() )
+			{
+			//
+			if ( dtmfSequence.Offset() ) // if not at start of line
+				{
+				TChar nextChar = dtmfSequence.Peek();
+				if( nextChar == '/' || nextChar == 'w' || 
+					nextChar == 'p' || nextChar == ',' )
+					{
+					// if the previous wait char was either 'w' or '/' 
+					// then skip it
+					// and mark new extraction mark.
+					if( previousChar == 'w' || previousChar == '/' )
+						{
+						dtmfSequence.Mark();
+						}
+					else
+						{
+						parsedArray->AppendL(
+							dtmfSequence.MarkedToken().Alloc() );
+						dtmfSequence.Mark();            
+						}
+					}
+				previousChar = nextChar;
+				}
+    
+			dtmfSequence.Inc();
+			}
+
+		parsedArray->AppendL( dtmfSequence.RemainderFromMark().Alloc() );
+
+        CleanupStack::Pop( parsedArray );
+		}
+    TELSERVICE_LEAVEFN( "ParseDTMFSequencesL()" )
+    return parsedArray;
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::DisplaySendDTMFDialog()
+//---------------------------------------------------------------------------------------
+//
+TBool CBrowserTelService::DisplaySendDTMFDialog( TDes* aNumber )  
+    {
+    TELSERVICE_ENTERFN( "DisplaySendDTMFDialog()" )
+    TBool ret = EFalse;
+
+    if( aNumber )
+        {
+        TInt length = aNumber->Length();
+        if( length )
+            {
+            TChar waitChar = RipWaitChar( aNumber );
+            
+            switch( waitChar )
+                {
+                case '/':
+                case 'w':
+					{
+                    ret = ETrue;
+					}
+                    break;
+
+                case 'p':
+                case ',':
+					{
+                    ret = EFalse;
+					}
+                    break;
+
+                default:
+					{
+                     ret = ((iDTMFAlwaysConfirm) || (!iConfirmedOnce));
+					}
+                    break;
+                }
+            }
+        }
+    TELSERVICE_LEAVEFN( "DisplaySendDTMFDialog()" )
+    return ret;
+    }  
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::RipWaitChar()
+//---------------------------------------------------------------------------------------
+//
+TChar CBrowserTelService::RipWaitChar( TDes* aNumber )
+    {
+    TELSERVICE_ENTERFN( "RipWaitChar()" )
+    TChar waitChar = NULL;
+    if( aNumber )
+        {
+        TInt length = aNumber->Length();
+        if( length )
+            {
+            TChar tempWaitChar = ( *aNumber )[0];
+            if( tempWaitChar == 'w' || tempWaitChar == '/' || 
+                tempWaitChar == 'p' || tempWaitChar == ',')
+                {
+                waitChar = tempWaitChar;
+                aNumber->Delete( 0, 1 );
+                }
+            }
+        }
+    TELSERVICE_LEAVEFN( "RipWaitChar()" )
+    return waitChar;
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendDTMF()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::SendDTMF( TDesC& aNumber, 
+										    TBool aSendDTMFAlwaysConfirm )
+	{
+    TELSERVICE_ENTERFN( "SendDTMF() synchronous" )
+
+    iRetVal = KErrNone;
+
+    TRAPD( err, SendDTMFL( aNumber, aSendDTMFAlwaysConfirm ) );
+
+    if( err )
+        {
+        ErrorHandler( err );
+        iRetVal = KErrCancel;
+        }
+
+    TELSERVICE_LEAVEFN( "SendDTMF() synchronous" )
+    return iRetVal;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendDTMFL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C void CBrowserTelService::SendDTMF( TRequestStatus& aStatus,
+										    TDesC& aNumber, 
+										    TBool aSendDTMFAlwaysConfirm )
+	{
+    TELSERVICE_ENTERFN( "SendDTMF() asynchronous" )
+
+    iRetVal = KErrNone;
+
+    TRAPD( err, SendDTMFL( aStatus, aNumber, aSendDTMFAlwaysConfirm ) );
+
+    if( err )
+        {
+        TELSERVICE_WRITE_FORMAT( "Complete the request: %d", KErrInvocationError )
+
+        ErrorHandler( err );
+
+        User::RequestComplete( iUserRequestStatus, KErrInvocationError );
+        }
+    
+    TELSERVICE_LEAVEFN( "SendDTMF() asynchronous" )    
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::CancelSendDTMFL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C void CBrowserTelService::CancelSendDTMFL()
+	{
+    TELSERVICE_ENTERFN( "CancelSendDTMF()" )
+
+    if( State() == EDialingDTMF )
+		{
+        RCall::TStatus callStatus;
+        User::LeaveIfError( iRCall.GetStatus( callStatus ) );
+
+        if( callStatus == RCall::EStatusConnected )
+			{
+            if( State() == EDialingDTMF )
+				{
+                Cancel();
+                SetState( EConnected );
+				}
+			}
+		}
+
+    TELSERVICE_LEAVEFN( "CancelSendDTMF()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::AddPBEntryL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::AddPBEntryL(
+								TDesC& aNumber, 
+								TDesC& aName, 
+								TDesC& aEmail )
+    {
+    TELSERVICE_ENTERFN( "AddPBEntryL()" )
+
+    CPbkContactEngine* pbkEngine = CPbkContactEngine::NewL();
+    CleanupStack::PushL( pbkEngine );
+
+    // Make sure a resource file is available
+    RPbkViewResourceFile pbkResourceFile( *CCoeEnv::Static() );
+    pbkResourceFile.OpenL();
+    CleanupClosePushL<RPbkViewResourceFile> ( pbkResourceFile );
+	
+	// Step 1: Search Pb for matches and open existing or create new
+    TBool newContact;
+    CPbkContactItem* contactItem = SearchPBItemLC( *pbkEngine
+                                                   , aNumber
+                                                   , aEmail
+                                                   , newContact );
+
+    TPtrC lastName;
+    TPtrC firstName;
+	TPtrC email;
+
+	email.Set( aEmail );
+
+	// Step 2: Set values to the correct lines
+    // default focused dialog line 
+    TInt formIndex = -1;
+
+    if( JAPANESE )
+        // Japanese version only. See Vodafone spec: 
+        // http://developers.vodafone.jp/dp/tool_dl/download.php?docid=120
+        {
+        TPtrC lastNameReading;
+
+        TInt yomiganaInd = aName.LocateReverse( TChar('-') );
+
+        if( yomiganaInd != KErrNotFound )
+            {
+            lastNameReading.Set( aName.Right( aName.Length() - yomiganaInd - 1 ) );
+            lastName.Set( aName.Left( yomiganaInd ) );
+            }
+        else
+            {
+            lastName.Set( aName );
+            }
+
+        SetPBEntryFieldL( EPbkFieldIdLastName, pbkEngine, contactItem, lastName, formIndex );
+        SetPBEntryFieldL( EPbkFieldIdLastNameReading, pbkEngine, contactItem, lastNameReading, formIndex );
+        }
+    else
+        {
+        TInt lastNameInd = aName.LocateReverse( TChar(' ') );
+	    TBool whichtag = EFalse;
+	    if ( lastNameInd == KErrNotFound )
+		    {
+		    _LIT( tag, "%20" );
+		    lastNameInd = aName.Find( tag );
+		    whichtag = ETrue;
+		    }
+	    
+        if( lastNameInd != KErrNotFound )
+		    {
+            if( lastNameInd )
+			    {
+			    if ( whichtag )
+				    {
+				    lastName.Set( aName.Right( aName.Length() - lastNameInd - 3 ) );
+				    }
+			    else
+				    {
+				    lastName.Set( aName.Right( aName.Length() - lastNameInd - 1 ) );
+				    }            
+                firstName.Set( aName.Left( lastNameInd ) );
+			    }
+            else
+			    {
+                lastName.Set( aName );
+			    }
+		    }
+        else
+		    {
+            lastName.Set( aName );
+		    }
+
+        SetPBEntryFieldL( EPbkFieldIdLastName, pbkEngine, contactItem, lastName, formIndex );
+        SetPBEntryFieldL( EPbkFieldIdFirstName, pbkEngine, contactItem, firstName, formIndex );
+        }
+
+    // common fields
+    SetPBEntryFieldL( EPbkFieldIdPhoneNumberStandard, pbkEngine, contactItem, aNumber, formIndex );
+    SetPBEntryFieldL( EPbkFieldIdEmailAddress, pbkEngine, contactItem, aEmail, formIndex );
+
+    // Step 3: Open the editor dialog
+    CPbkContactEditorDlg* dlg = CPbkContactEditorDlg::NewL(
+		*pbkEngine, *contactItem, newContact, formIndex, formIndex >= 0 ); 
+    
+    // Execute phonebook editor
+    dlg->ExecuteLD();
+
+    CleanupStack::PopAndDestroy( 3 ); // contactItem, pbkResourceFile, pbkEngine
+
+    TELSERVICE_LEAVEFN( "AddPBEntryL()" )
+
+    return KErrNone;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::State()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TBrowserTelServiceState CBrowserTelService::State() const
+	{
+    TELSERVICE_WRITE_FORMAT( "State(): %d", iState )
+    return iState;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SetState()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::SetState( TBrowserTelServiceState aState )
+	{
+    TELSERVICE_WRITE( "SetState()" )
+    iState = aState;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::AddObserver()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C void CBrowserTelService::AddObserver(
+								MBrowserTelServiceObserver* aObserver )
+	{
+    TELSERVICE_ENTERFN( "AddObserver()" )
+
+    if( aObserver )
+        {
+        iObserverList.Append( aObserver );
+		}
+    TELSERVICE_LEAVEFN( "AddObserver()" )
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::RemoveObserver()
+//---------------------------------------------------------------------------------------
+
+EXPORT_C void CBrowserTelService::RemoveObserver(
+								MBrowserTelServiceObserver* aObserver )
+	{
+    TELSERVICE_ENTERFN( "RemoveObserver()" )
+
+    TInt count = iObserverList.Count();
+    if( count )
+	    {
+        TInt index = iObserverList.Find( aObserver );
+        if( index != KErrNotFound )
+		    {
+            iObserverList.Remove( index );
+            iObserverList.GranularCompress();
+		    }
+		}
+    TELSERVICE_LEAVEFN( "AddObserver()" )
+	}
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendEmailMessageL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::SendEmailMessageL(
+												const TDesC& aToRecipients,
+												const TDesC& aCcRecipients, 
+                                                const TDesC& aParams,
+												const TDesC& aBody )
+	{ 	
+	return this->SendEmailMessageL( aToRecipients, aCcRecipients,
+									aParams, aBody, 0 );
+	}
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendEmailMessageL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::SendEmailMessageL( 
+												const TDesC& aToRecipients,
+												const TDesC& aCcRecipients, 
+                                                const TDesC& aParams,
+												const TDesC& aBody,
+												TBool aLaunchEmbedded )
+	{ 
+    TELSERVICE_ENTERFN( "SendEmailMessageL()" )
+	
+    ///////////////////////////////////////////////////////////////
+    // Determine if mailto handled via MMS from variation mechanism
+    TBool sendMms( EFalse );
+    TInt keyVal( 0 );
+    CRepository* repository = CRepository::NewL( KCRUidBrowserUiLV );
+    CleanupStack::PushL( repository );
+    if(repository->Get( KBrowserMailtoSendingApp, keyVal ) == KErrNone )
+        {
+        sendMms = ( keyVal == 1 );
+        }
+    CleanupStack::PopAndDestroy( repository );    
+
+    //Search for @ and .(dot) characters
+    TInt at  = aToRecipients.Locate('@');
+    TInt dot = aToRecipients.Locate('.');
+    TInt len = aToRecipients.Length();
+    if(len > 0 && KErrNotFound == at && KErrNotFound == dot)
+    {
+        TELSERVICE_WRITE("CBrowserTelService::SendEmailMessageL chars @ and .(dot) are not present");
+        sendMms = ETrue;
+        //Make sure all chars are numbers only except first char '+'
+        TInt loopCounter = 0;
+        const TUint16 *ptr = aToRecipients.Ptr();
+        
+        if(*ptr == '+')
+        {
+           ptr = ptr + 1;
+           loopCounter = 1;
+        }
+                   
+        for(loopCounter; loopCounter<len; loopCounter++)
+        {
+            if( (*ptr >= '0' && *ptr <= '9') || *ptr == ',')
+            {
+                TELSERVICE_WRITE_FORMAT("CBrowserTelService::SendEmailMessageL character: %c", *ptr );
+                ptr = ptr + 1;
+                continue;
+            }
+            else
+            {
+               TELSERVICE_WRITE_FORMAT("CBrowserTelService::SendEmailMessageL found invalid character: %c", *ptr );
+               TELSERVICE_WRITE("CBrowserTelService::SendEmailMessageL chars otherthan numbers are present");
+               sendMms = EFalse;
+               break;
+            }
+        }
+    }
+    
+    if ( sendMms )
+        {
+        TELSERVICE_WRITE("CBrowserTelService::SendEmailMessageL Sending MMS message");
+        return SendMmsMessageL( aToRecipients, aCcRecipients, aParams, aBody, aLaunchEmbedded );
+        }
+
+    /////////////////////////////////
+    // Email editor is launched.
+    TInt cleanUpCount = 0;
+    
+    CParaFormatLayer* paraFormat = CParaFormatLayer::NewL();
+    CleanupStack::PushL( paraFormat );
+    ++cleanUpCount;
+
+    CCharFormatLayer* charFormat = CCharFormatLayer::NewL(); 
+    CleanupStack::PushL( charFormat );
+    ++cleanUpCount;
+
+    CRichText* body = CRichText::NewL( paraFormat, charFormat );
+    CleanupStack::PushL( body );
+    ++cleanUpCount;
+
+    if( aBody.Length() )
+		{
+        body->InsertL( 0, aBody );
+		}
+    else
+		{
+        body->InsertL( 0, KNullDesC );
+		}
+		
+    CPtrC16Array* recipients = ParseRecipientsLC( aToRecipients );
+    ++cleanUpCount;
+    CPtrC16Array* ccrecipients = ParseRecipientsLC( aCcRecipients );
+    ++cleanUpCount;		
+    
+    CSendUi* sendUi = CSendUi::NewL();
+    CleanupStack::PushL( sendUi );
+    ++cleanUpCount;
+    CMessageData* messageData = CMessageData::NewL();
+    CleanupStack::PushL( messageData );
+    ++cleanUpCount;
+    messageData->SetSubjectL( &aParams );
+    messageData->SetBodyTextL( body );
+    for( TInt i = 0; i < recipients->Count(); i++ )
+    	{
+    	messageData->AppendToAddressL( (*recipients)[i] );
+    	}
+    for( TInt j = 0; j < ccrecipients->Count(); j++ )
+    	{
+    	messageData->AppendCcAddressL( (*ccrecipients)[j] );
+    	}
+    	    // check first that the selected mtm supports bodytext
+/*
+    TSendingCapabilities caps( aBody.Size(), 
+                               aBody.Size(), 
+                               TSendingCapabilities::ESupportsBodyText );    	    
+    if( sendUi->ValidateServiceL( KUidMsgTypeSMTP, caps  ) )
+		{
+    	sendUi->CreateAndSendMessageL( KUidMsgTypeSMTP, messageData );
+		} */
+	sendUi->CreateAndSendMessageL( KUidMsgTypeSMTP, messageData );	  
+    
+    CleanupStack::PopAndDestroy( cleanUpCount );
+
+    TELSERVICE_LEAVEFN( "SendEmailMessageL()" )
+    return KErrNone;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SendMmsMessageL()
+//---------------------------------------------------------------------------------------
+//
+TInt CBrowserTelService::SendMmsMessageL( 
+										const TDesC& aToRecipients,
+										const TDesC& aCcRecipients, 
+                                        const TDesC& aParams,
+										const TDesC& aBody,
+										TBool aLaunchEmbedded )
+    {
+    TELSERVICE_ENTERFN( "SendMmsMessageL()" )
+    
+    TInt cleanUpCount = 0;
+    // We give NULL body for the SendUi.
+    CRichText* body = NULL;
+    
+    // We need to write body to file in order to give as a attachment
+    // for the SendUi.
+    CDesCArrayFlat* attachments = NULL;
+    TFileName fileName;
+    TFileName tempPath;
+    CCoeEnv* coeEnv = CCoeEnv::Static();
+	RFs& fs = coeEnv->FsSession();
+
+    attachments = new (ELeave) CDesCArrayFlat(1);
+    CleanupStack::PushL(attachments);
+    ++cleanUpCount;
+    if ( aBody.Length() > 0 )
+        {
+        // Create plaintext object from body
+        CPlainText* text = CPlainText::NewL( CEditableText::EFlatStorage );
+        CleanupStack::PushL( text );
+        text->InsertL( 0, aBody );
+
+        TInt err = KErrNone;
+        RFileWriteStream writer;
+        tempPath.Copy(KTempDrive);  
+  		tempPath.Append(KTempPath);  
+  		err = fs.MkDirAll( tempPath );  
+		if ( err != KErrNone && err != KErrAlreadyExists )
+            {
+            User::Leave( err );
+            }
+        writer.PushL();
+        User::LeaveIfError( writer.Temp( fs, tempPath, fileName, EFileWrite ) );
+        writer.WriteUint16L(CEditableText::EByteOrderMark);
+        text->ExportTextL( 0, writer, 
+            CPlainText::EOrganiseByParagraph );
+        CleanupStack::PopAndDestroy( 2 ); // text, writer
+        attachments->AppendL( fileName );
+        }
+
+    // Create address arrays
+    CPtrC16Array* recipients = ParseRecipientsLC( aToRecipients );
+    ++cleanUpCount;
+    CPtrC16Array* ccrecipients = ParseRecipientsLC( aCcRecipients );
+    ++cleanUpCount;
+    TInt count = ccrecipients->Count();
+    if ( count > 0 )
+        {
+        for (TInt i = 0; i < count; i++)
+            {
+            recipients->AppendL( ccrecipients->At(i) );
+            }
+        }
+    CleanupStack::PopAndDestroy(ccrecipients);
+    --cleanUpCount;
+    ccrecipients = NULL;
+
+    CSendUi* sendUi = CSendUi::NewL();
+    CleanupStack::PushL( sendUi );
+    ++cleanUpCount;
+    CMessageData* messageData = CMessageData::NewL();
+    CleanupStack::PushL( messageData );
+    ++cleanUpCount;    
+    messageData->SetSubjectL( &aParams );
+    messageData->SetBodyTextL( body );
+    for( TInt i = 0; i < recipients->Count(); i++ )
+    	{
+    	messageData->AppendToAddressL( (*recipients)[i] );
+    	}
+    for( TInt j = 0; j < attachments->Count(); j++ )
+    	{
+    	messageData->AppendAttachmentL( (*attachments)[j] );
+    	}    	
+    sendUi->CreateAndSendMessageL( KSenduiMtmMmsUid, messageData, 
+                                   KNullUid, aLaunchEmbedded );
+
+    fs.Delete( fileName );
+    CleanupStack::PopAndDestroy( cleanUpCount );	
+
+    TELSERVICE_LEAVEFN( "SendMmsMessageL()" )
+    return KErrNone;
+    }
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::DisconnectActiveCSDConnectionL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C void CBrowserTelService::DisconnectActiveCSDConnectionL()
+	{
+    TELSERVICE_ENTERFN( "DisconnectActiveCSDConnectionL()" )
+
+    RSocketServ server;
+    RConnection connection;
+    TInt err( KErrNone );
+
+    User::LeaveIfError( server.Connect() );
+    CleanupClosePushL<RSocketServ>( server );
+
+    User::LeaveIfError( connection.Open( server, KAfInet ) );
+    CleanupClosePushL<RConnection>( connection );
+
+    TUint conns( 0 );
+    connection.EnumerateConnections( conns );
+    if( conns )
+        // we need to check if there is any (HS)CSD conneciton
+        {
+        TPckgBuf<TConnectionInfo> connInfo;
+        TBool found = EFalse;
+        TUint index = 1;
+        for( index = 1; index <= conns; ++index )
+            {
+            err = connection.GetConnectionInfo( index, connInfo );
+            if( err == KErrNone )
+                {						
+                TApBearerType bearerType = EApBearerTypeGPRS;
+
+                // Fixing SLAA-6k52P which only happens in MAGNUM. Since
+                // we only need to find if there is CSD or HSCSD, we should
+                // not leave here 
+                TRAP_IGNORE( bearerType = ConnectionTypeL( connInfo().iIapId ) );
+		        
+		        if( bearerType == EApBearerTypeCSD || 
+					bearerType == EApBearerTypeHSCSD )
+			        {
+                    found = ETrue;
+                    }
+                }
+            }
+
+        if( found )
+            // there is active (HS)CSD. We need to close it.
+            {
+            if( ( err = connection.Attach( connInfo, 
+				RConnection::EAttachTypeNormal ) ) == KErrNone )
+                {
+                // disconnect
+                connection.Stop();
+                }
+            TELSERVICE_WRITE( "Found active (HS)CSD connection" )
+            }
+        }
+
+    CleanupStack::PopAndDestroy( 2 ); // connection, server
+
+    TELSERVICE_LEAVEFN( "DisconnectActiveCSDConnectionL()" )
+
+    User::LeaveIfError( err );
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ShowDialogL()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::ShowDialogL(
+								const TDesC& aDynamicText, 
+								const TBrowserTelServiceDlgType& aDlgType)
+	{
+    TELSERVICE_ENTERFN( "ShowDialogL()" )
+
+	TInt retVal = 0;
+
+    switch( aDlgType )
+        {
+        case EConfirmMakeCall:
+		    {
+		    HBufC* number = NULL;
+            HBufC* valNumber = NULL;
+		    HBufC* text = NULL;
+            number = aDynamicText.AllocLC();            
+            
+            valNumber = ValidateNumberL( *number );
+            CleanupStack::PopAndDestroy( number );  // number;
+
+            CleanupStack::PushL( valNumber );
+		    
+            HBufC* name = SearchPbForMatchL( *valNumber );
+			if( name  )
+				{
+				CleanupStack::PushL( name );
+				text = StringLoader::LoadL(
+					R_QTN_WML_WTAI_CALL_NO, *name );
+				CleanupStack::PopAndDestroy();	// name
+				CleanupStack::PushL( text );
+				}
+			else
+				{
+				text = StringLoader::LoadLC(
+    				R_QTN_WML_WTAI_CALL_NO, *valNumber );
+                }
+			
+			retVal = TDialerDialogs::ConfirmationDlgL(
+				*text, R_CONFIRMATION_DIALOG );
+
+			CleanupStack::PopAndDestroy( 2 );	// valNumber, text
+		    }
+            break;
+
+        case EConfirmSendDTMF:
+		    {
+		    HBufC* text = StringLoader::LoadLC(
+				R_QTN_WML_WTAI_SEND_DTMF, aDynamicText, CEikonEnv::Static() );
+		    retVal = TDialerDialogs::ConfirmationDlgL(
+				*text, R_CONFIRMATION_DIALOG );
+		    CleanupStack::PopAndDestroy();	// text
+		    }
+            break;
+
+        case EConfirmAddToPb:
+		    {
+		    TInt index = 0;
+			CAknListQueryDialog* dlg = 
+				new( ELeave ) CAknListQueryDialog( &index );
+			if ( dlg->ExecuteLD( R_ADD_TO_CONTACTS_DIALOG ) )
+				{
+				return index;
+				}
+			else
+				{
+				User::Leave( KErrCancel );
+				}
+		    }
+            break;
+
+        case ESendingDTMF:
+            {
+			HBufC* text = StringLoader::LoadLC(
+			R_QTN_DTMF_SENDING_WAIT_NOTE, 
+			aDynamicText, CEikonEnv::Static() );
+			if( !iWaitDlg )
+				{
+				TELSERVICE_WRITE( "Create Sending DTMF wait dialog" )
+				iWaitDlg = new ( ELeave ) CAknWaitDialog(
+				reinterpret_cast<CEikDialog**>( &iWaitDlg ), ETrue );
+				iWaitDlg->SetCallback( this );
+				iWaitDlg->PrepareLC( R_SENDDTMF_DIALOG );
+				iWaitDlg->SetTextL( *text );
+				iWaitDlg->RunLD();
+				}
+			else
+				{
+				TELSERVICE_WRITE( "Update Sending DTMF wait dialog" )
+					iWaitDlg->SetTextL( *text ); // Just update the text
+				}
+            CleanupStack::PopAndDestroy();  // text
+            }
+            break;
+        default:
+            break;
+        }
+    TELSERVICE_LEAVEFN( "ShowDialogL()" )
+	return retVal;
+	}
+
+
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::MakeVOIPCall()
+//---------------------------------------------------------------------------------------
+//
+EXPORT_C TInt CBrowserTelService::MakeVOIPCall( TDesC& aNumber, 
+										    TBool aSendDTMFAlwaysConfirm )
+	{
+    TELSERVICE_ENTERFN( "MakeVOIPCall() synchronous" )
+       
+    TInt retVal( KErrNone );
+
+    iRetVal = KErrNone;
+
+    // Flag to indicate that synchronous method was called
+    iSynch = ETrue;
+    TBool voipCall = ETrue;
+    TRAP( retVal, MakeCallL( aNumber, aSendDTMFAlwaysConfirm, voipCall ) );
+
+    if( retVal != KErrNone )
+		{
+        ErrorHandler( retVal );
+
+        retVal = KErrCancel;
+        }
+    iSynch = EFalse;
+
+    TELSERVICE_LEAVEFN( "MakeVOIPCall() synchronous" )
+    return retVal;
+	}
+	
+	
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::DoCancel()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::DoCancel()
+	{
+    TELSERVICE_ENTERFN( "DoCancel()" )
+
+    switch( State() )
+	    {
+        case EDialing:
+			{
+            iRCall.DialCancel();
+			}
+            break;
+
+        case EDialingDTMF:
+			{			
+            iRAdvGsmPhone.StopDTMFTone();
+            if( iInternalDTMFWaitStarted )
+				{
+				// We have to hold on a bit so that the CSendAppUi is 
+				// properly initialized
+				iIdle->Start( TCallBack( IdleCallback,this ) );
+				}
+			}
+            break;
+			
+        case EConnected:
+			{
+			}
+            break;
+
+		case EIdle:
+        default:
+            break;
+		}
+
+    TELSERVICE_LEAVEFN( "DoCancel()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::RunL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::RunL()
+	{
+    TELSERVICE_ENTERFN( "CBrowserTelService::RunL()" )
+
+    RCall::TStatus callStatus;
+    callStatus = RCall::EStatusUnknown;
+        
+    iRCall.GetStatus( callStatus );
+
+    TInt status = iStatus.Int();
+    TELSERVICE_WRITE_FORMAT( "status: %d", status );
+    TELSERVICE_WRITE_FORMAT( "callStatus: %d", callStatus );
+
+    if ( status != KErrNone )
+		{
+        TELSERVICE_WRITE_FORMAT( "RunL() - iStatus error: %d", status )
+        HandleError( status );
+        return;
+		}
+    
+    if( status == KErrNone )
+		{
+        switch( State() )
+			{
+            // the call is now active
+            case EDialing:
+                {
+                TELSERVICE_WRITE( "RunL - KDialing" )
+
+                BringBrowserToForeground();
+
+				if( callStatus == RCall::EStatusConnected )
+					{
+					SetState( EConnected );
+					// Notify the observer
+					NotifyObservers();
+
+					if( iSynch )
+						{
+						iWait.AsyncStop();  // stop the wait loop. 
+											// Now DoMakeCallL will return
+						}
+					else    
+						{   // async variant was called
+                        if( HandleInternalSendDTMFL() == EFalse )
+                            { // nothing to handle anymore
+
+						    // Complete the request
+                            TELSERVICE_WRITE_FORMAT(
+								"Complete the request: %d",KErrNone )
+
+						    User::RequestComplete( 
+							iUserRequestStatus, KErrNone );
+                            }
+						}
+					}
+                }
+                break;
+
+            // the DTMF tones have been sent
+            case EDialingDTMF:
+                {
+                TELSERVICE_WRITE( "RunL - KDialingDTMF" )
+
+				iRAdvGsmPhone.Close();
+
+                if( HandleInternalSendDTMFL() == EFalse )
+                    { // nothing to handle anymore
+				    SetState( EConnected );
+				    // Notify the observer
+				    NotifyObservers();
+
+				    if( iSynch || iInternalDTMFWaitStarted )
+						{
+					    iWait.AsyncStop();  // stop the wait loop. 
+											//Now SendDTMFL() will return
+						}
+				    else    
+					    {
+					    // Asynchronous method was called.
+                        if( iWaitDlg )
+							{
+                            iWaitDlg->ProcessFinishedL();
+							}
+					    // Complete the request
+                        TELSERVICE_WRITE_FORMAT(
+							"Complete the request: %d",KErrNone )
+
+					    User::RequestComplete( iUserRequestStatus, KErrNone );
+					    }
+                    }
+                }
+                break;
+
+            // the call has been active, but 
+            // the caller has hanged up.
+            case EConnected:
+                {
+                TELSERVICE_WRITE( "RunL - EPhoneAnswered,EConnected" )
+
+				if( iCallStatus == RCall::EStatusIdle || 
+					iCallStatus == RCall::EStatusHangingUp )
+					{
+					SetStateIdleAndNotifyObservers();                       
+					}
+                }
+                break;
+
+			case EIdle:
+            default:
+                {
+                TELSERVICE_WRITE( "RunL - Default" )
+                break;
+				}
+			}
+		}
+	else
+		{
+		if ( State() == EDialing )
+			{
+			BringBrowserToForeground();
+			// If there is not activate voice call on
+			// changes state to EIdle.
+			CheckIsThereActivateVoiceCallOnL();
+			// MakeCall must return error code Canceled in this case.
+			iRetVal = KErrCancel;
+
+			if( iSynch )
+			    {
+				iWait.AsyncStop();  // stop the wait loop. 
+				// Now DoMakeCallL will return
+			    }
+			else    
+			    {   // async variant was called
+				if( HandleInternalSendDTMFL() == EFalse )
+				    { // nothing to handle anymore
+					
+					// Complete the request
+					TELSERVICE_WRITE_FORMAT(
+						"Complete the request: %d",KErrNone )
+						
+						User::RequestComplete( 
+						iUserRequestStatus, KErrNone );
+				    }
+			    }
+			}
+		}
+    TELSERVICE_LEAVEFN("CBrowserTelService::RunL()")
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::CloseAllSessions()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::CloseAllSessions()
+	{
+    TELSERVICE_ENTERFN( "CloseAllSessions()" )
+
+    iRCall.Close();
+    iRLine.Close();
+    iRPhone.Close();
+    iRTelServer.Close();
+    TELSERVICE_LEAVEFN( "CloseAllSessions()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SetStateIdleAndNotifyObserver()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::SetStateIdleAndNotifyObservers()
+	{
+    TELSERVICE_ENTERFN("SetStateIdleAndNotifyObservers()")
+
+    SetState( EIdle );
+    CloseAllSessions();
+    // Notify the observers
+    NotifyObservers();
+    TELSERVICE_LEAVEFN( "SetStateIdleAndNotifyObservers()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::NotifyObservers()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::NotifyObservers()
+	{
+    TELSERVICE_ENTERFN( "NotifyObservers()" )
+
+    TInt count = iObserverList.Count();
+
+    for( TInt i = 0; i < count ;i++ )
+		{
+        iObserverList[i]->BrowserTelServiceEvent( State() );
+		}
+    TELSERVICE_LEAVEFN( "NotifyObservers()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::NotifyObservers()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::NotifyObservers( TBrowserTelServiceError aError )
+	{
+    TELSERVICE_ENTERFN( "NotifyObservers( TBrowserTelServiceError )" )
+
+    TInt count = iObserverList.Count();
+	
+    for( TInt i = 0; i < count; i++)
+		{
+        iObserverList[i]->BrowserTelServiceError( aError );
+		}
+    TELSERVICE_LEAVEFN( "NotifyObservers(TBrowserTelServiceError)" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::HandleError()
+//
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::HandleError( TInt aError )
+	{
+    TELSERVICE_ENTERFN( "HandleError()" )
+
+    switch( State() )
+		{
+        case EDialingDTMF:
+			{
+            iRAdvGsmPhone.Close();  // close RAdvGsmPhone session.
+            NotifyObservers( ESendDTMFFailed );
+            SetState( EConnected );
+            NotifyObservers();
+			}
+            break;
+		
+		case EDialing:
+        case EConnected:
+			{
+            Cancel();
+			}
+            break;
+
+		case EIdle:
+        default:
+            break;
+		}
+
+    iRetVal = aError;
+
+    if( iSynch || iInternalDTMFWaitStarted )
+		{
+        iWait.AsyncStop();  // stop the wait loop. 
+							// Now synchronous method will return
+		}
+    else    
+		{
+        // Asynchronous method was called.
+        // Complete the request
+        TELSERVICE_WRITE_FORMAT( "Complete the request: %d", aError )
+        User::RequestComplete( iUserRequestStatus, aError );
+		}
+    TELSERVICE_LEAVEFN( "HandleError()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::EtelWatcherEvent()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::BrowserTelServiceEtelWatcherEvent(
+								  RCall::TStatus& aStatus )
+	{
+    TELSERVICE_ENTERFN( "EtelWatcherEvent()" )
+
+    if( aStatus == RCall::EStatusIdle )
+		{   
+		// the call recepient has hung up without answering the call,
+        // so lets reset our state and notify observers
+        
+        Cancel();
+        SetStateIdleAndNotifyObservers();       
+
+        iRetVal = KErrUserBusy;
+
+        if( iSynch )
+			{
+            iWait.AsyncStop();  // stop the wait loop. 
+								// Now DoMakeCallL will return
+			}
+        else    
+			{
+            // Asynchronous method was called.
+            // Complete the request
+            TELSERVICE_WRITE_FORMAT( "Complete the request: %d", KErrUserBusy )
+            User::RequestComplete( iUserRequestStatus, KErrUserBusy );
+			}
+		}
+    TELSERVICE_LEAVEFN( "EtelWatcherEvent()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ConnectionStageAchievedL()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::ConnectionStageAchievedL()
+	{
+    TELSERVICE_ENTERFN( "ConnectionStageAchievedL()" )
+		iAgentDisconnected = ETrue;
+		if( iWait.IsStarted() )
+			{
+			iWait.AsyncStop();
+			}
+    TELSERVICE_LEAVEFN( "ConnectionStageAchievedL()" )
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SearchPbForMatchL()
+//---------------------------------------------------------------------------------------
+//
+HBufC* CBrowserTelService::SearchPbForMatchL( 
+									const TDesC& aPhoneNumber )
+	{
+    TELSERVICE_ENTERFN( "SearchPbForMatchL()" )
+
+    HBufC* matchingName = NULL;
+	
+    // Create phonebook engine
+    CPbkContactEngine* pbkEngine = CPbkContactEngine::NewL();
+    CleanupStack::PushL( pbkEngine );
+
+    // Make sure a resource file is available
+    RPbkViewResourceFile pbkResourceFile( *CCoeEnv::Static() );
+    pbkResourceFile.OpenL();
+    CleanupClosePushL<RPbkViewResourceFile> ( pbkResourceFile );
+	
+	CContactIdArray* idArray = SearchPbForMatchLC( *pbkEngine
+                                                   ,aPhoneNumber
+                                                   ,EPhoneNumber 
+                                                  );
+
+    if( idArray->Count() )
+        {
+        // retrive contact's full matching name
+        CPbkContactItem* item = pbkEngine->ReadMinimalContactLC( (*idArray)[0] );
+
+        matchingName = item->GetContactTitleOrNullL();
+
+        CleanupStack::PopAndDestroy( item );
+        }
+
+    CleanupStack::PopAndDestroy( 3 );   // idArray, pbkResourceFile, pbkEngine
+
+    TELSERVICE_LEAVEFN("SearchPbForMatchL()")
+
+    return matchingName;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::SearchPbForMatchLC()
+//---------------------------------------------------------------------------------------
+//
+CContactIdArray* CBrowserTelService::SearchPbForMatchLC( 
+                                    CPbkContactEngine& aPbkEngine,
+									const TDesC& aToMatch,
+									const TMatchType& aMatchType )
+	{
+    TELSERVICE_ENTERFN( "SearchPbForMatchLC()" )
+
+    CContactIdArray* idArray = NULL;
+
+	if( aMatchType == EPhoneNumber )
+		{
+		idArray = aPbkEngine.MatchPhoneNumberL( aToMatch, aToMatch.Length() );
+		}
+	else if( aMatchType == EEmail )
+		{
+        CPbkFieldIdArray* findFrom = new( ELeave ) CPbkFieldIdArray;
+        CleanupStack::PushL( findFrom );
+
+		findFrom->AppendL( EPbkFieldIdEmailAddress );
+		idArray = aPbkEngine.FindLC( aToMatch, findFrom );
+
+        CleanupStack::Pop( idArray );
+        CleanupStack::PopAndDestroy( findFrom );
+		}
+
+	CleanupStack::PushL( idArray );
+    TELSERVICE_LEAVEFN( "SearchPbForMatchLC()" )
+	return idArray;
+	}
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::IdleCallback()
+//---------------------------------------------------------------------------------------
+//
+TInt CBrowserTelService::IdleCallback( TAny* aTelService )
+    {
+    TELSERVICE_ENTERFN( "IdleCallback()" )
+	( ( CBrowserTelService* ) aTelService )->DoIdleCallback();
+    TELSERVICE_LEAVEFN( "IdleCallback()" )
+	return EFalse;	// return false since we don't want to run idle again
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::IdleCallback()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::DoIdleCallback()
+    {
+    TELSERVICE_WRITE( "DoIdleCallback()" )
+	iWait.AsyncStop();
+    }
+
+// ---------------------------------------------------------
+// CBrowserTelService::DialogDismissedL
+// ---------------------------------------------------------
+//
+void CBrowserTelService::DialogDismissedL( TInt aButtonId )
+    {
+    TELSERVICE_ENTERFN( "DialogDismissedL()" )
+    
+    if ( aButtonId == EAknSoftkeyCancel )
+        {
+        Cancel();
+        }
+	iWaitDlg = NULL;   // Dialog will delete itself; prevent DoCancel
+	// deleting it beforehand.
+    TELSERVICE_LEAVEFN( "DialogDismissedL()" )
+    }
+
+// ---------------------------------------------------------
+// CBrowserTelService::HandleInternalSendDTMFL
+// ---------------------------------------------------------
+//
+TBool CBrowserTelService::HandleInternalSendDTMFL() 
+    {
+    TELSERVICE_ENTERFN( "HandleInternalSendDTMFL()" )
+    
+    iSynch = EFalse;    // Reset to EFalse since the HandleInternalSendDTMFL()
+                        // is asynchronous!
+
+    if( !(iSendableDTMFNumbers && iDlgDTMFNumbers) )
+        {
+        return EFalse;
+        }
+
+	TBool retVal = EFalse;
+
+    CRepository* repository = CRepository::NewL( KCRUidBrowser );
+    CleanupStack::PushL (repository );
+    repository->Get( KBrowserConfirmedDTMFOnce, iConfirmedOnce );  
+
+    if( iSendableDTMFNumbers->Count() > 0 && iDlgDTMFNumbers->Count() > 0 )
+        {
+        TELSERVICE_WRITE( "we have dtmf numbers to send" )
+        TInt sendDTMF = 1;
+        TPtr sendableNumberPtr = iSendableDTMFNumbers->At(0)->Des();
+        TPtr dlgNumberPtr = iDlgDTMFNumbers->At(0)->Des();
+
+        if( DisplaySendDTMFDialog( &dlgNumberPtr ) )
+            {
+            if( dlgNumberPtr.Length() > 0 )
+                {
+                TELSERVICE_WRITE( "display send dtmf dialog" )
+                if( iDTMFAlwaysConfirm )
+                    {
+                    sendDTMF = ShowDialogL( dlgNumberPtr,EConfirmSendDTMF );
+                    }
+                else if( iDTMFAlwaysConfirm == EFalse && 
+                         iConfirmedOnce == EFalse )
+                    {
+                    sendDTMF = ShowDialogL( dlgNumberPtr, 
+											EConfirmSendDTMF );
+                    iConfirmedOnce = ETrue;
+                    repository->Set( KBrowserConfirmedDTMFOnce, iConfirmedOnce );
+                    }
+                else
+                    {
+                    sendDTMF = 1;
+                    }
+                }
+            else
+                {
+                TELSERVICE_WRITE("don't display send dtmf dialog dlgNumberPtr.Length() < 0")
+                sendDTMF = 0;
+				}
+            }
+        else
+            {
+            TELSERVICE_WRITE( "don't display send dtmf dialog" )
+
+            if( dlgNumberPtr.Length() > 0 )
+                {
+                TELSERVICE_WRITE( "start dtmf wait timer" )
+
+                RTimer timer; 
+                TRequestStatus timerStatus; // request status 
+											// associated with timer
+                timer.CreateLocal(); // create for this thread
+                timer.After( timerStatus, KTimerDelay ); // pause for 2,5 
+														 // seconds
+                User::WaitForRequest( timerStatus );
+                timer.Close();
+                }
+            else
+				{
+                sendDTMF = 0;
+				}
+            }
+
+        if( sendDTMF )
+            {
+            TELSERVICE_WRITE( "Send the DTMF" )
+
+            RipWaitChar( &sendableNumberPtr );
+            ValidateDTMFNumberL( &sendableNumberPtr );
+            // Send DTMF tones
+            DoSendDTMFL( sendableNumberPtr );
+
+            TELSERVICE_WRITE( "DoSendDTMFL() ok!" )
+
+            ShowDialogL( dlgNumberPtr, ESendingDTMF );
+            retVal = ETrue;
+            }
+
+        iSendableDTMFNumbers->Delete(0);
+        iSendableDTMFNumbers->Compress();
+        iDlgDTMFNumbers->Delete(0);
+        iDlgDTMFNumbers->Compress();
+        }
+
+    CleanupStack::PopAndDestroy( repository );
+
+    TELSERVICE_LEAVEFN( "HandleInternalSendDTMFL()" )
+    return retVal;
+    }
+
+// ---------------------------------------------------------------------------
+// CBrowserTelService::BringBrowserToForeground
+// ---------------------------------------------------------------------------
+//
+void CBrowserTelService::BringBrowserToForeground()
+    {
+    TELSERVICE_ENTERFN( "BringBrowserToForeground()" )
+    TApaTaskList taskList( CEikonEnv::Static()->WsSession() );
+    TUid wapUid = KUidBrowserApplication;
+    TApaTask task = taskList.FindApp( wapUid );
+    task.BringToForeground();
+    TELSERVICE_LEAVEFN( "BringBrowserToForeground()" )
+    }
+
+// ---------------------------------------------------------------------------
+// CBrowserTelService::CheckIsThereActivateVoiceCallOnL
+// ---------------------------------------------------------------------------
+//
+void CBrowserTelService::CheckIsThereActivateVoiceCallOnL()
+	{
+	RTelServer::TPhoneInfo info;
+    RPhone::TLineInfo lineInfo;
+	RLine::TLineInfo callInfo;
+	
+    // Connect to the telephony server and load the TSY.
+    User::LeaveIfError( iRTelServer.Connect() );
+    User::LeaveIfError( iRTelServer.LoadPhoneModule( KMmTsyModuleName ) );
+    // Get the details for the first (and only) phone.
+    User::LeaveIfError( iRTelServer.GetPhoneInfo( 0, info ) );
+    // Open the phone.
+	iRPhone.Close();
+    User::LeaveIfError( iRPhone.Open( iRTelServer, info.iName ) );
+    // Get the information for the voice line, line 0.
+    User::LeaveIfError( iRPhone.GetLineInfo( 0, lineInfo ) );
+ 
+    if( lineInfo.iStatus > RCall::EStatusIdle )
+        {
+        TELSERVICE_WRITE( "There's an active call" );
+        // Open the line. iName will now be "VoiceLine1".
+	    iRLine.Close();
+        User::LeaveIfError( iRLine.Open( iRPhone, KMmTsyVoice1LineName ) );     
+	    TInt count;
+	    // Gets the number of calls opened from a line.	
+	    User::LeaveIfError( iRLine.EnumerateCall( count ) );
+	    if ( count >= 1 )
+		    {
+		    SetState( EConnected );
+		    User::LeaveIfError( iRLine.GetInfo( callInfo ) );
+		    iRCall.Close();
+
+            User::LeaveIfError( iRCall.OpenExistingCall( iRLine, 
+			    callInfo.iNameOfLastCallAdded ) );
+		    }
+	    else
+		    {
+		    SetState( EIdle );
+		    }
+        }
+	else
+		{
+        TELSERVICE_WRITE( "No active call" );
+		SetState( EIdle );
+		}
+	}
+
+// ---------------------------------------------------------------------------
+// CBrowserTelService::CheckDTMFNumber
+// ---------------------------------------------------------------------------
+//
+void CBrowserTelService::CheckDTMFNumberL( TDesC& aNumber )
+	{
+	TBool multiw = EFalse;
+	TBool multikeno = EFalse;
+
+	for ( TInt i = 0; i < aNumber.Length(); i++ )
+		{
+        if( (KValidDTMFChars().Locate( aNumber[i] ) ) == KErrNotFound )
+            {
+            User::Leave( KErrArgument );
+            }
+        else
+            {
+            if( aNumber[i] == 'w' )
+                {
+				if( multiw )
+					{
+					User::Leave( KErrArgument );
+					}
+				multiw = ETrue;
+                }
+            else if( aNumber[i] == '/' )
+                {
+				if( multikeno )
+					{
+                    User::Leave( KErrArgument );
+					}
+				multikeno = ETrue;
+                }
+            }
+        }
+	}
+
+// ---------------------------------------------------------------------------
+// CBrowserTelService::CheckDTMFNumber
+// ---------------------------------------------------------------------------
+//
+CPbkContactItem* CBrowserTelService::SearchPBItemLC( CPbkContactEngine& aPbkEngine,
+                                                     TDesC& aNumber, 
+                                                     TDesC& aEmail,
+                                                     TBool& aNewContact )
+    {
+	CPbkContactItem* contactItem = NULL;
+	CContactIdArray* idArrayPhoneNr = SearchPbForMatchLC( aPbkEngine, aNumber, EPhoneNumber );
+	CContactIdArray* idArrayEmail = SearchPbForMatchLC( aPbkEngine, aEmail, EEmail );
+
+    aNewContact = ETrue;
+
+	if( idArrayPhoneNr->Count() && aNumber.Length() )
+		{
+		// Open existing
+		if ( ShowDialogL( aNumber, EConfirmAddToPb ) )
+			{
+			contactItem = aPbkEngine.OpenContactL( ( *idArrayPhoneNr )[0] );
+			aNewContact = EFalse;
+			}
+		else
+			{
+			// Create a new contact
+			contactItem = aPbkEngine.CreateEmptyContactL();
+			}
+		
+		}
+	else if( idArrayEmail->Count() && aEmail.Length() )
+		{
+		if ( ShowDialogL( aEmail, EConfirmAddToPb ) )
+			{
+			// Open existing
+			contactItem = aPbkEngine.OpenContactL( ( *idArrayEmail )[0] );
+			aNewContact = EFalse;
+			}
+		else
+			{
+			// Create a new contact
+			contactItem = aPbkEngine.CreateEmptyContactL();
+			}		
+		}
+	else
+		{
+		// Create a new contact
+		contactItem = aPbkEngine.CreateEmptyContactL();
+		}
+
+	CleanupStack::PopAndDestroy( 2 );		// idArrayEmail,idArrayPhoneNr
+
+	CleanupStack::PushL( contactItem );
+
+    return contactItem;
+    }
+
+// ---------------------------------------------------------------------------
+// CBrowserTelService::SetPBEntryField()
+// ---------------------------------------------------------------------------
+//
+void CBrowserTelService::SetPBEntryFieldL( TInt aField,
+                                           CPbkContactEngine* aPbkEngine,
+                                           CPbkContactItem* aContactItem,
+                                           const TPtrC& aFieldValue,
+                                           TInt& aFormIndex )
+    {
+    if( aFieldValue.Length() )
+		{
+        TPbkContactItemField *dataField = aContactItem->FindField( aField );
+
+        if( !dataField )
+			{
+            CPbkFieldInfo* newFieldType = NULL;
+
+            for ( TInt i = 0; !newFieldType &&
+			          i < aPbkEngine->FieldsInfo().Count(); ++i ) 
+		        {
+                CPbkFieldInfo* fieldInfo = aPbkEngine->FieldsInfo()[i];
+                if( fieldInfo->FieldId() == aField )
+			        {
+                    // we found the proper field. Yeah!
+                    newFieldType = fieldInfo;
+			        }
+		        }
+            // add new field
+            dataField = aContactItem->AddOrReturnUnusedFieldL( *newFieldType );
+            }
+
+        if( dataField )
+            {
+            // Put the data to the field
+            dataField->TextStorage()->SetTextL( aFieldValue );
+            if( aFormIndex == -1 )
+			    {
+                aFormIndex = aContactItem->FindFieldIndex( *dataField );
+			    }
+            }
+		}
+    }
+
+// ---------------------------------------------------------------------------
+// CBrowserTelService::ParseRecipientsLC
+// ---------------------------------------------------------------------------
+//
+CPtrC16Array* CBrowserTelService::ParseRecipientsLC( const TDesC& aRecipients )
+    {
+    CPtrC16Array* recips = new( ELeave ) CPtrC16Array( 2 );
+
+    CleanupStack::PushL( recips );
+
+    if( aRecipients.Length() )
+        {
+        TPtrC tempRec( aRecipients );
+
+        do
+            {
+            int posComma = tempRec.Find( _L(",") );
+
+
+            if( posComma != KErrNotFound )
+                {
+                recips->AppendL( tempRec.Left( posComma ) );
+                tempRec.Set( tempRec.Right( tempRec.Length() - posComma - 1 ) );
+                }
+            else
+                {
+                recips->AppendL( tempRec );
+                tempRec.Set( KNullDesC );
+                }
+
+            }while( tempRec.Length() );
+        }
+
+    return recips;
+    }
+   
+// ---------------------------------------------------------------------------
+// CBrowserTelService::ConnectionTypeL
+// ---------------------------------------------------------------------------
+//
+TApBearerType CBrowserTelService::ConnectionTypeL( TUint aApId )
+    {
+	CCommsDatabase* commsDb = CCommsDatabase::NewL( EDatabaseTypeIAP );
+    CleanupStack::PushL( commsDb );
+
+	CApDataHandler* apDataHandler = CApDataHandler::NewLC( *commsDb );
+	TUint32 apId = 0;
+	CApUtils* apUtils = CApUtils::NewLC( *commsDb );
+
+	apId = apUtils->WapIdFromIapIdL( aApId );
+
+	CleanupStack::PopAndDestroy(); //apUtils
+    apUtils = NULL;
+
+	CApAccessPointItem* apItem = CApAccessPointItem::NewLC();
+	
+	apDataHandler->AccessPointDataL( apId, *apItem );
+
+    TApBearerType bearerType = apItem->BearerTypeL();
+
+    CleanupStack::PopAndDestroy( 3 );    // apItem, apDataHandler, commsDb
+
+    return bearerType;
+    }
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::ErrorHandler()
+//---------------------------------------------------------------------------------------
+//
+void CBrowserTelService::ErrorHandler( TInt aErrorId )
+    {
+    TELSERVICE_WRITE_FORMAT( "Error handler: %d", aErrorId );
+    
+    if( aErrorId == KErrCancel )
+        {
+        return;
+        }
+
+    TInt i;
+    for( i = 0; KErrorConvTable[i][0] && KErrorConvTable[i][0] != aErrorId; ++i ){};
+
+    if( KErrorConvTable[i][0] )
+        {
+        // If KErrorConvTable[i][1] is 0 it's already handled by the system
+        if( KErrorConvTable[i][1] )
+            {
+            TRAP_IGNORE( iErrorUi->ShowGlobalErrorNoteL( -(KErrorConvTable[i][1] + KKimonoBase )) );
+            }
+        }
+    else
+        // global error id is received
+        {
+        TRAP_IGNORE( iErrorUi->ShowGlobalErrorNoteL( aErrorId ) );
+        }
+    }
+
+#ifdef __BROWSER_TEL_SERVICES_CALLUI__
+
+//---------------------------------------------------------------------------------------
+// CBrowserTelService::HandleNotifyL()
+//---------------------------------------------------------------------------------------
+//
+TInt CBrowserTelService::HandleNotifyL( TInt /*aCmdId*/,
+                                        TInt /*aEventId*/,
+                                        CAiwGenericParamList& /*aEventParamList*/,
+                                        const CAiwGenericParamList& /*aInParamList*/ )
+    {
+    TELSERVICE_ENTERFN("CBrowserTelService::HandleNotifyL");
+
+ 	if( iSynch && iWait.IsStarted() )
+		{
+		iWait.AsyncStop();  // stop the wait loop. 
+							// Now DoMakeCallL will return
+		}
+    else
+        {
+        // The client is not interested what happened!
+        iSynch = EFalse; // Just in case not to start iWait after ExecuteServiceCmdL
+        if( iUserRequestStatus )
+            {
+            User::RequestComplete( iUserRequestStatus, KErrNone );
+            }
+        }
+
+    TELSERVICE_LEAVEFN( "CBrowserTelService::HandleNotifyL" );
+    return KErrNone;
+    }
+
+#endif // __BROWSER_TEL_SERVICES_CALLUI__
+
+// ================= OTHER EXPORTED FUNCTIONS ==============
+