--- /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 <eikenv.h>
+#include <eikrutil.h>
+#include <StringLoader.h>
+
+// Messaging includes
+#include <miut_err.h>
+#include <miutset.h>
+#include <msvuids.h>
+#include <mtmuibas.h>
+#include <imapset.h>
+#include <MsvPrgReporter.h>
+#include <imapcmds.h>
+#include <ImumUtils.rsg>
+#include <AlwaysOnlineManagerClient.h>
+#include <SendUiConsts.h>
+#include <ImumInMailboxUtilities.h>
+
+#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<MMsvImapConnectionObserver*> 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<KImasImailMaxSettingsLength> 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<CBaseMtmUi::EProgressStringMaxLen> 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<CBaseMtmUi::EProgressStringMaxLen>& 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<TInt> 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<CBaseMtmUi::EProgressStringMaxLen>& 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<TMsvEmailConnectionProgress> 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