diff -r 000000000000 -r 72b543305e3a email/imum/Mtms/Src/ImapConnectionOp.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/email/imum/Mtms/Src/ImapConnectionOp.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,645 @@ +/* +* Copyright (c) 2006 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: +* CImapConnectionOp implementation file +* +*/ + + + +// General includes +#include +#include +#include + +// Messaging includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ImapConnectionOp.h" +#include "MsvConnectionValidation.h" +#include "MsvEmailConnectionProgressProvider.h" +#include "PROGTYPE.H" +#include "ImumPanic.h" +#include "ImumMtmLogging.h" +#include "ImapFolderSyncOperation.h" +#include "EmailUtils.H" +#include "ImumMboxSettingsUtils.h" + + +const TInt KImumMaxLoginRetries = 3; + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::NewL() +// ---------------------------------------------------------------------------- +CImapConnectionOp* CImapConnectionOp::NewL( + CMsvSession& aMsvSession, + TInt aPriority, + TRequestStatus& aStatus, + TMsvId aService, + MMsvProgressReporter& aProgressReporter, + TImapConnectionType aConnectionType) + { + IMUM_STATIC_CONTEXT( CImapConnectionOp::NewL, 0, mtm, KImumMtmLog ); + IMUM_IN(); + + CImapConnectionOp* me=new (ELeave) CImapConnectionOp( + aMsvSession, aPriority, aStatus, + aService, aProgressReporter, aConnectionType ); + CleanupStack::PushL(me); + me->ConstructL(); + CleanupStack::Pop(); // me + IMUM_OUT(); + return me; + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::CImapConnectionOp() +// ---------------------------------------------------------------------------- +CImapConnectionOp::CImapConnectionOp( + CMsvSession& aMsvSession, + TInt aPriority, + TRequestStatus& aStatus, + TMsvId aService, + MMsvProgressReporter& aProgressReporter, + TImapConnectionType aConnectionType ) + : + CMsvOperation(aMsvSession, aPriority, aStatus), + iMailboxApi( NULL ), + iState(EConstructing), + iConnectionType(aConnectionType), + iSyncProgress(), + iProgressReporter(aProgressReporter)/*, + iOperations( KImumOperationsArrayGranularity )*/ + { + IMUM_CONTEXT( CImapConnectionOp::CImapConnectionOp, 0, KImumMtmLog ); + IMUM_IN(); + + iService=aService; + iMtm=KUidMsgTypeIMAP4; + iSyncProgress().iType=EImap4SyncProgressType; + iCoeEnv = CCoeEnv::Static(); + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::~CImapConnectionOp() +// ---------------------------------------------------------------------------- +CImapConnectionOp::~CImapConnectionOp() + { + IMUM_CONTEXT( CImapConnectionOp::~CImapConnectionOp, 0, KImumMtmLog ); + IMUM_IN(); + + //iOperations.ResetAndDestroy(); + + Cancel(); + iProgressReporter.UnsetProgressDecoder(); + + // Release the shared MtmUi + if(iMtmUi) + { + iProgressReporter.MtmStore().ReleaseMtmUi(iMtm); + } + + delete iConnectionProgressProvider; + delete iSubOperation; + delete iTitleText; + delete iConnectionText; + + delete iMailboxApi; + iMailboxApi = NULL; + // don't own iCoeEnv so don't delete it + iMtmUi = NULL; + iCoeEnv = NULL; + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::ConstructL() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::ConstructL() + { + IMUM_CONTEXT( CImapConnectionOp::ConstructL, 0, KImumMtmLog ); + IMUM_IN(); + + CMsvEntry* serviceEntry=NULL; + + serviceEntry=iMsvSession.GetEntryL(iService); + CleanupStack::PushL(serviceEntry); + + iSyncProgress().iState=TImap4SyncProgress::EConnecting; + iSyncProgress().iErrorCode=KErrNone; + + // Store the related service Id + iRelatedServiceId=serviceEntry->Entry().iRelatedId; + + iConnectionText = NULL; + iTitleText = StringLoader::LoadL( + R_EMAIL_CONNECTING_SERVER, + serviceEntry->Entry().iDetails, + iCoeEnv ); + + CleanupStack::PopAndDestroy( serviceEntry ); + + iMailboxApi = CreateEmailApiL( &iMsvSession ); + + CActiveScheduler::Add(this); + + iObserverRequestStatus=KRequestPending; + + TRequestStatus* myStatus=&iStatus; + User::RequestComplete(myStatus,KErrNone); + + SetActive(); + // We complete ourselves so that the dialog gets a chance to redraw + // before entering the lengthy process of opening system agent and + // connection progress provider + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::GetConnectionOperationL() +// ---------------------------------------------------------------------------- +CMsvOperation* CImapConnectionOp::GetConnectionOperationL() + { + IMUM_CONTEXT( CImapConnectionOp::GetConnectionOperationL, 0, KImumMtmLog ); + IMUM_IN(); + + // Invoke the appropriate client connection operation + // InvokeAsyncFunctionL in the MtmUi. + // + TPckg param(this); + + CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection; + CleanupStack::PushL(selection); + selection->AppendL(iService); + + CMsvOperation* connectOp=NULL; + + switch(iConnectionType) + { + case ECompleteAfterConnect: + connectOp=iMtmUi->InvokeAsyncFunctionL( + KIMAP4MTMConnect, *selection, iStatus, param); + break; + case EWithSyncCompleteAfterConnect: + connectOp=iMtmUi->InvokeAsyncFunctionL( + KIMAP4MTMConnectAndSyncCompleteAfterConnect, *selection, iStatus, param); + break; + case EWithSyncCompleteAfterFullSync: + connectOp=iMtmUi->InvokeAsyncFunctionL( + KIMAP4MTMConnectAndSyncCompleteAfterFullSync, *selection, iStatus, param); + break; + case EWithSyncCompleteAfterDisconnection: + connectOp=iMtmUi->InvokeAsyncFunctionL( + KIMAP4MTMConnectAndSyncCompleteAfterDisconnect, *selection, iStatus, param); + break; + default: + __ASSERT_DEBUG( 0, + User::Panic(KImumMtmUiPanic, EIMAP4MtmUiUnknownOperation) ); + } + + CleanupStack::PopAndDestroy(); // selection + IMUM_OUT(); + + return connectOp; + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::RunL() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::RunL() + { + IMUM_CONTEXT( CImapConnectionOp::RunL, 0, KImumMtmLog ); + IMUM_IN(); + + DoRunL(); + + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::DoRunL() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::DoRunL() + { + IMUM_CONTEXT( CImapConnectionOp::DoRunL, 0, KImumMtmLog ); + IMUM_IN(); + + if(iState==EConstructing) + { + FinishConstructionL(); + } + else + { + ConnectionCompletionL(); + } + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::RunError() +// ---------------------------------------------------------------------------- +TInt CImapConnectionOp::RunError(TInt aError) + { + IMUM_CONTEXT( CImapConnectionOp::RunError, 0, KImumMtmLog ); + IMUM_IN(); + + IMUM1( 0, "RunL leaved with error code %d", aError ); + + iSyncProgress().iErrorCode = aError; + Complete(); + + IMUM_OUT(); + return KErrNone; + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::FinishConstructionL() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::FinishConstructionL() + { + IMUM_CONTEXT( CImapConnectionOp::FinishConstructionL, 0, KImumMtmLog ); + IMUM_IN(); + + // Called by RunL when in EConstructing state + TBool check = ETrue; + + // To speed up connection establishment, avoid loading settings multiple + // times. Get all the info needed at once. + CImumInSettingsData* settings = + iMailboxApi->MailboxServicesL().LoadMailboxSettingsL( iService ); + CleanupStack::PushL( settings ); + + // Check if the service has a password and valid IAP + // Get login data from settings + TMsvLoginData loginData; + ImumMboxSettingsUtils::GetLoginInformationL( *settings, + KSenduiMtmImap4Uid, loginData.iUsername, loginData.iPassword, + loginData.iIsPasswordTemporary ); + // Get iap name + TBuf iapName; + MsvConnectionValidation::GetServiceIapNameL( *settings, + KSenduiMtmImap4Uid, iapName); + TBool iapOk = ( settings->Validate() == KErrNone ); + CleanupStack::PopAndDestroy(); // settings + + iLoginRetryCounter = 0; + if( !check || + !iapOk || + !MsvConnectionValidation::CheckAndPromptForPasswordL( + *iMailboxApi, iService, loginData, iLoginRetryCounter ) ) + { + // User has declined to provide a password or a IAP. Complete + // _ourselves_ immediately. + iStatus=KRequestPending; + SetActive(); + + TRequestStatus* myStatus=&iStatus; + User::RequestComplete(myStatus, KErrNone); + iSyncProgress().iErrorCode= ( iapOk ? KErrCancel : KErrImapConnectFail ); + iState=ECompleted; + } + else + { + // Service has password in it and a valid IAP. + // + iMtmUi=&(iProgressReporter.MtmStore().ClaimMtmUiL(iMtm)); + iMtmUi->BaseMtm().SwitchCurrentEntryL(iService); + + iConnectionProgressProvider = CMsvEmailConnectionProgressProvider::NewL( + iapName, iService); + iSubOperation=GetConnectionOperationL(); + iState=EEstablishingConnection; + + SetActive(); + // + // We're going to try and connect; tell our MMsvProgressReporter + // to come to us for progress. + // + iProgressReporter.SetProgressDecoder(*this); + } + iObserverRequestStatus=KRequestPending; + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::ConnectionCompletionL() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::ConnectionCompletionL() + { + IMUM_CONTEXT( CImapConnectionOp::ConnectionCompletionL, 0, KImumMtmLog ); + IMUM_IN(); + + // Called by RunL when past EConstructing state + TInt err=KErrNone; + if(iSubOperation) + { + // The sub connection operation has completed. + + // We need to detect a failure to connect due to invalid login details, + // and prompt the user accordingly. + // + TBuf dummyString; + TInt dummyInt[4]; // CSI: 47 # For dummyInt. + + err=DecodeProgress(iSubOperation->ProgressL(),dummyString,dummyInt[0],dummyInt[1],dummyInt[2],dummyInt[3],ETrue); // CSI: 47 # dummyInts. + if(err == KErrImapBadLogon) + { + // Login details are wrong. + TBool retry = EFalse; + if ( iLoginRetryCounter < KImumMaxLoginRetries ) + { + retry = MsvConnectionValidation::ShowLoginDetailsRejectionDlgL( + *iMailboxApi, iService); + } + else + { + // User has entered wrong username or password max number of times, + // sets error code for imap mtm ui to display correct note... + iSyncProgress().iErrorCode = KErrImapBadLogon; + iState=ECompleted; + } + iLoginRetryCounter++; + + if(retry) + { + // Retry connect. + iProgressReporter.MakeProgressVisibleL(ETrue); + iProgressReporter.SetTitleL(*iTitleText); + delete iSubOperation; + iSubOperation=NULL; + iSubOperation=GetConnectionOperationL(); + SetActive(); + iProgressReporter.SetProgressDecoder(*this); + IMUM_OUT(); + return; + } + else + { + Complete(); + IMUM_OUT(); + return; + } + } + } + + User::LeaveIfError(err); // Any error apart from KErrImapBadLogon + + Complete(); + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::DoCancel() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::DoCancel() + { + IMUM_CONTEXT( CImapConnectionOp::DoCancel, 0, KImumMtmLog ); + IMUM_IN(); + + if( iSubOperation ) + { + iSubOperation->Cancel(); + } + + iSyncProgress().iErrorCode = KErrCancel; + Complete(); + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::ProgressL() +// ---------------------------------------------------------------------------- +const TDesC8& CImapConnectionOp::ProgressL() + { + IMUM_CONTEXT( CImapConnectionOp::ProgressL, 0, KImumMtmLog ); + IMUM_IN(); + + if(iSubOperation && (iState!=ECompleted)) + { + // Need to make the distinction between connection states. + // + // EEstablishingConnection -> CMsvEMailConnectionProgressProvider + // EUpdatingFolderList -> iOperation->ProgressL + // EUpdatingInbox, -> iOperation->ProgressL + // EUpdatingFolders, -> iOperation->ProgressL + // EOnline, -> iOperation->ProgressL + // ECompleted -> iSyncProgress + // + if(iState==EEstablishingConnection) + { + IMUM_OUT(); + return iConnectionProgressProvider->GetConnectionProgressL(); + } + else + { + IMUM_OUT(); + return iSubOperation->ProgressL(); + } + } + else + { + IMUM_OUT(); + return iSyncProgress; + } + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::DecodeProgress() +// ---------------------------------------------------------------------------- +TInt CImapConnectionOp::DecodeProgress(const TDesC8& aProgress, + TBuf& aReturnString, + TInt& aTotalEntryCount, TInt& aEntriesDone, + TInt& aCurrentEntrySize, TInt& aCurrentBytesTrans, TBool aInternal) + { + IMUM_CONTEXT( CImapConnectionOp::DecodeProgress, 0, KImumMtmLog ); + IMUM_IN(); + + if(aProgress.Length()==0) + return KErrNone; + + TPckgC type(0); + type.Set(aProgress.Left(sizeof(TInt))); + + IMUM_OUT(); + if(!aInternal || type()!=EUiProgTypeConnecting) + return iMtmUi->GetProgress(aProgress, aReturnString, aTotalEntryCount, + aEntriesDone, aCurrentEntrySize, aCurrentBytesTrans); + else + // We want the internal representation of connection progress... + return DecodeConnectionProgress(aProgress, aReturnString,aTotalEntryCount, aEntriesDone, aCurrentEntrySize, aCurrentBytesTrans); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::DecodeConnectionProgress() +// ---------------------------------------------------------------------------- +TInt CImapConnectionOp::DecodeConnectionProgress( + const TDesC8& aProgress, + TBuf& aReturnString, + TInt& aTotalEntryCount, + TInt& aEntriesDone, + TInt& aCurrentEntrySize, + TInt& aCurrentBytesTrans) + { + IMUM_CONTEXT( CImapConnectionOp::DecodeConnectionProgress, 0, KImumMtmLog ); + IMUM_IN(); + + aTotalEntryCount=0; // No quantitative progress to return + aEntriesDone=0; + aCurrentEntrySize=0; + aCurrentBytesTrans=0; + + TPckgBuf progressBuf; + progressBuf.Copy(aProgress); + const TMsvEmailConnectionProgress& connectionProgress=progressBuf(); + + switch(connectionProgress.iState) + { + case TMsvEmailConnectionProgress::EInitialising: + case TMsvEmailConnectionProgress::EConnectNetwork: + { + // Check if the name is already prepared + if( iConnectionText ) + { + aReturnString.Copy( *iConnectionText ); + } + else + { + MsvEmailMtmUiUtils::CreateConnectingToText( aReturnString, + iMsvSession, iService ); + iConnectionText = aReturnString.Alloc(); + } + + } + break; + case TMsvEmailConnectionProgress::EConnectMailbox: + aReturnString.Copy( *iTitleText ); + break; + } + IMUM_OUT(); + + return connectionProgress.iErrorCode; + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::Complete() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::Complete() + { + IMUM_CONTEXT( CImapConnectionOp::Complete, 0, KImumMtmLog ); + IMUM_IN(); + + TRequestStatus* observer=&iObserverRequestStatus; + User::RequestComplete(observer, KErrNone); + iState=ECompleted; + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::HandleImapConnectionEvent() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::HandleImapConnectionEvent( + TImapConnectionEvent aConnectionEvent ) + { + IMUM_CONTEXT( CImapConnectionOp::HandleImapConnectionEvent, 0, KImumMtmLog ); + IMUM_IN(); + + switch ( aConnectionEvent ) + { + case ESynchronisingInbox: + // Means that the connection has finished + iState=EUpdatingFolderList; + delete iConnectionProgressProvider; + iConnectionProgressProvider=NULL; + + // Get progress decoded by the default decoder + iProgressReporter.UnsetProgressDecoder(); + + // Try to update successful connection time. If failed + // just forget it. + TRAP_IGNORE( ImumMboxSettingsUtils::SetLastUpdateInfoL( + *iMailboxApi, iService, ETrue ) ); + + break; + + case ESynchronisingFolderList: + break; + + case ESynchronisingFolders: + case ESynchronisationComplete: + { + if ( iConnectionType == EWithSyncCompleteAfterDisconnection ) + { + // Only hide dialog if we're here 'til the end + TRAP_IGNORE( iProgressReporter.MakeProgressVisibleL( EFalse ) ); + } + + // Send the 'Turn ON' message to always online. + TRAP_IGNORE( MsvEmailMtmUiUtils::SendAOCommandL( + EServerAPIEmailUpdateMailWhileConnected, iService ) ); + } + + break; + + default: + break; + } + + /* We can always call NewMessage function, because Ncnlist is responsible of + checking whether there really is new messages or not. We only tell Ncnlist + that now there might be new messages */ + TRAP_IGNORE( MsvEmailMtmUiUtils::CallNewMessagesL( iService ) ); + IMUM_OUT(); + } + +// ---------------------------------------------------------------------------- +// CImapConnectionOp::OpCompleted() +// ---------------------------------------------------------------------------- +void CImapConnectionOp::OpCompleted( + CMsvSingleOpWatcher& /*aOpWatcher*/, + TInt /*aCompletionCode*/ ) + { + IMUM_CONTEXT( CImapConnectionOp::OpCompleted, 0, KImumMtmLog ); + IMUM_IN(); + IMUM_OUT(); + + /* + TMsvOp opId = aOpWatcher.Operation().Id(); + const TInt count = iOperations.Count(); + + for ( TInt i=0; i < count; i++ ) + { + CMsvOperation& op = iOperations[i]->Operation(); + + if ( op.Id() == opId ) + { + delete iOperations[i]; + iOperations.Delete(i); + break; + } + } + */ + } + +// End of File