/*
* Copyright (c) 2007-2008 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: POP3 connect operation
*
*/
#include "emailtrace.h"
#include "ipsplgheaders.h"
// Constants and defines
const TInt KConnectOpPriority = CActive::EPriorityStandard;
const TInt KIpsPlgPop3PopulateLimitInitValue = 50;
_LIT( KIpsPlgPopConnectPanic, "PopConnectOp" );
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::NewL()
// ----------------------------------------------------------------------------
//
CIpsPlgPop3ConnectOp* CIpsPlgPop3ConnectOp::NewL(
CMsvSession& aMsvSession,
TRequestStatus& aObserverRequestStatus,
TMsvId aService,
TBool aForcePopulate,
CIpsPlgTimerOperation& aActivityTimer,
TFSMailMsgId aFSMailBoxId,
MFSMailRequestObserver& aFSOperationObserver,
TInt aFSRequestId,
CIpsPlgEventHandler* aEventHandler,
TBool aSignallingAllowed )
{
FUNC_LOG;
CIpsPlgPop3ConnectOp* op =
new(ELeave) CIpsPlgPop3ConnectOp( aMsvSession, aObserverRequestStatus,
aService, aForcePopulate, aActivityTimer, aFSMailBoxId,
aFSOperationObserver, aFSRequestId,
aEventHandler, aSignallingAllowed );
CleanupStack::PushL( op );
op->ConstructL();
CleanupStack::Pop( op );
return op;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::~CIpsPlgPop3ConnectOp()
// ----------------------------------------------------------------------------
//
CIpsPlgPop3ConnectOp::~CIpsPlgPop3ConnectOp()
{
FUNC_LOG;
delete iEntry;
delete iSelection;
iState = EIdle;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::ProgressL()
// ----------------------------------------------------------------------------
//
const TDesC8& CIpsPlgPop3ConnectOp::ProgressL()
{
FUNC_LOG;
if( iError != KErrNone )
{
return GetErrorProgressL( iError );
}
else if( iOperation )
{
return iOperation->ProgressL();
}
iProgress().iErrorCode = KErrNone;
return iProgress;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
void CIpsPlgPop3ConnectOp::DoCancel()
{
FUNC_LOG;
if( iOperation )
{
iOperation->Cancel();
}
CompleteObserver( KErrCancel );
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::DoRunL()
// ----------------------------------------------------------------------------
//
void CIpsPlgPop3ConnectOp::DoRunL()
{
FUNC_LOG;
// handle these error situations properly,
// and report somehow back to framework
TInt err = KErrNone;
if ( iState == EQueryingDetails )
{
// Retry connect.
DoConnectL();
iState = EConnected;
}
else if ( iState == EStartConnect )
{
if ( iOperation )
{
// operation exist and it means
// disconnect operation was ongoing.
// How handle errors
delete iOperation;
iOperation = NULL;
}
if ( ValidateL() )
{
// Begin Connect.
DoConnectL();
iState = EConnected;
}
else
{
User::Leave( KErrCancel ); // User cancelled.
}
}
else if ( iState == EConnected )
{
// Connect completed.
err = GetOperationErrorCodeL( );
if ( ( err == KPop3InvalidUser ) ||
( err == KPop3InvalidLogin ) ||
( err == KPop3InvalidApopLogin ) )
{
// Login details are wrong. Trying to ask for password
if ( !QueryUserPassL() )
{
CompleteObserver( err );
}
}
else if ( err == KErrNone )
{
if ( iForcePopulate && Connected() )
{
iState = EPopulate;
DoPopulateL();
}
else
{
iState = EIdle;
CompleteObserver( KErrNone );
}
}
else
{
// We can't do this before, because
// we want to handle KPop3InvalidUser,
// KPop3InvalidLogin and KPop3InvalidApopLogin separately.
User::Leave( err );
}
}
else if ( iState == EPopulate )
{
err = GetOperationErrorCodeL( );
if ( iEventHandler )
{
iEventHandler->SetNewPropertyEvent(
iService, KIpsSosEmailSyncCompleted, err );
}
CIpsPlgSyncStateHandler::SaveSuccessfulSyncTimeL(
iMsvSession, iService );
CompleteObserver( err );
}
else
{
User::Panic( KIpsPlgPopConnectPanic ,KErrNotFound);
}
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::GetErrorProgressL
// ----------------------------------------------------------------------------
//
const TDesC8& CIpsPlgPop3ConnectOp::GetErrorProgressL( TInt aError )
{
FUNC_LOG;
iError = aError;
if ( iOperation && iError == KErrNone )
{
return iOperation->ProgressL();
}
TPop3Progress& progress = iProgress();
progress.iPop3Progress = TPop3Progress::EPopConnecting;
progress.iTotalMsgs = 0;
progress.iMsgsToProcess = 0;
progress.iBytesDone = 0;
progress.iTotalBytes = 0;
progress.iErrorCode = iError;
progress.iPop3SubStateProgress = TPop3Progress::EPopConnecting;
progress.iServiceId = iService;
return iProgress;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::GetFSProgressL()
// ----------------------------------------------------------------------------
//
TFSProgress CIpsPlgPop3ConnectOp::GetFSProgressL() const
{
FUNC_LOG;
// might not never called, but gives something reasonable if called
TFSProgress result = { TFSProgress::EFSStatus_Waiting, 0, 0, KErrNone };
result.iError = KErrNone;
switch( iState )
{
case EQueryingDetails:
case EQueryingDetailsBusy:
result.iProgressStatus = TFSProgress::EFSStatus_Authenticating;
break;
case EStartConnect:
case EConnected:
result.iProgressStatus = TFSProgress::EFSStatus_Connecting;
break;
case EPopulate:
// staus is used to inform fetching in base plugin
result.iProgressStatus = TFSProgress::EFSStatus_Status;
break;
default:
result.iProgressStatus = TFSProgress::EFSStatus_RequestComplete;
break;
}
if ( iStatus.Int() == KErrCancel )
{
result.iProgressStatus = TFSProgress::EFSStatus_RequestCancelled;
result.iError = KErrCancel;
}
return result;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::CIpsPlgPop3ConnectOp
// ----------------------------------------------------------------------------
//
CIpsPlgPop3ConnectOp::CIpsPlgPop3ConnectOp(
CMsvSession& aMsvSession,
TRequestStatus& aObserverRequestStatus,
TMsvId aServiceId,
TBool aForcePopulate,
CIpsPlgTimerOperation& aActivityTimer,
TFSMailMsgId aFSMailBoxId,
MFSMailRequestObserver& aFSOperationObserver,
TInt aFSRequestId,
CIpsPlgEventHandler* aEventHandler,
TBool aSignallingAllowed )
:
CIpsPlgOnlineOperation( aMsvSession, KConnectOpPriority,
aObserverRequestStatus, aActivityTimer, aFSMailBoxId,
aFSOperationObserver, aFSRequestId, aSignallingAllowed ),
iState( EIdle ),
iEntry( NULL ),
iPopulateLimit( KIpsPlgPop3PopulateLimitInitValue ),
iForcePopulate( aForcePopulate ),
iSelection( NULL ),
iEventHandler( aEventHandler ),
iAlreadyConnected( EFalse )
{
iService = aServiceId;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::ConstructL()
// ----------------------------------------------------------------------------
//
void CIpsPlgPop3ConnectOp::ConstructL()
{
FUNC_LOG;
BaseConstructL( KUidMsgTypePOP3 );
iEntry = iMsvSession.GetEntryL( iService );
if ( !iEntry )
{
User::Leave( KErrGeneral );
}
iSelection = new(ELeave) CMsvEntrySelection;
const TMsvEntry& tentry = iEntry->Entry();
if ( tentry.iType.iUid != KUidMsvServiceEntryValue )
{
// should we panic with own codes?
User::Leave( KErrNotSupported );
}
// get correct populate and sync limet values from settings
CImPop3Settings* settings = new(ELeave) CImPop3Settings();
CleanupStack::PushL( settings );
TPopAccount popAccountId;
CEmailAccounts* accounts = CEmailAccounts::NewLC();
accounts->GetPopAccountL( iService , popAccountId );
accounts->LoadPopSettingsL( popAccountId, *settings );
iPopulateLimit = settings->PopulationLimit();
if ( iPopulateLimit > 0 )
{
iPopulateLimit = ( iPopulateLimit * 1024 ) / 75;
}
else if ( iPopulateLimit == KIpsSetDataHeadersOnly )
{
iPopulateLimit = 0;
}
else
{
iPopulateLimit = KMaxTInt;
}
CleanupStack::PopAndDestroy( 2, settings );
if ( tentry.Connected() )
{
iState = EConnected;
iAlreadyConnected = ETrue;
SetActive();
CompleteThis();
}
else
{
iState = EStartConnect;
SetActive();
CompleteThis();
}
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::DoConnectL()
// ----------------------------------------------------------------------------
//
void CIpsPlgPop3ConnectOp::DoConnectL()
{
FUNC_LOG;
iStatus = KRequestPending;
InvokeClientMtmAsyncFunctionL( KPOP3MTMConnect, iService, iService );
SetActive();
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::DoPopulateL()
// ----------------------------------------------------------------------------
//
void CIpsPlgPop3ConnectOp::DoPopulateL()
{
FUNC_LOG;
iStatus = KRequestPending;
// Prepare parameters and include filtering
TImPop3PopulateOptions pop3GetMailInfo;
pop3GetMailInfo.SetMaxEmailSize( KMaxTInt32 );
pop3GetMailInfo.SetPopulationLimit( iPopulateLimit );
TPckgBuf<TImPop3PopulateOptions> params( pop3GetMailInfo );
iSelection->InsertL(0, iService);
iBaseMtm->SwitchCurrentEntryL( iService );
// Start the fetch operation
InvokeClientMtmAsyncFunctionL( KPOP3MTMPopulateAll, *iSelection,
iService, params);
SetActive();
if ( iEventHandler )
{
iEventHandler->SetNewPropertyEvent(
iService, KIpsSosEmailSyncStarted, KErrNone );
}
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
//
TBool CIpsPlgPop3ConnectOp::Connected() const
{
FUNC_LOG;
TMsvEntry tentry;
TMsvId service;
iMsvSession.GetEntry(iService, service, tentry );
return tentry.Connected();
}
// ----------------------------------------------------------------------------
// CIpsPlgImap4ConnectOp::IpsOpType()
// ----------------------------------------------------------------------------
//
TInt CIpsPlgPop3ConnectOp::IpsOpType() const
{
FUNC_LOG;
return EIpsOpTypePop3SyncOp;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::ValidateL()
// ----------------------------------------------------------------------------
//
TBool CIpsPlgPop3ConnectOp::ValidateL()
{
// do proper validation. OR: not needed?
return ETrue;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::QueryUserPassL()
// ----------------------------------------------------------------------------
//
TBool CIpsPlgPop3ConnectOp::QueryUserPassL()
{
FUNC_LOG;
if ( iEventHandler )
{
// ask for credentials for pop3 account and wait for callback
if ( iEventHandler->QueryUsrPassL( iEntry->EntryId(), this ) )
{
iState = EQueryingDetails;
}
else
{
// another operation is waiting for password
iState = EQueryingDetailsBusy;
}
return ETrue;
}
return EFalse;
}
// ----------------------------------------------------------------------------
// CIpsPlgPop3ConnectOp::GetOperationErrorCodeL()
// ----------------------------------------------------------------------------
//
TInt CIpsPlgPop3ConnectOp::GetOperationErrorCodeL( )
{
FUNC_LOG;
if ( iAlreadyConnected )
{
// Connected state was set in CIpsPlgPop3ConnectOp::ConstructL()
// so iOperation is null
return KErrNone;
}
if ( !iOperation )
{
return KErrNotFound;
}
if ( !iOperation->IsActive() && iOperation->iStatus.Int() != KErrNone )
{
return iOperation->iStatus.Int();
}
TPckgBuf<TPop3Progress> paramPack;
paramPack.Copy( iOperation->ProgressL() );
const TPop3Progress& progress = paramPack();
return progress.iErrorCode;
}
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
void CIpsPlgPop3ConnectOp::CredientialsSetL( TInt aEvent )
{
FUNC_LOG;
if ( iState == EQueryingDetails )
{
// response for our operation`s query
if ( aEvent == EIPSSosCredientialsCancelled )
{
// user canceled operation
CompleteObserver( KErrCancel );
}
// password has been set, continue with operation
SetActive();
CompleteThis();
}
else if ( iState == EQueryingDetailsBusy )
{
// response for other operation`s query
// we could try to ask for password now,
// but decision was made to cancel operation
CompleteObserver( KErrCancel );
SetActive();
CompleteThis();
}
}
//EOF