| 31 |      1 | // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
 | 
|  |      2 | // All rights reserved.
 | 
|  |      3 | // This component and the accompanying materials are made available
 | 
|  |      4 | // under the terms of "Eclipse Public License v1.0"
 | 
|  |      5 | // which accompanies this distribution, and is available
 | 
|  |      6 | // at the URL "http://www.eclipse.org/legal/epl-v10.html".
 | 
|  |      7 | //
 | 
|  |      8 | // Initial Contributors:
 | 
|  |      9 | // Nokia Corporation - initial contribution.
 | 
|  |     10 | //
 | 
|  |     11 | // Contributors:
 | 
|  |     12 | //
 | 
|  |     13 | // Description:
 | 
|  |     14 | //
 | 
|  |     15 | 
 | 
|  |     16 | #include <imapset.h>
 | 
|  |     17 | #include <mentact.h>
 | 
|  |     18 | #include <miut_err.h>
 | 
|  |     19 | 
 | 
|  |     20 | #include "cimapprotocolcontroller.h"
 | 
|  |     21 | #include "cimapsettings.h"
 | 
|  |     22 | #include "cimapsessionmanager.h"
 | 
|  |     23 | #include "cimapsession.h"
 | 
|  |     24 | #include "cimapsessionconsts.h"
 | 
|  |     25 | #include "cimapmailstore.h" 
 | 
|  |     26 | #include "cimapofflinecontrol.h"
 | 
|  |     27 | #include "cimapsyncmanager.h"
 | 
|  |     28 | #include "cimapfolder.h"
 | 
|  |     29 | 
 | 
|  |     30 | #include "cimapcompoundcopyfromlocal.h"
 | 
|  |     31 | #include "cimapcompoundcopytolocal.h"
 | 
|  |     32 | #include "cimapcompoundcopywithinservice.h"
 | 
|  |     33 | #include "cimapcompoundcreate.h"
 | 
|  |     34 | #include "cimapcompounddelete.h"
 | 
|  |     35 | #include "cimapcompounddeletefolder.h"
 | 
|  |     36 | #include "cimapcompounddisconnect.h"
 | 
|  |     37 | #include "cimapcompoundrename.h"
 | 
|  |     38 | #include "cimapcompoundselect.h"
 | 
|  |     39 | #include "cimapcompoundsyncfolder.h"
 | 
|  |     40 | #include "cimapcompoundsynctree.h"
 | 
|  |     41 | #include "cimapcompoundsyncservice.h"
 | 
|  |     42 | 
 | 
|  |     43 | #include "cimapopbackgroundsync.h"
 | 
|  |     44 | #include "cimapidlecontroller.h"
 | 
|  |     45 | #include "cimapupdateflagoperation.h"
 | 
|  |     46 | 
 | 
|  |     47 | #include "cimaplogger.h"
 | 
|  |     48 | 
 | 
|  |     49 | #include "mobilitytestmtmapi.h"
 | 
|  |     50 | 
 | 
|  |     51 | // at the moment we do not need more than 2 sessions
 | 
|  |     52 | const TInt KImapSessionArrayGranularity = 2;
 | 
|  |     53 | 
 | 
|  |     54 | const TUid KUidImapServerMtm = {0x10003C4E};
 | 
|  |     55 | 
 | 
|  |     56 | CImapProtocolController::CImapProtocolController(CMsvServerEntry& aEntry,CImapOfflineControl& aImapOfflineControl):
 | 
|  |     57 | 	CMsgActive(EPriorityStandard),
 | 
|  |     58 | 	iEntry(aEntry),
 | 
|  |     59 | 	iImapSessionArray(KImapSessionArrayGranularity),
 | 
|  |     60 | 	iImapOfflineControl(aImapOfflineControl)
 | 
|  |     61 | 	{
 | 
|  |     62 | 	}
 | 
|  |     63 | 	
 | 
|  |     64 | CImapProtocolController::~CImapProtocolController()
 | 
|  |     65 | 	{
 | 
|  |     66 | 	Cancel();
 | 
|  |     67 | 
 | 
|  |     68 | 	// The mail store needs to be deleted before DisconnectAll() as its destructor
 | 
|  |     69 | 	// uses the session that DisconnectAll() destroys.
 | 
|  |     70 | 	delete iImapMailStore;	
 | 
|  |     71 | 
 | 
|  |     72 | 	//serviceid indicates that we are online
 | 
|  |     73 | 	if(iServiceId!=0)
 | 
|  |     74 | 		{
 | 
|  |     75 | 		DisconnectAll();
 | 
|  |     76 | 		}
 | 
|  |     77 | 
 | 
|  |     78 | 	delete iBackgroundSyncOp;
 | 
|  |     79 | 	delete iImapCompound;
 | 
|  |     80 | 	delete iMigrateCompound;
 | 
|  |     81 | 	delete iImapSyncManager;
 | 
|  |     82 | 	delete iImapIdleController;
 | 
|  |     83 | 	delete iImapSettings;
 | 
|  |     84 | 	
 | 
|  |     85 | 	delete iMobilityManager;
 | 
|  |     86 | 
 | 
|  |     87 | 	// Need to destroy the sessions before the session manager is deleted.
 | 
|  |     88 | 	// This is because session manager will cleanup transport handler code,
 | 
|  |     89 | 	// and it is important to ensure that the sockets are not being used
 | 
|  |     90 | 	// by the session when that happens.
 | 
|  |     91 | 	iImapSessionArray.ResetAndDestroy();
 | 
|  |     92 | 	delete iImapSessionManager;
 | 
|  |     93 | 	}
 | 
|  |     94 | 
 | 
|  |     95 | EXPORT_C CImapProtocolController* CImapProtocolController::NewL(CMsvServerEntry& aEntry,CImapOfflineControl& aImapOfflineControl)
 | 
|  |     96 | 	{
 | 
|  |     97 | 	CImapProtocolController* self = new (ELeave) CImapProtocolController(aEntry,aImapOfflineControl);
 | 
|  |     98 | 	CleanupStack::PushL(self);
 | 
|  |     99 | 	self->ConstructL();
 | 
|  |    100 | 	CleanupStack::Pop(self);
 | 
|  |    101 | 	return self;
 | 
|  |    102 | 	}
 | 
|  |    103 | 
 | 
|  |    104 | /**
 | 
|  |    105 | Part of two phase construction
 | 
|  |    106 | Note that syncmanager is not constructed until a connection is made.
 | 
|  |    107 | */
 | 
|  |    108 | void CImapProtocolController::ConstructL()
 | 
|  |    109 | 	{
 | 
|  |    110 | 	iImapSettings       = CImapSettings::NewL(iEntry);
 | 
|  |    111 | 	iImapMailStore 		= CImapMailStore::NewL(iEntry);
 | 
|  |    112 | 	iImapSessionManager = CImapSessionManager::NewL(*iImapSettings, *iImapMailStore);
 | 
|  |    113 | 
 | 
|  |    114 | 	iFlushPrimary = EFalse;
 | 
|  |    115 | 	// We're an active object...
 | 
|  |    116 | 	CActiveScheduler::Add(this);
 | 
|  |    117 | 	}
 | 
|  |    118 | 
 | 
|  |    119 | /**
 | 
|  |    120 | Query connection status - return true if at least one IMAP Session exists and is 
 | 
|  |    121 | connected. Also return true if migrating.
 | 
|  |    122 | This is not a compound operation.
 | 
|  |    123 | 
 | 
|  |    124 | @return 
 | 
|  |    125 | */
 | 
|  |    126 | EXPORT_C TBool CImapProtocolController::Connected() const
 | 
|  |    127 | 	{
 | 
|  |    128 | 	if (iImapSessionArray.Count() > 0 || iMigrateState != ENotMigrating)
 | 
|  |    129 | 		{
 | 
|  |    130 | 		// Sessions are deleted if a disconnect is observed,
 | 
|  |    131 | 		// therefore the existance of any sessions indicates 
 | 
|  |    132 | 		// that the Protocol Controller is connected.
 | 
|  |    133 | 		return ETrue;
 | 
|  |    134 | 		}
 | 
|  |    135 | 	return EFalse;
 | 
|  |    136 | 	}
 | 
|  |    137 | 
 | 
|  |    138 | /**
 | 
|  |    139 | If a connected session already exists, this API shall complete immediately with 
 | 
|  |    140 | KErrServerBusy. Otherwise, this API uses the IMAP Session Manager to create and connect 
 | 
|  |    141 | an IMAP Session object that can be used for subsequent commands.
 | 
|  |    142 | On successful connection, the passed request status is completed. This API can not 
 | 
|  |    143 | be used to instantiate further IMAP Session objects.
 | 
|  |    144 | 
 | 
|  |    145 | Sequence For Connect
 | 
|  |    146 | 	CreateSession
 | 
|  |    147 | 	SelectInboxRW
 | 
|  |    148 | 	Finished
 | 
|  |    149 | 	
 | 
|  |    150 | @param aStatus
 | 
|  |    151 | @param aSelection
 | 
|  |    152 | @leave KErrServerBusy if a connected session already exists
 | 
|  |    153 | */
 | 
|  |    154 | EXPORT_C void CImapProtocolController::ConnectL( TRequestStatus& aStatus,
 | 
|  |    155 | 												 CMsvEntrySelection& aSelection )
 | 
|  |    156 | 	{
 | 
|  |    157 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::ConnectL()");
 | 
|  |    158 | 	
 | 
|  |    159 | 	ResetProgress();
 | 
|  |    160 | 	
 | 
|  |    161 | 	if (Connected())
 | 
|  |    162 | 		{
 | 
|  |    163 | 		// Do not call Complete() - this would result in the Protocol
 | 
|  |    164 | 		// Controller disconnecting all sessions.
 | 
|  |    165 | 		TRequestStatus* pStatus = &aStatus;
 | 
|  |    166 | 		User::RequestComplete(pStatus, KErrServerBusy);
 | 
|  |    167 | 		}
 | 
|  |    168 | 	else
 | 
|  |    169 | 		{
 | 
|  |    170 | 		// Load the Service Settings
 | 
|  |    171 | 		iServiceId = aSelection[0];
 | 
|  |    172 | 		iImapSettings->LoadSettingsL(iServiceId);
 | 
|  |    173 | 
 | 
|  |    174 | 		// We're going online - create a session manager if none exists
 | 
|  |    175 | 		if (iImapSessionManager==NULL)
 | 
|  |    176 | 			{
 | 
|  |    177 | 			// session manage may have been deleted due to a mobility error
 | 
|  |    178 | 			iImapSessionManager = CImapSessionManager::NewL(*iImapSettings, *iImapMailStore);
 | 
|  |    179 | 			}
 | 
|  |    180 | 	
 | 
|  |    181 | 		// create a sync manager
 | 
|  |    182 | 		delete iImapSyncManager;
 | 
|  |    183 | 		iImapSyncManager = NULL;
 | 
|  |    184 | 		iImapSyncManager = CImapSyncManager::NewL( iEntry, *iImapSettings);
 | 
|  |    185 | 		
 | 
|  |    186 | 		// create the mobility manager if mobility supported
 | 
|  |    187 | 		delete iMobilityManager;
 | 
|  |    188 | 		iMobilityManager = NULL;
 | 
|  |    189 | 
 | 
|  |    190 | 		if (iImapSettings->BearerMobility())
 | 
|  |    191 | 			{
 | 
|  |    192 | 			iMobilityManager = CImMobilityManager::NewL(KUidImapServerMtm, iServiceId, *this);
 | 
|  |    193 | 			}
 | 
|  |    194 | 	
 | 
|  |    195 | 		// Create the primary session pointer
 | 
|  |    196 | 		CImapSession* imapSession = NULL;
 | 
|  |    197 | 		iImapSessionArray.AppendL(imapSession);
 | 
|  |    198 | 
 | 
|  |    199 | 		// Request the session manager to connect the session
 | 
|  |    200 | 		iImapSessionManager->GetSessionL(iStatus, iImapSessionArray[0]);
 | 
|  |    201 | 
 | 
|  |    202 | 		iForegroundSession = 0;
 | 
|  |    203 | 		iRequestedOp = EConnect;
 | 
|  |    204 | 		iCurrentOp = iRequestedOp;
 | 
|  |    205 | 
 | 
|  |    206 | 		Queue(aStatus);
 | 
|  |    207 | 		SetActive();
 | 
|  |    208 | 		}
 | 
|  |    209 | 	}
 | 
|  |    210 | 
 | 
|  |    211 | /**
 | 
|  |    212 | This method allows the client to connect to an IMAP account and initialise a 
 | 
|  |    213 | background synchronisation of the account once connection has completed. If a 
 | 
|  |    214 | connected IMAP Session already exists, the API shall complete immdediately with 
 | 
|  |    215 | KErrServerBusy. 
 | 
|  |    216 | On successful connection, a background synchronisation is started and the passed 
 | 
|  |    217 | request status is completed. The background synchronisation is processed by a 
 | 
|  |    218 | CImapBackgroundSyncOp object, which will notify the Protocol Controller that 
 | 
|  |    219 | the process has completed via a callback function void 
 | 
|  |    220 | BackgroundSyncCompleted( TInt aError )
 | 
|  |    221 | 
 | 
|  |    222 | Sequence For ConnectAndSynchronise
 | 
|  |    223 | 	CreateSession
 | 
|  |    224 | 	StartBackgroundSyncOp
 | 
|  |    225 | 	Finished
 | 
|  |    226 | 
 | 
|  |    227 | @param aStatus
 | 
|  |    228 | @param aSelection
 | 
|  |    229 | @leave KErrServerBusy if a connected session already exists
 | 
|  |    230 | */
 | 
|  |    231 | EXPORT_C void CImapProtocolController::ConnectAndSynchroniseL( TRequestStatus& aStatus, 
 | 
|  |    232 | 															   CMsvEntrySelection& aSelection )
 | 
|  |    233 | 	{
 | 
|  |    234 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::ConnectAndSynchroniseL()");
 | 
|  |    235 | 
 | 
|  |    236 | 	// Issue the connect request (this will cause ResetProgress() to be called)
 | 
|  |    237 | 	ConnectL(aStatus, aSelection);
 | 
|  |    238 | 
 | 
|  |    239 | 	// Create the Background Sync Operation object
 | 
|  |    240 | 	if (IsActive())
 | 
|  |    241 | 		{
 | 
|  |    242 | 		__ASSERT_DEBUG(iBackgroundSyncOp==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EConnectAndSyncBgSyncOpIsNotNull));
 | 
|  |    243 | 		iBackgroundSyncOp = CImapOpBackgroundSync::NewL(*this, iEntry, *iImapSyncManager, *iImapSettings, *iImapMailStore, iImapOfflineControl);
 | 
|  |    244 | 		}
 | 
|  |    245 | 	}
 | 
|  |    246 | 
 | 
|  |    247 | /**
 | 
|  |    248 | Logs out and disconnects all connected sessions with the remote server.
 | 
|  |    249 | 
 | 
|  |    250 | Disconnect request is handled and acted upon during migration, unlike other 
 | 
|  |    251 | client-requested operations which are rejected (with KErrServerBusy).
 | 
|  |    252 | 
 | 
|  |    253 | The Bearer Mobility Manager is deleted prior to acting on this request,
 | 
|  |    254 | effectively de-registering the server MTM from the mobility framework
 | 
|  |    255 | 
 | 
|  |    256 | @param aStatus
 | 
|  |    257 | */
 | 
|  |    258 | EXPORT_C void CImapProtocolController::DisconnectL(TRequestStatus& aStatus)
 | 
|  |    259 | 	{
 | 
|  |    260 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectL()");
 | 
|  |    261 | 
 | 
|  |    262 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EDisconnectCompoundIsNotNull));
 | 
|  |    263 | 	
 | 
|  |    264 | 	// de-register for mobility notifications
 | 
|  |    265 | 	delete iMobilityManager;
 | 
|  |    266 | 	iMobilityManager = NULL;
 | 
|  |    267 | 	
 | 
|  |    268 | 	// Disconnect allowed to happen even if we are migrating...
 | 
|  |    269 | 	switch (iMigrateState)
 | 
|  |    270 | 		{
 | 
|  |    271 | 		case ENotMigrating:
 | 
|  |    272 | 		case EHandlingConnectError:
 | 
|  |    273 | 			{
 | 
|  |    274 | 			// normal behaviour...
 | 
|  |    275 | 			DoDisconnectL(aStatus);
 | 
|  |    276 | 			break;
 | 
|  |    277 | 			}
 | 
|  |    278 | 		case EConnectingAfterMigrate: // Cancel connecting of new session
 | 
|  |    279 | 		case EStartingReconnect:	  // already disconnected. Cancel dummy request
 | 
|  |    280 | 		case EWaitingForNewCarrier:   // already disconnected. Cancel dummy request
 | 
|  |    281 | 		case EWaitingInitialCarrierRejected: // already disconnected. Cancel dummy request
 | 
|  |    282 | 			{
 | 
|  |    283 | 			Cancel();
 | 
|  |    284 | 			// mark offline and complete
 | 
|  |    285 | 			DisconnectAll();
 | 
|  |    286 | 			Queue(aStatus);
 | 
|  |    287 | 			Complete(KErrNone);
 | 
|  |    288 | 			break;
 | 
|  |    289 | 			}
 | 
|  |    290 | 		case EDisconnectingForMigrate:
 | 
|  |    291 | 			{
 | 
|  |    292 | 			// already doing a graceful disconnect, switch to main state machine.
 | 
|  |    293 | 			iMigrateState = ENotMigrating;
 | 
|  |    294 | 			iRequestedOp  = EDisconnect;
 | 
|  |    295 | 			iCurrentOp    = EDisconnect;
 | 
|  |    296 | 			// however, using the iMigrateCompound pointer...
 | 
|  |    297 | 			iImapCompound = iMigrateCompound;
 | 
|  |    298 | 			iMigrateCompound = NULL;
 | 
|  |    299 | 			Queue(aStatus);
 | 
|  |    300 | 			break;
 | 
|  |    301 | 			}
 | 
|  |    302 | 		case EWaitingForOpToComplete:
 | 
|  |    303 | 		case EWaitingForOpToStop:
 | 
|  |    304 | 		default:
 | 
|  |    305 | 			{
 | 
|  |    306 | 			__ASSERT_DEBUG(iBackgroundSyncOp==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EDisconnectUnexpectedMigrateState));
 | 
|  |    307 | 			break;
 | 
|  |    308 | 			}
 | 
|  |    309 | 		}
 | 
|  |    310 | 	}
 | 
|  |    311 | 
 | 
|  |    312 | void CImapProtocolController::DoDisconnectL(TRequestStatus& aStatus)
 | 
|  |    313 | 	{
 | 
|  |    314 | 	// Unlike the other async methods, DisconnectL() will wait for any flush operation to finish
 | 
|  |    315 | 	// and then initiate the disconnect.
 | 
|  |    316 | 	// Consequently there is no need to call CompleteIfBackgroundOpInProgress()	
 | 
|  |    317 | 	ResetProgress();
 | 
|  |    318 | 	
 | 
|  |    319 | 	iImapCompound = CImapCompoundDisconnect::NewL( *iImapSyncManager, 
 | 
|  |    320 | 												   iEntry, 
 | 
|  |    321 | 												   *iImapSettings,
 | 
|  |    322 | 												   *iImapSessionManager,
 | 
|  |    323 | 												   *iImapMailStore,
 | 
|  |    324 | 												   iImapSessionArray,
 | 
|  |    325 | 												   iImapOfflineControl,
 | 
|  |    326 | 												   ETrue );
 | 
|  |    327 | 	iRequestedOp = EDisconnect;
 | 
|  |    328 | 	
 | 
|  |    329 | 	if (iCurrentOp != ECancelRecoverPrimary)
 | 
|  |    330 | 		{
 | 
|  |    331 | 		// Cancel any outstanding background sync												   
 | 
|  |    332 | 		if (iBackgroundSyncOp!=NULL)
 | 
|  |    333 | 			{
 | 
|  |    334 | 			iBackgroundSyncOp->Cancel();
 | 
|  |    335 | 			delete iBackgroundSyncOp;
 | 
|  |    336 | 			iBackgroundSyncOp=NULL;
 | 
|  |    337 | 
 | 
|  |    338 | 			// Flush the session, now that it has been cancelled
 | 
|  |    339 | 			iCurrentOp = ECancelRecoverPrimary;
 | 
|  |    340 | 			CImapSession* session = iImapSessionArray[0];
 | 
|  |    341 | 			session->FlushCancelledCommand(iStatus);
 | 
|  |    342 | 			SetActive();
 | 
|  |    343 | 			}
 | 
|  |    344 | 		else
 | 
|  |    345 | 			{
 | 
|  |    346 | 			StartPrimaryOperation();	
 | 
|  |    347 | 			SetActive();	
 | 
|  |    348 | 			}
 | 
|  |    349 | 		}
 | 
|  |    350 | 	
 | 
|  |    351 | 	// NOTE: In the case of iCurrentOp == ECancelRecoverPrimary, DoRunL() will start the async 
 | 
|  |    352 | 	// iImapCompound operation after the flush has completed.
 | 
|  |    353 | 	// The iImapCompound will expect aStatus to have been queued so that it can be Completed later.
 | 
|  |    354 | 	
 | 
|  |    355 | 	Queue(aStatus);
 | 
|  |    356 | 	}
 | 
|  |    357 | 
 | 
|  |    358 | /**
 | 
|  |    359 | Checks the status of the CImapSessions
 | 
|  |    360 | 
 | 
|  |    361 | @return ETrue if a backgroundsync is in progress and the second session is busy,
 | 
|  |    362 | 		EFalse otherwise.
 | 
|  |    363 | */
 | 
|  |    364 | EXPORT_C TBool CImapProtocolController::Busy() const
 | 
|  |    365 | 	{
 | 
|  |    366 | 	// second session is busy if a compound operation exists.
 | 
|  |    367 | 	if (BackgroundSyncInProgress() && iImapCompound!=NULL)
 | 
|  |    368 | 		{
 | 
|  |    369 | 		return ETrue;
 | 
|  |    370 | 		}
 | 
|  |    371 | 	return EFalse;	
 | 
|  |    372 | 					
 | 
|  |    373 | 	}
 | 
|  |    374 | 
 | 
|  |    375 | /**
 | 
|  |    376 | Gets the access point ID in use for the connection to the server
 | 
|  |    377 | 
 | 
|  |    378 | @param aIap On return stores the access point ID value
 | 
|  |    379 | 
 | 
|  |    380 | @return KErrNone if successful, or a system wide error code
 | 
|  |    381 | */
 | 
|  |    382 | EXPORT_C TInt CImapProtocolController::GetAccessPointIdForConnection(TUint32& aAccessPointId) const
 | 
|  |    383 | 	{
 | 
|  |    384 | 	if (iImapSessionManager)
 | 
|  |    385 | 		{
 | 
|  |    386 | 		return iImapSessionManager->GetAccessPointIdForConnection(aAccessPointId);
 | 
|  |    387 | 		}
 | 
|  |    388 | 
 | 
|  |    389 | 	return KErrNotFound;
 | 
|  |    390 | 	}
 | 
|  |    391 | 
 | 
|  |    392 | /**
 | 
|  |    393 | Returns whether a Background synchronisation is in progress
 | 
|  |    394 | 
 | 
|  |    395 | @return ETrue if a Background synchronisation is in progress, EFalse otherwise
 | 
|  |    396 | */
 | 
|  |    397 | EXPORT_C TBool CImapProtocolController::BackgroundSyncInProgress() const
 | 
|  |    398 | 	{
 | 
|  |    399 | 	return (iBackgroundSyncOp != NULL);
 | 
|  |    400 | 	}
 | 
|  |    401 | 
 | 
|  |    402 | /**
 | 
|  |    403 | Cancels an outstanding background synchronise operation. Calls 
 | 
|  |    404 | CImapOpBackgroundSync::Cancel() to propagate the cancel and kicks off
 | 
|  |    405 | an asynchronous cleanup operation.
 | 
|  |    406 | The cancel request is completed immediately with KErrNone if no background
 | 
|  |    407 | sync was in operation, otherwise it is completed with KErrCancel when
 | 
|  |    408 | the cleanup process is complete.
 | 
|  |    409 | */	
 | 
|  |    410 | EXPORT_C void CImapProtocolController::CancelBackgroundSync(TRequestStatus& aStatus)
 | 
|  |    411 | 	{
 | 
|  |    412 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CancelBackgroundSync()");
 | 
|  |    413 | 	
 | 
|  |    414 | 	ResetProgress();
 | 
|  |    415 | 	
 | 
|  |    416 | 	Queue(aStatus);
 | 
|  |    417 | 	if (BackgroundSyncInProgress())
 | 
|  |    418 | 		{
 | 
|  |    419 | 		if (iMigrateState != ENotMigrating && iBackgroundSyncOp->IsSuspendedForMigrate())
 | 
|  |    420 | 			{
 | 
|  |    421 | 			delete iBackgroundSyncOp;
 | 
|  |    422 | 			iBackgroundSyncOp = NULL;
 | 
|  |    423 | 			Complete(KErrCancel);
 | 
|  |    424 | 			}
 | 
|  |    425 | 		else
 | 
|  |    426 | 			{
 | 
|  |    427 | 			iBackgroundSyncOp->CancelAndCleanup();
 | 
|  |    428 | 			iWaitForBackgroundSync = ETrue;
 | 
|  |    429 | 			}
 | 
|  |    430 | 		}
 | 
|  |    431 | 	else
 | 
|  |    432 | 		{
 | 
|  |    433 | 		Complete(KErrNone);
 | 
|  |    434 | 		}
 | 
|  |    435 | 	}
 | 
|  |    436 | 
 | 
|  |    437 | /**
 | 
|  |    438 | Wait for background sync operation to complete. This effectively makes a background 
 | 
|  |    439 | synchronise a foreground operation blocking subsequent Server MTM requests until the 
 | 
|  |    440 | synchonise is completed.
 | 
|  |    441 | 
 | 
|  |    442 | @param aStatus
 | 
|  |    443 | */
 | 
|  |    444 | EXPORT_C void CImapProtocolController::WaitForBackground(TRequestStatus& aStatus)
 | 
|  |    445 | 	{
 | 
|  |    446 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::WaitForBackground()");
 | 
|  |    447 | 	
 | 
|  |    448 | 	ResetProgress();
 | 
|  |    449 | 	
 | 
|  |    450 | 	Queue(aStatus);
 | 
|  |    451 | 	// Wait for background operation to complete: is one running?
 | 
|  |    452 | 	if (!BackgroundSyncInProgress())
 | 
|  |    453 | 		{
 | 
|  |    454 | 		// No, complete immediately
 | 
|  |    455 | 		Complete(KErrNone);
 | 
|  |    456 | 		}
 | 
|  |    457 | 	else
 | 
|  |    458 | 		{
 | 
|  |    459 | 		// Otherwise, wait for completion
 | 
|  |    460 | 		iWaitForBackgroundSync = ETrue;
 | 
|  |    461 | 		}
 | 
|  |    462 | 	}
 | 
|  |    463 | 
 | 
|  |    464 | 
 | 
|  |    465 | /**
 | 
|  |    466 | Completes the passed request status if a background operation is in progress,
 | 
|  |    467 | or if the primary session is being recovered following a cancel operation.
 | 
|  |    468 | This should be called prior to starting a compound operation that requires the
 | 
|  |    469 | primary session to be performed.
 | 
|  |    470 | 
 | 
|  |    471 | This method must be called before assigning iRequestedOp, 
 | 
|  |    472 | for any operation that requires the primary session.
 | 
|  |    473 | 
 | 
|  |    474 | @return ETrue if the user request has been completed
 | 
|  |    475 | 		EFalse otherwise.
 | 
|  |    476 | */
 | 
|  |    477 | TBool CImapProtocolController::CompleteIfBackgroundOpInProgress(TRequestStatus& aStatus)
 | 
|  |    478 | 	{
 | 
|  |    479 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CompleteIfBackgroundOpInProgress()");
 | 
|  |    480 | 	if (BackgroundSyncInProgress() || iCurrentOp==ECancelRecoverPrimary || iMigrateState!=ENotMigrating)
 | 
|  |    481 | 		{
 | 
|  |    482 | 		// Complete the user request
 | 
|  |    483 | 		// Do not call Complete() - this would result in the Protocol
 | 
|  |    484 | 		// Controller disconnecting all sessions.
 | 
|  |    485 | 		TRequestStatus* status = &aStatus;
 | 
|  |    486 | 		User::RequestComplete(status, KErrServerBusy);
 | 
|  |    487 | 		return ETrue;
 | 
|  |    488 | 		}
 | 
|  |    489 | 	return EFalse;
 | 
|  |    490 | 	}
 | 
|  |    491 | 	
 | 
|  |    492 | /**
 | 
|  |    493 | Synchronise Folder Tree - calls CImapSyncManager::SynchroniseTreeL()
 | 
|  |    494 | Sequence For SynchroniseTree
 | 
|  |    495 | 	StopIdle
 | 
|  |    496 | 	SynchroniseTree // CImapSyncManager Operation
 | 
|  |    497 | 
 | 
|  |    498 | @param aStatus
 | 
|  |    499 | @leave
 | 
|  |    500 | */	
 | 
|  |    501 | EXPORT_C void CImapProtocolController::SynchroniseTreeL(TRequestStatus& aStatus)
 | 
|  |    502 | 	{
 | 
|  |    503 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::SynchroniseTreeL()");
 | 
|  |    504 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ESynchroniseTreeCompoundIsNotNull));
 | 
|  |    505 | 
 | 
|  |    506 | 	ResetProgress();
 | 
|  |    507 | 
 | 
|  |    508 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |    509 | 		{
 | 
|  |    510 | 		iImapCompound = CImapCompoundSyncTree::NewL( *iImapSyncManager, 
 | 
|  |    511 | 													 iEntry, 
 | 
|  |    512 | 													 *iImapSettings );
 | 
|  |    513 | 		
 | 
|  |    514 | 		iRequestedOp = ESync;
 | 
|  |    515 | 		StartPrimaryOperation();	
 | 
|  |    516 | 		Queue(aStatus);
 | 
|  |    517 | 		SetActive();
 | 
|  |    518 | 		}
 | 
|  |    519 | 	}
 | 
|  |    520 | 
 | 
|  |    521 | 
 | 
|  |    522 | /**
 | 
|  |    523 | Perform a full account synchronisation - calls CImapSyncManager::SynchroniseL()
 | 
|  |    524 | Sequence For SynchroniseAll
 | 
|  |    525 | 	StopIdle
 | 
|  |    526 | 	SynchroniseL  // CImapSyncManager Operation
 | 
|  |    527 | 
 | 
|  |    528 | @param aStatus
 | 
|  |    529 | @leave
 | 
|  |    530 | */	
 | 
|  |    531 | EXPORT_C void CImapProtocolController::SynchroniseAllL( TRequestStatus& aStatus )
 | 
|  |    532 | 	{
 | 
|  |    533 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::SynchroniseAllL()");
 | 
|  |    534 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ESynchroniseAllCompoundIsNotNull));
 | 
|  |    535 | 
 | 
|  |    536 | 	ResetProgress();
 | 
|  |    537 | 
 | 
|  |    538 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |    539 | 		{
 | 
|  |    540 | 		iImapCompound = CImapCompoundSyncService::NewL( *iImapSyncManager, 
 | 
|  |    541 | 												    	iEntry, 
 | 
|  |    542 | 												    	*iImapSettings,
 | 
|  |    543 | 												    	*iImapMailStore,
 | 
|  |    544 | 												    	iImapOfflineControl,
 | 
|  |    545 | 												    	EFalse);
 | 
|  |    546 | 	
 | 
|  |    547 | 		iRequestedOp = ESync;
 | 
|  |    548 | 		StartPrimaryOperation();	
 | 
|  |    549 | 		Queue(aStatus);
 | 
|  |    550 | 		SetActive();
 | 
|  |    551 | 		}
 | 
|  |    552 | 	}
 | 
|  |    553 | 
 | 
|  |    554 | /**
 | 
|  |    555 | Callback function to notify Protocol Controller that a background sync 
 | 
|  |    556 | operation has completed.
 | 
|  |    557 | Deletes the CImapOpBackgroundComplete object that has just completed.
 | 
|  |    558 | If WaitForBackground has been previously called, completes the user request.
 | 
|  |    559 | 
 | 
|  |    560 | @param aError
 | 
|  |    561 | */	
 | 
|  |    562 | EXPORT_C void CImapProtocolController::BackgroundSyncComplete(TInt aError)
 | 
|  |    563 | 	{
 | 
|  |    564 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::BackgroundSyncComplete()");
 | 
|  |    565 | 	__ASSERT_DEBUG(iBackgroundSyncOp!=NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ENoBackgroundSyncInProgress));
 | 
|  |    566 | 
 | 
|  |    567 | 	// get final sync progress... 
 | 
|  |    568 | 	// unless a foreground operation is being performed
 | 
|  |    569 | 	if (iImapCompound == NULL)
 | 
|  |    570 | 		{
 | 
|  |    571 | 		iBackgroundSyncOp->Progress(iProgress);
 | 
|  |    572 | 		}
 | 
|  |    573 | 		
 | 
|  |    574 | 	if (iMigrateState != ENotMigrating)
 | 
|  |    575 | 		{
 | 
|  |    576 | 		// If the protocol controller is not active, then there is no
 | 
|  |    577 | 		// operation currently in progress. Therefore we are now ready to
 | 
|  |    578 | 		// migrate. Complete the request here, and then Disconnect current sockets in DoMigrateRunL(). 
 | 
|  |    579 | 		// We cannot just test existance of a compound operation object, as there may be a "paused" operation.
 | 
|  |    580 | 		if (!IsActive())
 | 
|  |    581 | 			{
 | 
|  |    582 | 			// Complete the request so that, we migrate from DoMigrateRunL()
 | 
|  |    583 | 			SetActive();
 | 
|  |    584 | 			TRequestStatus* pStatus = &iStatus;
 | 
|  |    585 | 			User::RequestComplete(pStatus, KErrNone);
 | 
|  |    586 | 			}
 | 
|  |    587 | 		
 | 
|  |    588 | 		// the background sync may have been completed early to allow
 | 
|  |    589 | 		// a migration to occur. If that is the case, then we do not want
 | 
|  |    590 | 		// to delete the background sync operation object - it will need
 | 
|  |    591 | 		// to be restarted once the migrate has occurred. Otherwise, just
 | 
|  |    592 | 		// process the completion of the background sync normally.
 | 
|  |    593 | 		if (iBackgroundSyncOp->IsSuspendedForMigrate())
 | 
|  |    594 | 			{
 | 
|  |    595 | 			return;
 | 
|  |    596 | 			}
 | 
|  |    597 | 		}
 | 
|  |    598 | 
 | 
|  |    599 | 	// Deleting the background sync op.
 | 
|  |    600 | 	// CImapOpBackgroundComplete must finish immediately after calling this API
 | 
|  |    601 | 	delete iBackgroundSyncOp;
 | 
|  |    602 | 	iBackgroundSyncOp = NULL;
 | 
|  |    603 | 	
 | 
|  |    604 | 	if (aError>0)
 | 
|  |    605 | 		{
 | 
|  |    606 | 		// translate positive error codes, weed out non-fatal errors
 | 
|  |    607 | 		ThranslateSessionError(aError);
 | 
|  |    608 | 		}
 | 
|  |    609 | 
 | 
|  |    610 | 	TBool foregroundOpCancelled = EFalse;
 | 
|  |    611 | 	if (aError==KErrNone || aError==KErrCancel)
 | 
|  |    612 | 		{
 | 
|  |    613 | 		if (iImapCompound==NULL && iMigrateState == ENotMigrating)
 | 
|  |    614 | 			{
 | 
|  |    615 | 			// only start IDLE if foreground operation not in progress
 | 
|  |    616 | 			StartIdle();
 | 
|  |    617 | 			MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStateImapIdle);
 | 
|  |    618 | 			}
 | 
|  |    619 | 		}
 | 
|  |    620 | 	else
 | 
|  |    621 | 		{
 | 
|  |    622 | 		// Cancel any foreground operation - the primary session has
 | 
|  |    623 | 		// failed, so all sessions are to be torn down.
 | 
|  |    624 | 		if (iImapCompound != NULL)
 | 
|  |    625 | 			{
 | 
|  |    626 | 			iImapCompound->Cancel();
 | 
|  |    627 | 			foregroundOpCancelled = ETrue;
 | 
|  |    628 | 			delete iImapCompound;
 | 
|  |    629 | 			iImapCompound=NULL;
 | 
|  |    630 | 			}
 | 
|  |    631 | 
 | 
|  |    632 | 		// DisconnectAll will be process by DoComplete if a client request is outstanding.
 | 
|  |    633 | 		if (!iWaitForBackgroundSync && !foregroundOpCancelled)
 | 
|  |    634 | 			{
 | 
|  |    635 | 			// Drop all session connections and mark the service offline.
 | 
|  |    636 | 			DisconnectAll();
 | 
|  |    637 | 			}
 | 
|  |    638 | 		}
 | 
|  |    639 | 
 | 
|  |    640 | 	// Store the error in the progress object
 | 
|  |    641 | 	iProgress.iGenericProgress.iErrorCode=aError;
 | 
|  |    642 | 	iProgress.iGenericProgress.iState=TImap4GenericProgress::EIdle;
 | 
|  |    643 | 		
 | 
|  |    644 | 	// Complete the client request if it was waiting for notification of 
 | 
|  |    645 | 	// bg sync complete, or if we have cancelled an foreground operation
 | 
|  |    646 | 	if (iWaitForBackgroundSync || foregroundOpCancelled)
 | 
|  |    647 | 		{
 | 
|  |    648 | 		iCancelInProgress = ETrue;
 | 
|  |    649 | 		Complete(aError);
 | 
|  |    650 | 		iCancelInProgress = EFalse;
 | 
|  |    651 | 		}
 | 
|  |    652 | 
 | 
|  |    653 | 	iWaitForBackgroundSync = EFalse;
 | 
|  |    654 | 	}
 | 
|  |    655 | 
 | 
|  |    656 | /**
 | 
|  |    657 | CopyToLocalL() is used to fetch a selection of messages from the remote 
 | 
|  |    658 | server as a single operation, without return to idle state between handling each
 | 
|  |    659 | message. The email is fetched to the local mirror of the containing folder. Optionally 
 | 
|  |    660 | this function can also copy the message to a local folder, specified in aDestination. 
 | 
|  |    661 | A fetch to mirror only is performed by calling with aDestination set to 
 | 
|  |    662 | KMsvNullIndexEntryId
 | 
|  |    663 | 
 | 
|  |    664 | Sequence For CopyToLocal
 | 
|  |    665 | 	StopIdle
 | 
|  |    666 | 	SelectSourceMailboxRO
 | 
|  |    667 | 	FetchMessage(s)
 | 
|  |    668 | 	InboxDuplicateCopy
 | 
|  |    669 | 
 | 
|  |    670 | @param aStatus
 | 
|  |    671 | @param aSourceSel
 | 
|  |    672 | @param aDestination
 | 
|  |    673 | */
 | 
|  |    674 | EXPORT_C void CImapProtocolController::CopyToLocalL(TRequestStatus& aStatus, 
 | 
|  |    675 | 													const CMsvEntrySelection& aSourceSel, 
 | 
|  |    676 | 													const TMsvId aDestination)
 | 
|  |    677 | 	{
 | 
|  |    678 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CopyToLocalL()");
 | 
|  |    679 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyToLocalCompoundIsNotNull));
 | 
|  |    680 | 
 | 
|  |    681 | 	ResetProgress();
 | 
|  |    682 | 
 | 
|  |    683 | 	// Instead of calling CompleteIfBackgroundOpInProgress(), just check whether a flush is occurring 
 | 
|  |    684 | 	// on the primary session (always index 0).
 | 
|  |    685 | 	// If a background op is in progress, then the copy will be performed on a secondary session.
 | 
|  |    686 | 	if (iCurrentOp == ECancelRecoverPrimary || iMigrateState != ENotMigrating)
 | 
|  |    687 | 		{
 | 
|  |    688 | 		// Do not call Complete() - this would result in the Protocol
 | 
|  |    689 | 		// Controller disconnecting all sessions.
 | 
|  |    690 | 		TRequestStatus* pStatus = &aStatus;
 | 
|  |    691 | 		User::RequestComplete(pStatus, KErrServerBusy);
 | 
|  |    692 | 
 | 
|  |    693 | 		return;
 | 
|  |    694 | 		}
 | 
|  |    695 | 	
 | 
|  |    696 | 	// must be set before calling SelectSession
 | 
|  |    697 | 	iRequestedOp = ECopyToLocal;
 | 
|  |    698 | 
 | 
|  |    699 | 	// request the session to use.
 | 
|  |    700 | 	TBool startNow = SelectSessionL(iForegroundSession);
 | 
|  |    701 | 
 | 
|  |    702 | 	if (iBackgroundSyncOp && iImapSettings->UseSyncDownloadRules())
 | 
|  |    703 | 		{
 | 
|  |    704 | 		// we need a non-const copy of the message selection to operate on.
 | 
|  |    705 | 		CMsvEntrySelection* selection = aSourceSel.CopyLC();
 | 
|  |    706 | 		
 | 
|  |    707 | 		// show the list to the background sync controller
 | 
|  |    708 | 		iBackgroundSyncOp->RemoveFromSelectionL(*selection);
 | 
|  |    709 | 		// Create the copy to local operation object using the (possibly) updated selection
 | 
|  |    710 | 		iImapCompound = CImapCompoundCopyToLocal::NewL(*iImapSyncManager, 
 | 
|  |    711 | 		                    			               iEntry, 
 | 
|  |    712 | 		                                			   *iImapSettings,
 | 
|  |    713 | 		                                			   *iImapMailStore,
 | 
|  |    714 | 		                                               EFalse,
 | 
|  |    715 | 		                                               *selection,
 | 
|  |    716 | 		                                               aDestination);
 | 
|  |    717 | 		CleanupStack::PopAndDestroy(selection);
 | 
|  |    718 | 		}
 | 
|  |    719 | 	else
 | 
|  |    720 | 		{
 | 
|  |    721 | 		// Create the compound operation object
 | 
|  |    722 | 		iImapCompound = CImapCompoundCopyToLocal::NewL(*iImapSyncManager, 
 | 
|  |    723 | 		                    			               iEntry, 
 | 
|  |    724 | 		                                			   *iImapSettings,
 | 
|  |    725 | 		                                			   *iImapMailStore,
 | 
|  |    726 | 		                                               EFalse,
 | 
|  |    727 | 		                                               aSourceSel,
 | 
|  |    728 | 		                                               aDestination);
 | 
|  |    729 | 		}
 | 
|  |    730 | 
 | 
|  |    731 | 	if (startNow)
 | 
|  |    732 | 		{
 | 
|  |    733 | 		// A session is ready - start the command
 | 
|  |    734 | 		// otherwise a request to connect a secondary session has been issued
 | 
|  |    735 | 		if (iForegroundSession==0)
 | 
|  |    736 | 			{
 | 
|  |    737 | 			// Primary session
 | 
|  |    738 | 			StartPrimaryOperation();
 | 
|  |    739 | 			}
 | 
|  |    740 | 		else
 | 
|  |    741 | 			{
 | 
|  |    742 | 			// Secondary session
 | 
|  |    743 | 			iCurrentOp = iRequestedOp;
 | 
|  |    744 | 			iImapCompound->StartOperation(iStatus, *iImapSessionArray[iForegroundSession]);
 | 
|  |    745 | 			}
 | 
|  |    746 | 		}	
 | 
|  |    747 | 	
 | 
|  |    748 | 	Queue(aStatus);
 | 
|  |    749 | 	SetActive();
 | 
|  |    750 | 	}
 | 
|  |    751 | 
 | 
|  |    752 | 
 | 
|  |    753 | /**
 | 
|  |    754 | PopulateL() performs the same action as CopyToLocalL(), however uses the passed 
 | 
|  |    755 | TImImap4GetPartialMailInfo object instead of using the default parameters. This 
 | 
|  |    756 | allows the client application to specify the parts of the message that are to be 
 | 
|  |    757 | fetched, and to impose limits to on the amount of data that can be transferred.
 | 
|  |    758 | 
 | 
|  |    759 | Sequence For Populate
 | 
|  |    760 | 	StopIdle
 | 
|  |    761 | 	SelectSourceMailboxRO
 | 
|  |    762 | 	FetchMessage(s)
 | 
|  |    763 | 	InboxDuplicateCopy
 | 
|  |    764 | 
 | 
|  |    765 | @param aStatus
 | 
|  |    766 | @param aSourceSel
 | 
|  |    767 | @param aGetPartialMailInfo
 | 
|  |    768 | */
 | 
|  |    769 | EXPORT_C void CImapProtocolController::PopulateL(TRequestStatus& aStatus, 
 | 
|  |    770 |                                                  const CMsvEntrySelection& aSourceSel, 
 | 
|  |    771 |                                                  TImImap4GetPartialMailInfo aGetPartialMailInfo)
 | 
|  |    772 | 	{
 | 
|  |    773 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::PopulateL() - START - iCurrentOp: %d, iRequestedOp: %d", iCurrentOp, iRequestedOp ));
 | 
|  |    774 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EPopulateCompoundIsNotNull));
 | 
|  |    775 | 
 | 
|  |    776 | 	// Instead of calling CompleteIfBackgroundOpInProgress(), just check whether a flush is occurring 
 | 
|  |    777 | 	// on the primary session (always index 0).
 | 
|  |    778 | 	// If a background op is in prgoress, then the copy will be performed on a secondary session.
 | 
|  |    779 | 	ResetProgress();
 | 
|  |    780 | 
 | 
|  |    781 | 	// If a flush is occurring on the primary session (always index 0) then we are busy
 | 
|  |    782 | 	if (iCurrentOp == ECancelRecoverPrimary || iMigrateState != ENotMigrating)
 | 
|  |    783 | 		{
 | 
|  |    784 | 		// Do not call Complete() - this would result in the Protocol
 | 
|  |    785 | 		// Controller disconnecting all sessions.
 | 
|  |    786 | 		TRequestStatus* pStatus = &aStatus;
 | 
|  |    787 | 		User::RequestComplete(pStatus, KErrServerBusy);
 | 
|  |    788 | 	    __LOG_TEXT(KDefaultLog, "CImapProtocolController::PopulateL() - END - KErrServerBusy...");
 | 
|  |    789 | 		return;
 | 
|  |    790 | 		}
 | 
|  |    791 | 
 | 
|  |    792 | 	// must be set before calling SelectSessionL()
 | 
|  |    793 | 	iRequestedOp = EPopulate;		
 | 
|  |    794 | 
 | 
|  |    795 | 	// request the session to use.
 | 
|  |    796 | 	TBool startNow = SelectSessionL(iForegroundSession);
 | 
|  |    797 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::PopulateL() - iCurrentOp: %d, iRequestedOp: %d, startNow: %d", iCurrentOp, iRequestedOp, startNow ));
 | 
|  |    798 | 	
 | 
|  |    799 | 	if (iBackgroundSyncOp && iImapSettings->UseSyncDownloadRules())
 | 
|  |    800 | 		{
 | 
|  |    801 | 		// we need a non-const copy of the message selection to operate on.
 | 
|  |    802 | 		CMsvEntrySelection* selection = aSourceSel.CopyLC();
 | 
|  |    803 | 		
 | 
|  |    804 | 		// show the list to the background sync controller
 | 
|  |    805 | 		iBackgroundSyncOp->RemoveFromSelectionL(*selection);
 | 
|  |    806 | 		// Create the copy to local operation object using the (possibly) updated selection
 | 
|  |    807 | 		iImapCompound = CImapCompoundCopyToLocal::NewL(*iImapSyncManager, 
 | 
|  |    808 | 			                			               iEntry, 
 | 
|  |    809 | 		    	                        			   *iImapSettings,
 | 
|  |    810 | 		        	                    			   *iImapMailStore, 
 | 
|  |    811 | 		            	                               EFalse,
 | 
|  |    812 | 		                	                           *selection,
 | 
|  |    813 | 		                    	                       KMsvNullIndexEntryId,
 | 
|  |    814 | 		                        	                   aGetPartialMailInfo);
 | 
|  |    815 | 		CleanupStack::PopAndDestroy(selection);
 | 
|  |    816 | 		}
 | 
|  |    817 | 	else
 | 
|  |    818 | 		{
 | 
|  |    819 | 		// Create the compound operation object
 | 
|  |    820 | 		iImapCompound = CImapCompoundCopyToLocal::NewL(*iImapSyncManager, 
 | 
|  |    821 | 	    	                			               iEntry, 
 | 
|  |    822 | 	        	                        			   *iImapSettings,
 | 
|  |    823 | 	            	                    			   *iImapMailStore, 
 | 
|  |    824 | 	                	                               EFalse,
 | 
|  |    825 | 	                    	                           aSourceSel,
 | 
|  |    826 | 	                        	                       KMsvNullIndexEntryId,
 | 
|  |    827 | 	                            	                   aGetPartialMailInfo);
 | 
|  |    828 | 		}
 | 
|  |    829 | 
 | 
|  |    830 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::PopulateL() - done creation of CompoundCopyToLocal...");
 | 
|  |    831 | 	if (startNow)
 | 
|  |    832 | 		{
 | 
|  |    833 | 		// A session is ready - start the command
 | 
|  |    834 | 		// otherwise a request to connect a secondary session has been issued
 | 
|  |    835 | 		if (iForegroundSession==0)
 | 
|  |    836 | 			{
 | 
|  |    837 | 			// Primary session
 | 
|  |    838 | 	        __LOG_TEXT(KDefaultLog, "CImapProtocolController::PopulateL() - starting primary op...");
 | 
|  |    839 | 			StartPrimaryOperation();
 | 
|  |    840 | 			}
 | 
|  |    841 | 		else
 | 
|  |    842 | 			{
 | 
|  |    843 | 			// Secondary session
 | 
|  |    844 | 	        __LOG_TEXT(KDefaultLog, "CImapProtocolController::PopulateL() - starting compound op...");
 | 
|  |    845 | 			iCurrentOp = iRequestedOp;
 | 
|  |    846 | 			iImapCompound->StartOperation(iStatus, *iImapSessionArray[iForegroundSession]);
 | 
|  |    847 | 			}
 | 
|  |    848 | 		}	
 | 
|  |    849 | 	
 | 
|  |    850 | 	Queue(aStatus);
 | 
|  |    851 | 	SetActive();
 | 
|  |    852 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::PopulateL() - END - iCurrentOp: %d, iRequestedOp: %d, startNow: %d", iCurrentOp, iRequestedOp, startNow ));
 | 
|  |    853 | 	}
 | 
|  |    854 | 
 | 
|  |    855 | /**
 | 
|  |    856 | MoveToCopyL() shall enable a selection of messages to be moved as a single operation, 
 | 
|  |    857 | without return to idle state between handling each message. If a message has not been 
 | 
|  |    858 | previously fetched (ie is not complete on the local mirror of the IMAP folder) the 
 | 
|  |    859 | message is fetched to the local mirror and a copy is then made in the local service 
 | 
|  |    860 | folder. The message is then deleted from the IMAP folder on the remote server and the 
 | 
|  |    861 | local mirror.
 | 
|  |    862 | 
 | 
|  |    863 | Sequence For MoveToLocal
 | 
|  |    864 | 	StopIdle
 | 
|  |    865 | 	SelectSourceMailbox 
 | 
|  |    866 | 	FetchMessage
 | 
|  |    867 | 	InboxDuplicateCopy
 | 
|  |    868 | 	DeleteMessage
 | 
|  |    869 | 
 | 
|  |    870 | @param aStatus
 | 
|  |    871 | @param aSourceSel
 | 
|  |    872 | @param aDestination
 | 
|  |    873 | */	
 | 
|  |    874 | EXPORT_C void CImapProtocolController::MoveToLocalL(TRequestStatus& aStatus, 
 | 
|  |    875 | 													const CMsvEntrySelection& aSourceSel, 
 | 
|  |    876 | 													const TMsvId aDestination)
 | 
|  |    877 | 	{
 | 
|  |    878 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::MoveToLocalL()");
 | 
|  |    879 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EMoveToLocalCompoundIsNotNull));
 | 
|  |    880 | 
 | 
|  |    881 | 	ResetProgress();
 | 
|  |    882 | 
 | 
|  |    883 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |    884 | 		{
 | 
|  |    885 | 		// We can't do a 'movetolocal' with the destination being the same as the
 | 
|  |    886 | 		// source, as then the mirror will be out of sync. We must be moving to somewhere
 | 
|  |    887 | 		// outside this service. Check this.
 | 
|  |    888 | 		if (!IdIsLocalL(aDestination))
 | 
|  |    889 | 			{
 | 
|  |    890 | 			// Complete the user request
 | 
|  |    891 | 			// Do not call Complete() - this would result in the Protocol
 | 
|  |    892 | 			// Controller disconnecting all sessions.
 | 
|  |    893 | 			TRequestStatus* status = &aStatus;
 | 
|  |    894 | 			User::RequestComplete(status, KErrNotSupported);
 | 
|  |    895 | 			}
 | 
|  |    896 | 		else
 | 
|  |    897 | 			{
 | 
|  |    898 | 			iImapCompound = CImapCompoundCopyToLocal::NewL(*iImapSyncManager, 
 | 
|  |    899 | 														   iEntry, 
 | 
|  |    900 | 														   *iImapSettings,
 | 
|  |    901 | 														   *iImapMailStore,
 | 
|  |    902 | 														   ETrue,
 | 
|  |    903 | 		                                               	   aSourceSel,
 | 
|  |    904 | 		                                               	   aDestination);
 | 
|  |    905 | 			
 | 
|  |    906 | 			iRequestedOp = EMoveToLocal;
 | 
|  |    907 | 			StartPrimaryOperation();
 | 
|  |    908 | 			Queue(aStatus);
 | 
|  |    909 | 			SetActive();
 | 
|  |    910 | 			}
 | 
|  |    911 | 		}
 | 
|  |    912 | 	}
 | 
|  |    913 | 
 | 
|  |    914 | /**
 | 
|  |    915 | Copy within service is the operation of moving a message or selection of messages from 
 | 
|  |    916 | one mailbox  to another on the remote IMAP server. This is done by issuing a COPY IMAP 
 | 
|  |    917 | command to the remote server, followed by a sync operation on the destination folder.
 | 
|  |    918 | 
 | 
|  |    919 | Sequence For CopyWithinService
 | 
|  |    920 | 	StopIdle
 | 
|  |    921 | 	SelectSourceMailboxRO
 | 
|  |    922 | 	CopyMessage
 | 
|  |    923 | 	SelectDestinationMailboxRO
 | 
|  |    924 | 	NewSyncFolder
 | 
|  |    925 | 
 | 
|  |    926 | @param aStatus
 | 
|  |    927 | @param aSourceSel
 | 
|  |    928 | @param aDestination
 | 
|  |    929 | */
 | 
|  |    930 | EXPORT_C void CImapProtocolController::CopyWithinServiceL( TRequestStatus& aStatus, 
 | 
|  |    931 | 							 					  		   const CMsvEntrySelection& aSourceSel, 
 | 
|  |    932 | 							 					  		   const TMsvId aDestination )
 | 
|  |    933 | 	{
 | 
|  |    934 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CopyWithinServiceL()");
 | 
|  |    935 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyWithinServiceCompoundIsNotNull));
 | 
|  |    936 | 	
 | 
|  |    937 | 	ResetProgress();
 | 
|  |    938 | 
 | 
|  |    939 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |    940 | 		{	
 | 
|  |    941 | 		iImapCompound = CImapCompoundCopyWithinService::NewL( *iImapSyncManager, 
 | 
|  |    942 | 															  iEntry, 
 | 
|  |    943 | 															  *iImapSettings,
 | 
|  |    944 | 															  EFalse,
 | 
|  |    945 | 															  aSourceSel,
 | 
|  |    946 | 															  aDestination);
 | 
|  |    947 | 		
 | 
|  |    948 | 		iRequestedOp = ECopyWithinService;
 | 
|  |    949 | 		StartPrimaryOperation();
 | 
|  |    950 | 		Queue(aStatus);
 | 
|  |    951 | 		SetActive();
 | 
|  |    952 | 		}
 | 
|  |    953 | 	}
 | 
|  |    954 | 
 | 
|  |    955 | /**
 | 
|  |    956 | Move within service is the same as Copy Within Service, however the message is deleted 
 | 
|  |    957 | from the original location following the copy operation.
 | 
|  |    958 | 
 | 
|  |    959 | Sequence For MoveWithinService
 | 
|  |    960 | 	StopIdle
 | 
|  |    961 | 	SelectSourceMailboxRW
 | 
|  |    962 | 	CopyMessage
 | 
|  |    963 | 	DeleteMessage
 | 
|  |    964 | 	SelectDestinationMailboxRO
 | 
|  |    965 | 	NewSyncFolder
 | 
|  |    966 | 	
 | 
|  |    967 | @param aStatus
 | 
|  |    968 | @param aSourceSel
 | 
|  |    969 | @param aDestination
 | 
|  |    970 | */
 | 
|  |    971 | EXPORT_C void CImapProtocolController::MoveWithinServiceL( TRequestStatus& aStatus, 
 | 
|  |    972 | 							 					  		   const CMsvEntrySelection& aSourceSel, 
 | 
|  |    973 | 							 					  		   const TMsvId aDestination )
 | 
|  |    974 | 	{
 | 
|  |    975 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::MoveWithinServiceL()");
 | 
|  |    976 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EMoveWithinServiceCompoundIsNotNull));
 | 
|  |    977 | 	
 | 
|  |    978 | 	ResetProgress();
 | 
|  |    979 | 	
 | 
|  |    980 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |    981 | 		{	
 | 
|  |    982 | 		iImapCompound = CImapCompoundCopyWithinService::NewL( *iImapSyncManager, 
 | 
|  |    983 | 															  iEntry, 
 | 
|  |    984 | 															  *iImapSettings,
 | 
|  |    985 | 															  ETrue,
 | 
|  |    986 | 															  aSourceSel,
 | 
|  |    987 | 															  aDestination );
 | 
|  |    988 | 
 | 
|  |    989 | 		iRequestedOp = EMoveWithinService;
 | 
|  |    990 | 		StartPrimaryOperation();
 | 
|  |    991 | 		Queue(aStatus);
 | 
|  |    992 | 		SetActive();
 | 
|  |    993 | 		}
 | 
|  |    994 | 	}
 | 
|  |    995 | 
 | 
|  |    996 | /**
 | 
|  |    997 | Copy from local is the action of copying an email from a local service folder (for 
 | 
|  |    998 | example the local inbox) to a folder on the remote IMAP service. This is done using 
 | 
|  |    999 | the IMAP APPEND command.
 | 
|  |   1000 | 
 | 
|  |   1001 | Sequence For CopyFromLocal
 | 
|  |   1002 | 	AppendMessage
 | 
|  |   1003 | 	SelectDestinationMailboxRO
 | 
|  |   1004 | 	NewSyncFolder
 | 
|  |   1005 | 
 | 
|  |   1006 | @param aStatus
 | 
|  |   1007 | @param aSourceSel
 | 
|  |   1008 | @param aDestination
 | 
|  |   1009 | */	
 | 
|  |   1010 | EXPORT_C void CImapProtocolController::CopyFromLocalL( TRequestStatus& aStatus, 
 | 
|  |   1011 | 						 					  		   const CMsvEntrySelection& aSourceSel, 
 | 
|  |   1012 | 						 					  		   const TMsvId aDestination )
 | 
|  |   1013 | 	{
 | 
|  |   1014 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CopyFromLocalL()");
 | 
|  |   1015 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyFromLocalCompoundIsNotNull));
 | 
|  |   1016 | 	
 | 
|  |   1017 | 	ResetProgress();
 | 
|  |   1018 | 	
 | 
|  |   1019 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1020 | 		{	
 | 
|  |   1021 | 		iImapCompound = CImapCompoundCopyFromLocal::NewL( *iImapSyncManager, 
 | 
|  |   1022 | 														  iEntry, 
 | 
|  |   1023 | 														  *iImapSettings,
 | 
|  |   1024 | 														  EFalse,
 | 
|  |   1025 | 														  aSourceSel,
 | 
|  |   1026 | 														  aDestination );
 | 
|  |   1027 | 		
 | 
|  |   1028 | 		iRequestedOp = ECopyFromLocal;
 | 
|  |   1029 | 		StartPrimaryOperation();
 | 
|  |   1030 | 		Queue(aStatus);
 | 
|  |   1031 | 		SetActive();
 | 
|  |   1032 | 		}
 | 
|  |   1033 | 	}
 | 
|  |   1034 | 
 | 
|  |   1035 | /**
 | 
|  |   1036 | Move from local is the action of moving an email from a local service folder (for 
 | 
|  |   1037 | example the local inbox) to a folder on the remote IMAP service. It is performed 
 | 
|  |   1038 | by following the same steps as for a Copy From Local operation, using the IMAP APPEND 
 | 
|  |   1039 | command, however the local copy of the message is deleted after the APPEND has 
 | 
|  |   1040 | successfully completed.
 | 
|  |   1041 | 
 | 
|  |   1042 | Sequence For MoveFromLocal
 | 
|  |   1043 | 	StopIdle
 | 
|  |   1044 | 	AppendMessage
 | 
|  |   1045 | 	DeleteLocalMessage
 | 
|  |   1046 | 	SelectDestinationMailboxRO
 | 
|  |   1047 | 	NewSyncFolder
 | 
|  |   1048 | 
 | 
|  |   1049 | @param aStatus
 | 
|  |   1050 | @param aSourceSel
 | 
|  |   1051 | @param aDestination
 | 
|  |   1052 | */
 | 
|  |   1053 | EXPORT_C void CImapProtocolController::MoveFromLocalL( TRequestStatus& aStatus, 
 | 
|  |   1054 | 						 					  		   const CMsvEntrySelection& aSourceSel, 
 | 
|  |   1055 | 						 					  		   const TMsvId aDestination )
 | 
|  |   1056 | 	{
 | 
|  |   1057 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::MoveFromLocalL()");
 | 
|  |   1058 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECopyFromLocalCompoundIsNotNull));
 | 
|  |   1059 | 	
 | 
|  |   1060 | 	ResetProgress();
 | 
|  |   1061 | 	
 | 
|  |   1062 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1063 | 		{
 | 
|  |   1064 | 		iImapCompound = CImapCompoundCopyFromLocal::NewL( *iImapSyncManager, 
 | 
|  |   1065 | 														  iEntry, 
 | 
|  |   1066 | 														  *iImapSettings,
 | 
|  |   1067 | 														  ETrue,
 | 
|  |   1068 | 														  aSourceSel,
 | 
|  |   1069 | 														  aDestination );
 | 
|  |   1070 | 	
 | 
|  |   1071 | 		iRequestedOp = EMoveFromLocal;
 | 
|  |   1072 | 		StartPrimaryOperation();
 | 
|  |   1073 | 		Queue(aStatus);
 | 
|  |   1074 | 		SetActive();
 | 
|  |   1075 | 		}
 | 
|  |   1076 | 	}
 | 
|  |   1077 | 
 | 
|  |   1078 | /**
 | 
|  |   1079 | Deletes the specified messages from the remote server.
 | 
|  |   1080 | 
 | 
|  |   1081 | Sequence For Delete
 | 
|  |   1082 | 	StopIdle
 | 
|  |   1083 | 	SelectSourceMailboxRW
 | 
|  |   1084 | 	Store /delete flags for each message
 | 
|  |   1085 | 	Expunge remote messages
 | 
|  |   1086 | 	Delete local messages
 | 
|  |   1087 | 
 | 
|  |   1088 | @param aStatus
 | 
|  |   1089 | @param aSourceSel
 | 
|  |   1090 | */
 | 
|  |   1091 | EXPORT_C void CImapProtocolController::DeleteL(TRequestStatus& aStatus, 
 | 
|  |   1092 | 									   		   const CMsvEntrySelection& aSourceSel)
 | 
|  |   1093 | 	{
 | 
|  |   1094 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DeleteL()");
 | 
|  |   1095 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EDeleteCompoundIsNotNull));
 | 
|  |   1096 | 	
 | 
|  |   1097 | 	ResetProgress();
 | 
|  |   1098 | 	
 | 
|  |   1099 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1100 | 		{
 | 
|  |   1101 | 		// Create the compound object for message delete
 | 
|  |   1102 | 		iImapCompound = CImapCompoundDelete::NewL(*iImapSyncManager,
 | 
|  |   1103 | 												  iEntry,
 | 
|  |   1104 | 												  *iImapSettings,
 | 
|  |   1105 | 												  aSourceSel);
 | 
|  |   1106 | 
 | 
|  |   1107 | 		iRequestedOp = EDelete;
 | 
|  |   1108 | 		StartPrimaryOperation();
 | 
|  |   1109 | 		Queue(aStatus);
 | 
|  |   1110 | 		SetActive();
 | 
|  |   1111 | 		}
 | 
|  |   1112 | 	}
 | 
|  |   1113 | 
 | 
|  |   1114 | /**
 | 
|  |   1115 | Deletes the specified folder(s) on the remote IMAP Server.
 | 
|  |   1116 | 
 | 
|  |   1117 | Sequence For DeleteFolder
 | 
|  |   1118 | 	StopIdle
 | 
|  |   1119 | 	SelectSourceMailboxRW
 | 
|  |   1120 | 	DeleteAllMessages
 | 
|  |   1121 | 	CloseFolder
 | 
|  |   1122 | 	DeleteLocalFolder
 | 
|  |   1123 | 
 | 
|  |   1124 | @param aStatus
 | 
|  |   1125 | @param aSelection
 | 
|  |   1126 | */
 | 
|  |   1127 | EXPORT_C void CImapProtocolController::DeleteFolderL( TRequestStatus& aStatus, 
 | 
|  |   1128 | 											 		  const CMsvEntrySelection& aSelection )
 | 
|  |   1129 | 	{
 | 
|  |   1130 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DeleteFolderL()");
 | 
|  |   1131 | 	__ASSERT_DEBUG(iImapCompound == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EDeleteFolderCompoundIsNotNull));
 | 
|  |   1132 | 
 | 
|  |   1133 | 	ResetProgress();
 | 
|  |   1134 | 	
 | 
|  |   1135 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1136 | 		{
 | 
|  |   1137 | 		iImapCompound = CImapCompoundDeleteFolder::NewL( *iImapSyncManager,
 | 
|  |   1138 | 													     iEntry,
 | 
|  |   1139 | 													     *iImapSettings,
 | 
|  |   1140 | 													     aSelection );
 | 
|  |   1141 | 													     
 | 
|  |   1142 | 		iRequestedOp = EDelete;
 | 
|  |   1143 | 		StartPrimaryOperation();
 | 
|  |   1144 | 		Queue(aStatus);
 | 
|  |   1145 | 		SetActive();
 | 
|  |   1146 | 		}	
 | 
|  |   1147 | 	}
 | 
|  |   1148 | 
 | 
|  |   1149 | /**
 | 
|  |   1150 | NewOnlySyncL() is used to synchronise recent messages in the specified folder, 
 | 
|  |   1151 | i.e. any messages that have arrived in the remote IMAP mailbox since the last 
 | 
|  |   1152 | synchronisation. This is done by requesting (FETCHing) the header details for 
 | 
|  |   1153 | messages with UID's that are greater than the highest UID of the messages present 
 | 
|  |   1154 | in the local mirror of the folder. The message's header summary information, 
 | 
|  |   1155 | flags etc are stored as new entries in the Message Server entry array under the 
 | 
|  |   1156 | folder entry, and the header information is streamed to the Mailstore using the 
 | 
|  |   1157 | Mailstore API. 
 | 
|  |   1158 | 
 | 
|  |   1159 | Sequence For NewSyncFolder
 | 
|  |   1160 | 	StopIdle
 | 
|  |   1161 | 	SelectSourceMailboxRW
 | 
|  |   1162 | 	NewSyncFolder
 | 
|  |   1163 | 
 | 
|  |   1164 | @param aStatus
 | 
|  |   1165 | */
 | 
|  |   1166 | EXPORT_C void CImapProtocolController::NewOnlySyncFolderL( TRequestStatus& aStatus )
 | 
|  |   1167 | 	{
 | 
|  |   1168 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::NewOnlySyncFolderL()");
 | 
|  |   1169 | 	__ASSERT_DEBUG(iImapCompound == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ENewOnlySyncFolderCompoundIsNotNull));
 | 
|  |   1170 | 
 | 
|  |   1171 | 	ResetProgress();
 | 
|  |   1172 | 	
 | 
|  |   1173 | 	if (iMigrateState!=ENotMigrating)
 | 
|  |   1174 | 		{
 | 
|  |   1175 | 		// Complete the user request if migrating.
 | 
|  |   1176 | 		// Do not call Complete() - this would result in the Protocol
 | 
|  |   1177 | 		// Controller disconnecting all sessions.
 | 
|  |   1178 | 		TRequestStatus* status = &aStatus;
 | 
|  |   1179 | 		User::RequestComplete(status, KErrServerBusy);
 | 
|  |   1180 | 		return;
 | 
|  |   1181 | 		}
 | 
|  |   1182 | 	
 | 
|  |   1183 | 	// If we support idle, and the server we are talking to supports idle,
 | 
|  |   1184 | 	// then we don't need to do the new only sync as IMAP idle will take
 | 
|  |   1185 | 	// care of it for us.
 | 
|  |   1186 | 	// Just complete the user request with KErrNone.
 | 
|  |   1187 | 	if (iImapSettings->ImapIdle() && iImapSessionArray[0]->ImapIdleSupported())
 | 
|  |   1188 | 		{
 | 
|  |   1189 | 		__LOG_TEXT(KDefaultLog, "CImapProtocolController::NewOnlySyncFolderL() - Immediate complete as idle is in use");
 | 
|  |   1190 | 		Queue(aStatus);
 | 
|  |   1191 | 		Complete(KErrNone);
 | 
|  |   1192 | 		return;
 | 
|  |   1193 | 		}
 | 
|  |   1194 | 	
 | 
|  |   1195 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1196 | 		{	
 | 
|  |   1197 | 		CImapFolder* folder = iImapSyncManager->Inbox();
 | 
|  |   1198 | 		TMsvId inboxId = folder->MailboxId();
 | 
|  |   1199 | 		
 | 
|  |   1200 | 		iImapCompound = CImapCompoundSyncFolder::NewL( *iImapSyncManager,
 | 
|  |   1201 | 													   iEntry,
 | 
|  |   1202 | 													   *iImapSettings, 
 | 
|  |   1203 | 													   *iImapMailStore, 
 | 
|  |   1204 | 													   ETrue,
 | 
|  |   1205 | 													   inboxId);
 | 
|  |   1206 | 
 | 
|  |   1207 | 		iRequestedOp = ESync;
 | 
|  |   1208 | 		StartPrimaryOperation();
 | 
|  |   1209 | 		Queue(aStatus);
 | 
|  |   1210 | 		SetActive();
 | 
|  |   1211 | 		}
 | 
|  |   1212 | 	}
 | 
|  |   1213 | 
 | 
|  |   1214 | /**
 | 
|  |   1215 | The full synchronisation of a folder involves the synchronisation of messages newly 
 | 
|  |   1216 | received at the IMAP server, as described for NewOnlySyncL, above, and the 
 | 
|  |   1217 | synchronisation of "old messages", ie messages that have previously been synchronised 
 | 
|  |   1218 | to the local mirror of the folder.
 | 
|  |   1219 | When synchronising old messages, messages that have been marked for delete locally 
 | 
|  |   1220 | are marked such on the remote folder (the actual delete occurs either at the end of 
 | 
|  |   1221 | the synchronisation process, or is deferred until the connection is cancelled), 
 | 
|  |   1222 | messages that have been removed from the remote server (by another client) are 
 | 
|  |   1223 | deleted locally and any outstanding offline operations are performed, for example 
 | 
|  |   1224 | move operations may be outstanding, etc.
 | 
|  |   1225 | 
 | 
|  |   1226 | Sequence For FullSyncFolder
 | 
|  |   1227 | 	StopIdle
 | 
|  |   1228 | 	SelectSourceMailboxRW
 | 
|  |   1229 | 	SyncFolder
 | 
|  |   1230 | 
 | 
|  |   1231 | @param aStatus
 | 
|  |   1232 | @param aFolder
 | 
|  |   1233 | */
 | 
|  |   1234 | EXPORT_C void CImapProtocolController::FullSyncFolderL( TRequestStatus& aStatus, 
 | 
|  |   1235 | 											   			const TMsvId aFolder )
 | 
|  |   1236 | 	{
 | 
|  |   1237 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::FullSyncFolderL()");
 | 
|  |   1238 | 	__ASSERT_DEBUG(iImapCompound == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EFullSyncFolderCompoundIsNotNull));
 | 
|  |   1239 | 	
 | 
|  |   1240 | 	ResetProgress();
 | 
|  |   1241 | 
 | 
|  |   1242 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1243 | 		{
 | 
|  |   1244 | 		iImapCompound = CImapCompoundSyncFolder::NewL( *iImapSyncManager,
 | 
|  |   1245 | 													   iEntry,
 | 
|  |   1246 | 													   *iImapSettings,
 | 
|  |   1247 | 													   *iImapMailStore,
 | 
|  |   1248 | 													   EFalse,
 | 
|  |   1249 | 													   aFolder );
 | 
|  |   1250 | 
 | 
|  |   1251 | 		iRequestedOp = ESync;
 | 
|  |   1252 | 		StartPrimaryOperation();
 | 
|  |   1253 | 		Queue(aStatus);
 | 
|  |   1254 | 		SetActive();
 | 
|  |   1255 | 		}
 | 
|  |   1256 | 	}
 | 
|  |   1257 | 
 | 
|  |   1258 | /**
 | 
|  |   1259 | SELECT is made available to the client application directly via an IMAP MTM command 
 | 
|  |   1260 | which is handled by this function. It allows the client to specifically SELECT a 
 | 
|  |   1261 | mailbox and then, using the Synchronise MTM command, to specifically request the 
 | 
|  |   1262 | selected mailbox is synchronised.
 | 
|  |   1263 | 
 | 
|  |   1264 | Sequence For Select
 | 
|  |   1265 | 	StopIdle
 | 
|  |   1266 | 	SelectSourceMailboxRW
 | 
|  |   1267 | 
 | 
|  |   1268 | @param aStatus
 | 
|  |   1269 | @param aFolder
 | 
|  |   1270 | */	
 | 
|  |   1271 | EXPORT_C void CImapProtocolController::SelectL(TRequestStatus& aStatus, const TMsvId aFolder)
 | 
|  |   1272 | 	{
 | 
|  |   1273 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::SelectL()");
 | 
|  |   1274 | 	__ASSERT_DEBUG(iImapCompound == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ESelectCompoundIsNotNull));
 | 
|  |   1275 | 	
 | 
|  |   1276 | 	ResetProgress();
 | 
|  |   1277 | 	
 | 
|  |   1278 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1279 | 		{
 | 
|  |   1280 | 		iImapCompound = CImapCompoundSelect::NewL( *iImapSyncManager, 
 | 
|  |   1281 | 												   iEntry, 
 | 
|  |   1282 | 												   *iImapSettings,
 | 
|  |   1283 | 												   aFolder );
 | 
|  |   1284 | 
 | 
|  |   1285 | 		iRequestedOp = ESelect;
 | 
|  |   1286 | 		StartPrimaryOperation();
 | 
|  |   1287 | 		Queue(aStatus);
 | 
|  |   1288 | 		SetActive();
 | 
|  |   1289 | 		}
 | 
|  |   1290 | 	}
 | 
|  |   1291 | 
 | 
|  |   1292 | /**
 | 
|  |   1293 | Performs a full sync on the currently selected mailbox.
 | 
|  |   1294 | 
 | 
|  |   1295 | Sequence For FullSyncSelectedFolder
 | 
|  |   1296 | 	StopIdle
 | 
|  |   1297 | 	SyncFolder
 | 
|  |   1298 | 
 | 
|  |   1299 | @param aStatus
 | 
|  |   1300 | */	
 | 
|  |   1301 | EXPORT_C void CImapProtocolController::FullSyncSelectedFolderL( TRequestStatus& aStatus )
 | 
|  |   1302 | 	{
 | 
|  |   1303 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::FullSyncSelectedFolderL()");
 | 
|  |   1304 | 	__ASSERT_DEBUG( iImapCompound == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EFullSyncSelectedFolderCompoundIsNotNull));
 | 
|  |   1305 | 	
 | 
|  |   1306 | 	ResetProgress();
 | 
|  |   1307 | 	
 | 
|  |   1308 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1309 | 		{
 | 
|  |   1310 | 		iImapCompound = CImapCompoundSyncFolder::NewL( *iImapSyncManager,
 | 
|  |   1311 | 													   iEntry,
 | 
|  |   1312 | 													   *iImapSettings,
 | 
|  |   1313 | 													   *iImapMailStore, 
 | 
|  |   1314 | 													   EFalse );
 | 
|  |   1315 | 		
 | 
|  |   1316 | 		iRequestedOp = ESync;
 | 
|  |   1317 | 		StartPrimaryOperation();
 | 
|  |   1318 | 		Queue(aStatus);
 | 
|  |   1319 | 		SetActive();
 | 
|  |   1320 | 		}
 | 
|  |   1321 | 	}
 | 
|  |   1322 | 	
 | 
|  |   1323 | /**
 | 
|  |   1324 | Creates a new folder on the remote IMAP service with the given name.
 | 
|  |   1325 | 
 | 
|  |   1326 | Sequence For Create
 | 
|  |   1327 | 	StopIdle
 | 
|  |   1328 | 	Create
 | 
|  |   1329 | 
 | 
|  |   1330 | @param aStatus
 | 
|  |   1331 | @param aParent
 | 
|  |   1332 | @param aLeafName
 | 
|  |   1333 | @param aFolder
 | 
|  |   1334 | */
 | 
|  |   1335 | EXPORT_C void CImapProtocolController::CreateL( TRequestStatus& aStatus, 
 | 
|  |   1336 | 				  					   			const TMsvId aParent, 
 | 
|  |   1337 | 				  					   			const TDesC& aLeafName, 
 | 
|  |   1338 | 				  					   			const TBool aFolder )
 | 
|  |   1339 | 	{
 | 
|  |   1340 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CreateL()");
 | 
|  |   1341 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECreateCompoundIsNotNull));
 | 
|  |   1342 | 	
 | 
|  |   1343 | 	ResetProgress();
 | 
|  |   1344 | 	
 | 
|  |   1345 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1346 | 		{
 | 
|  |   1347 | 		iImapCompound = CImapCompoundCreate::NewL( *iImapSyncManager,
 | 
|  |   1348 | 												   iEntry,
 | 
|  |   1349 | 												   *iImapSettings,
 | 
|  |   1350 | 												   aParent, 
 | 
|  |   1351 | 												   aLeafName, 
 | 
|  |   1352 | 												   aFolder );
 | 
|  |   1353 | 
 | 
|  |   1354 | 		iRequestedOp = ECreate;
 | 
|  |   1355 | 		StartPrimaryOperation();
 | 
|  |   1356 | 		Queue(aStatus);
 | 
|  |   1357 | 		SetActive();
 | 
|  |   1358 | 		}
 | 
|  |   1359 | 	}
 | 
|  |   1360 | 
 | 
|  |   1361 | /**
 | 
|  |   1362 | Renames the specified folder. Note that although this does cause a write to the 
 | 
|  |   1363 | remote folder, it does not change the contents of the folder and hence does not 
 | 
|  |   1364 | force a re-synchronisation of the folder.
 | 
|  |   1365 | 
 | 
|  |   1366 | Sequence For Rename
 | 
|  |   1367 | 	StopIdle
 | 
|  |   1368 | 	RenameRemote
 | 
|  |   1369 | 	RenameLocal
 | 
|  |   1370 | 
 | 
|  |   1371 | @param aStatus
 | 
|  |   1372 | @param aTarget
 | 
|  |   1373 | @param aNewName
 | 
|  |   1374 | */	
 | 
|  |   1375 | EXPORT_C void CImapProtocolController::RenameL( TRequestStatus& aStatus, 
 | 
|  |   1376 | 				  					   			const TMsvId aTarget, 
 | 
|  |   1377 | 				  					   			const TDesC& aNewName )
 | 
|  |   1378 | 	{
 | 
|  |   1379 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::RenameL()");
 | 
|  |   1380 | 	__ASSERT_DEBUG(iImapCompound == NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ERenameCompoundIsNotNull));
 | 
|  |   1381 | 	
 | 
|  |   1382 | 	ResetProgress();
 | 
|  |   1383 | 	
 | 
|  |   1384 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   1385 | 		{
 | 
|  |   1386 | 		iImapCompound = CImapCompoundRename::NewL( *iImapSyncManager, 
 | 
|  |   1387 | 												   iEntry, 
 | 
|  |   1388 | 												   *iImapSettings,
 | 
|  |   1389 | 												   aTarget,
 | 
|  |   1390 | 												   aNewName );
 | 
|  |   1391 | 												   
 | 
|  |   1392 | 		iRequestedOp = ERename;
 | 
|  |   1393 | 		StartPrimaryOperation();
 | 
|  |   1394 | 		Queue(aStatus);
 | 
|  |   1395 | 		SetActive();
 | 
|  |   1396 | 		}
 | 
|  |   1397 | 	}
 | 
|  |   1398 | 
 | 
|  |   1399 | 
 | 
|  |   1400 | EXPORT_C void CImapProtocolController::DoRunL()
 | 
|  |   1401 | 	{
 | 
|  |   1402 | 	// Handle all migration operations in a separate state machnine.
 | 
|  |   1403 | 	if (iMigrateState != ENotMigrating)
 | 
|  |   1404 | 		{
 | 
|  |   1405 | 		DoMigrateRunL();
 | 
|  |   1406 | 		return;
 | 
|  |   1407 | 		}
 | 
|  |   1408 | 
 | 
|  |   1409 | 	// ProcessError completes and returns ETrue if an error occured
 | 
|  |   1410 | 	if (ProcessError(iStatus.Int()))
 | 
|  |   1411 | 		{
 | 
|  |   1412 | 		return;
 | 
|  |   1413 | 		}
 | 
|  |   1414 | 
 | 
|  |   1415 | 	switch (iCurrentOp)
 | 
|  |   1416 | 		{
 | 
|  |   1417 | 	case EConnect:
 | 
|  |   1418 | 		{
 | 
|  |   1419 | 		// Collect the final connect progress information		
 | 
|  |   1420 | 		iImapSessionManager->Progress(iProgress.iGenericProgress);
 | 
|  |   1421 | 
 | 
|  |   1422 | 		// Set last socket activity timeout to iMtmData1. This is used by Imcm.
 | 
|  |   1423 | 		User::LeaveIfError( iEntry.SetEntry( iServiceId ) );
 | 
|  |   1424 | 		TMsvEntry entry=iEntry.Entry();
 | 
|  |   1425 | 		entry.SetMtmData1(iImapSessionManager->LastSocketActivityTimeout());
 | 
|  |   1426 | 		User::LeaveIfError( iEntry.ChangeEntry( entry ) );
 | 
|  |   1427 | 
 | 
|  |   1428 | 		TRAP_IGNORE(MarkOnOrOfflineL(ETrue));
 | 
|  |   1429 | 				
 | 
|  |   1430 | 		// Create an IMAP IDLE controller
 | 
|  |   1431 | 		delete iImapIdleController;
 | 
|  |   1432 | 		iImapIdleController=NULL;
 | 
|  |   1433 | 		iImapIdleController = CImapIdleController::NewL(*this, iImapSessionArray[0], *iImapSyncManager, iEntry, *iImapSettings, *iImapMailStore);
 | 
|  |   1434 | 		
 | 
|  |   1435 | 		// Register the connection with the mobility manager, 
 | 
|  |   1436 | 		// if we are a mobile service
 | 
|  |   1437 | 		if (iMobilityManager)
 | 
|  |   1438 | 			{
 | 
|  |   1439 | 			iMobilityManager->SetConnection(iImapSessionManager->GetConnectionL());
 | 
|  |   1440 | 			}
 | 
|  |   1441 | 
 | 
|  |   1442 | 		// kick off a background sync if it was requested.
 | 
|  |   1443 | 		if (iBackgroundSyncOp != NULL)
 | 
|  |   1444 | 			{
 | 
|  |   1445 | 			iBackgroundSyncOp->StartSync(*iImapSessionArray[0]);
 | 
|  |   1446 | 			iCurrentOp = EIdle;
 | 
|  |   1447 | 			}
 | 
|  |   1448 | 		else
 | 
|  |   1449 | 			{
 | 
|  |   1450 | 			StartIdle();
 | 
|  |   1451 | 			}
 | 
|  |   1452 | 
 | 
|  |   1453 | 		// complete the connect request
 | 
|  |   1454 | 		Complete(iStatus.Int());
 | 
|  |   1455 | 		break;
 | 
|  |   1456 | 		}
 | 
|  |   1457 | 
 | 
|  |   1458 | 	case EConnectSecondary:
 | 
|  |   1459 | 		{
 | 
|  |   1460 | 		// perform the user-requested operation using the
 | 
|  |   1461 | 		// newly created imap session
 | 
|  |   1462 | 		iCurrentOp = iRequestedOp;
 | 
|  |   1463 | 		if(iImapCompound->Suspended())
 | 
|  |   1464 | 			{
 | 
|  |   1465 | 			// if the operation was previously suspended for migration, resume it...
 | 
|  |   1466 | 			iImapCompound->ResumeOperationL(iStatus, *iImapSessionArray[iForegroundSession]);
 | 
|  |   1467 | 			}
 | 
|  |   1468 | 		else
 | 
|  |   1469 | 			{
 | 
|  |   1470 | 			// otherwise, just start the operation.
 | 
|  |   1471 | 			iImapCompound->StartOperation(iStatus, *iImapSessionArray[iForegroundSession]);
 | 
|  |   1472 | 			}
 | 
|  |   1473 | 		SetActive();
 | 
|  |   1474 | 		break;
 | 
|  |   1475 | 		}
 | 
|  |   1476 | 	
 | 
|  |   1477 | 	case EStopIdle:
 | 
|  |   1478 | 		{
 | 
|  |   1479 | 		// Idle has been cancelled, the primary session is available
 | 
|  |   1480 | 		// Kick off the requested operation
 | 
|  |   1481 | 		iCurrentOp = iRequestedOp;
 | 
|  |   1482 | 		iImapCompound->StartOperation(iStatus, *iImapSessionArray[0]);
 | 
|  |   1483 | 		SetActive();
 | 
|  |   1484 | 		break;
 | 
|  |   1485 | 		}
 | 
|  |   1486 | 
 | 
|  |   1487 | 	case EDisconnect:
 | 
|  |   1488 | 		{
 | 
|  |   1489 | 		TRAP_IGNORE( MarkOnOrOfflineL( EFalse ) );
 | 
|  |   1490 | 
 | 
|  |   1491 | 		iImapSessionArray.ResetAndDestroy();
 | 
|  |   1492 | 
 | 
|  |   1493 | 		// update last operation progress state
 | 
|  |   1494 | 		iImapCompound->Progress(iProgress);
 | 
|  |   1495 | 
 | 
|  |   1496 | 		delete iImapCompound;
 | 
|  |   1497 | 		iImapCompound = NULL;
 | 
|  |   1498 | 		iServiceId=0;
 | 
|  |   1499 | 		
 | 
|  |   1500 | 		Complete(iStatus.Int());
 | 
|  |   1501 | 		break;
 | 
|  |   1502 | 		}
 | 
|  |   1503 | 	
 | 
|  |   1504 | 	case ECancelRecoverPrimary:
 | 
|  |   1505 | 		{
 | 
|  |   1506 | 		// Primary session is successfully recovered
 | 
|  |   1507 | 		// Start the next requested operation
 | 
|  |   1508 | 		
 | 
|  |   1509 | 		if (iRequestedOp == EIdle)
 | 
|  |   1510 | 			{
 | 
|  |   1511 | 			// We should only go into Idle if no async operations have been requested.
 | 
|  |   1512 | 			// Consequently, CMsgActive::iReport should be NULL.
 | 
|  |   1513 | 			// We can't ASSERT this here as it is a private member of CMsgActive, but it is worth checking while debugging.
 | 
|  |   1514 | 			StartIdle();
 | 
|  |   1515 | 			}
 | 
|  |   1516 | 		else if (iRequestedOp == EDisconnect)
 | 
|  |   1517 | 			{
 | 
|  |   1518 | 			// We should only start a primary operation if an async operation has been requested, and an aStatus Queue()ed.
 | 
|  |   1519 | 			// Consequently, CMsgActive::iReport should NOT be NULL.
 | 
|  |   1520 | 			// We can't ASSERT this here as it is a private member of CMsgActive, but it is worth checking while debugging.
 | 
|  |   1521 | 			StartPrimaryOperation();
 | 
|  |   1522 | 			SetActive();
 | 
|  |   1523 | 			}
 | 
|  |   1524 | 		else
 | 
|  |   1525 | 			{
 | 
|  |   1526 | 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EProtocolControllerUnexpectedRequestedOp));
 | 
|  |   1527 | 			}
 | 
|  |   1528 | 		
 | 
|  |   1529 | 		break;
 | 
|  |   1530 | 		}
 | 
|  |   1531 | 
 | 
|  |   1532 | 	case ESync:
 | 
|  |   1533 | 	case ESelect:
 | 
|  |   1534 | 	case ECopyToLocal:
 | 
|  |   1535 | 	case ECopyWithinService:
 | 
|  |   1536 | 	case ECopyFromLocal:
 | 
|  |   1537 | 	case EMoveToLocal:
 | 
|  |   1538 | 	case EMoveWithinService:
 | 
|  |   1539 | 	case EMoveFromLocal:
 | 
|  |   1540 | 	case EPopulate:
 | 
|  |   1541 | 	case EDelete:
 | 
|  |   1542 | 	case EDeleteFolder:
 | 
|  |   1543 | 	case ECreate:
 | 
|  |   1544 | 	case ERename:
 | 
|  |   1545 | 	case EUpdateFlag:
 | 
|  |   1546 | 		{
 | 
|  |   1547 | 		// update last operation progress state
 | 
|  |   1548 | 		iImapCompound->Progress(iProgress);
 | 
|  |   1549 | 
 | 
|  |   1550 | 		delete iImapCompound;
 | 
|  |   1551 | 		iImapCompound = NULL;
 | 
|  |   1552 | 		
 | 
|  |   1553 | 		if ((iRequestedOp==ESelect) && (iProgress.iGenericProgress.iErrorCode==KErrNone))
 | 
|  |   1554 | 			{
 | 
|  |   1555 | 			// Do not start IDLE following a select request
 | 
|  |   1556 | 			Complete(iStatus.Int());
 | 
|  |   1557 | 			}
 | 
|  |   1558 | 		else
 | 
|  |   1559 | 			{
 | 
|  |   1560 | 			// Start idle and complete the server mtm request.
 | 
|  |   1561 | 			StartIdle();
 | 
|  |   1562 | 			Complete(iStatus.Int());
 | 
|  |   1563 | 			}
 | 
|  |   1564 | 		break;
 | 
|  |   1565 | 		}
 | 
|  |   1566 | 
 | 
|  |   1567 | 	case EIdle:	// shouldn't happen
 | 
|  |   1568 | 	default:
 | 
|  |   1569 | 		{
 | 
|  |   1570 | 		Complete(iStatus.Int());
 | 
|  |   1571 | 		break;
 | 
|  |   1572 | 		}
 | 
|  |   1573 | 		
 | 
|  |   1574 | 		} // end of switch (iCurrentOp)
 | 
|  |   1575 | 	}
 | 
|  |   1576 | 
 | 
|  |   1577 | /**
 | 
|  |   1578 | This variation on DoRunL() presents a super-state machine, that replaces 
 | 
|  |   1579 | the default state machine during a migration process.
 | 
|  |   1580 | */
 | 
|  |   1581 | void CImapProtocolController::DoMigrateRunL()
 | 
|  |   1582 | 	{
 | 
|  |   1583 | 	// waiting for existing operation to stop to allow migration to occur.
 | 
|  |   1584 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::DoMigrateRunL(iMigrateState = %d) CurrentOp = %d", iMigrateState, iCurrentOp));
 | 
|  |   1585 | 	switch (iMigrateState)
 | 
|  |   1586 | 		{
 | 
|  |   1587 |  		case EWaitingForOpToStop: 
 | 
|  |   1588 | 		case EWaitingForOpToComplete:
 | 
|  |   1589 | 			{
 | 
|  |   1590 | 			// operation has completed (is either finished, or has "paused"
 | 
|  |   1591 | 			// to allow migration to complete. Do any tidying up necessary.
 | 
|  |   1592 | 			ProcessOpCompleteForMigrate();
 | 
|  |   1593 | 			
 | 
|  |   1594 | 			// is there also a background sync op in progress? if not (or if the
 | 
|  |   1595 | 			// background sync op is suspended, we are now ready to migrate, 
 | 
|  |   1596 | 			// otherwise wait for the background op to complete.
 | 
|  |   1597 | 			 // 
 | 
|  |   1598 | 			if (!iBackgroundSyncOp || iBackgroundSyncOp->IsSuspendedForMigrate())
 | 
|  |   1599 | 				{
 | 
|  |   1600 | 				// Asynch disconnect current sockets.
 | 
|  |   1601 | 				DisconnectForMigrateL();
 | 
|  |   1602 | 				}
 | 
|  |   1603 | 			break;
 | 
|  |   1604 | 			}
 | 
|  |   1605 | 		case EDisconnectingForMigrate:
 | 
|  |   1606 | 			{
 | 
|  |   1607 | 			// The disconnect operation has completed. Delete IMAP Sessions.
 | 
|  |   1608 | 			iImapSessionArray.ResetAndDestroy();
 | 
|  |   1609 | 
 | 
|  |   1610 | 			// delete the migration compound object
 | 
|  |   1611 | 			delete iMigrateCompound;
 | 
|  |   1612 | 			iMigrateCompound = NULL;
 | 
|  |   1613 | 			
 | 
|  |   1614 | 			// Notify the mobility framework that we are ready to migrate.
 | 
|  |   1615 | 			iMigrateState = EWaitingForNewCarrier;
 | 
|  |   1616 | 			iMobilityManager->MigrateToNewCarrier();
 | 
|  |   1617 | 			
 | 
|  |   1618 | 			// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   1619 | 			if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   1620 | 				{
 | 
|  |   1621 | 				// Now in a waiting state, set self active
 | 
|  |   1622 | 				iStatus = KRequestPending;
 | 
|  |   1623 | 				SetActive();
 | 
|  |   1624 | 				}
 | 
|  |   1625 | 			break;
 | 
|  |   1626 | 			}
 | 
|  |   1627 | 		case EHandlingConnectError:
 | 
|  |   1628 | 			{
 | 
|  |   1629 | 			// register with the mobility framework
 | 
|  |   1630 | 			iMobilityManager->SetConnection(iImapSessionManager->GetConnectionL());
 | 
|  |   1631 | 						
 | 
|  |   1632 | 			// empty the session array
 | 
|  |   1633 | 			TInt numSessions = iImapSessionArray.Count();
 | 
|  |   1634 | 			for (TInt i=0; i<numSessions; ++i)
 | 
|  |   1635 | 				{
 | 
|  |   1636 | 				if (iImapSessionArray[i])
 | 
|  |   1637 | 					{
 | 
|  |   1638 | 					iImapSessionManager->Disconnect(*(iImapSessionArray[i]));
 | 
|  |   1639 | 					}
 | 
|  |   1640 | 				}
 | 
|  |   1641 | 			iImapSessionArray.ResetAndDestroy();
 | 
|  |   1642 | 
 | 
|  |   1643 | 			// reject the initial carrier
 | 
|  |   1644 | 			iMigrateState = EWaitingInitialCarrierRejected;
 | 
|  |   1645 | 			iMobilityManager->NewCarrierRejected();
 | 
|  |   1646 | 			
 | 
|  |   1647 | 			if (iMigrateState == EWaitingInitialCarrierRejected)
 | 
|  |   1648 | 				{
 | 
|  |   1649 | 				iStatus = KRequestPending;
 | 
|  |   1650 | 				SetActive();
 | 
|  |   1651 | 				}
 | 
|  |   1652 | 			break;
 | 
|  |   1653 | 			}
 | 
|  |   1654 | 		case EStartingReconnect:
 | 
|  |   1655 | 			{
 | 
|  |   1656 | 			NewPrimarySessionL();
 | 
|  |   1657 | 			break;
 | 
|  |   1658 | 			}
 | 
|  |   1659 | 		case EConnectingAfterMigrate:
 | 
|  |   1660 | 			{
 | 
|  |   1661 | 			if (iStatus.Int()!=KErrNone)
 | 
|  |   1662 | 				{
 | 
|  |   1663 | 				// An error has occurred while attempting to re-connect
 | 
|  |   1664 | 				// - reject this new carrier, wait to see if a new one turns up.
 | 
|  |   1665 | 				iMigrateState = EWaitingForNewCarrier;
 | 
|  |   1666 | 				iMobilityManager->NewCarrierRejected();
 | 
|  |   1667 | 
 | 
|  |   1668 | 				// Now in a waiting state, set self active
 | 
|  |   1669 | 				if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   1670 | 					{
 | 
|  |   1671 | 					iStatus = KRequestPending;
 | 
|  |   1672 | 					SetActive();
 | 
|  |   1673 | 					}
 | 
|  |   1674 | 				}
 | 
|  |   1675 | 			else
 | 
|  |   1676 | 				{
 | 
|  |   1677 | 				iMobilityManager->NewCarrierAccepted();
 | 
|  |   1678 | 				RestartAfterMigrateL();
 | 
|  |   1679 | 				}
 | 
|  |   1680 | 			break;
 | 
|  |   1681 | 			}
 | 
|  |   1682 | 		case ENotMigrating:
 | 
|  |   1683 | 		case EWaitingForNewCarrier:
 | 
|  |   1684 | 		case EWaitingInitialCarrierRejected:
 | 
|  |   1685 | 			// DoRunMigrateL() Should never be called in this state.
 | 
|  |   1686 | 		default:
 | 
|  |   1687 | 			{
 | 
|  |   1688 | 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EProtocolControllerUnexpectedMigrateState));
 | 
|  |   1689 | 			break;
 | 
|  |   1690 | 			}
 | 
|  |   1691 | 		}
 | 
|  |   1692 | 	}
 | 
|  |   1693 | 
 | 
|  |   1694 | 
 | 
|  |   1695 | /** 
 | 
|  |   1696 | Called when completing an outstanding client request.
 | 
|  |   1697 | Handles negative (system-wide) error codes returned
 | 
|  |   1698 | on completion of asynchronous service requests.
 | 
|  |   1699 | */
 | 
|  |   1700 | void CImapProtocolController::DoComplete(TInt& aErr)
 | 
|  |   1701 | 	{
 | 
|  |   1702 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::DoComplete() - START - aErr = %d, CurrentOp = %d, iCancelInProgress: %d", aErr, iCurrentOp, iCancelInProgress));
 | 
|  |   1703 | 
 | 
|  |   1704 | 	// Requested operation is completed.
 | 
|  |   1705 | 	iRequestedOp = EIdle;
 | 
|  |   1706 | 
 | 
|  |   1707 | 	// return if everything is OK
 | 
|  |   1708 | 	if (aErr==KErrNone)
 | 
|  |   1709 | 		{
 | 
|  |   1710 | 	    __LOG_TEXT( KDefaultLog, "CImapProtocolController::DoComplete() - END - KErrNone" );
 | 
|  |   1711 | 		return;
 | 
|  |   1712 | 		}
 | 
|  |   1713 | 		
 | 
|  |   1714 | 	// First retrieve the progress information
 | 
|  |   1715 | 	this->Progress();
 | 
|  |   1716 | 	
 | 
|  |   1717 | 	// log that a cancel has occurred and return
 | 
|  |   1718 | 	if (aErr==KErrCancel)
 | 
|  |   1719 | 		{
 | 
|  |   1720 | 	    __LOG_TEXT( KDefaultLog, "CImapProtocolController::DoComplete() - dealing with cancel case..." );
 | 
|  |   1721 | 		iProgress.iGenericProgress.iErrorCode=aErr;
 | 
|  |   1722 | 		if(!iCancelInProgress)
 | 
|  |   1723 | 			{
 | 
|  |   1724 | 	        __LOG_TEXT( KDefaultLog, "CImapProtocolController::DoComplete() - no cancel in progress, so disconnecting all..." );
 | 
|  |   1725 | 			DisconnectAll();
 | 
|  |   1726 | 			}
 | 
|  |   1727 | 			
 | 
|  |   1728 | 	    __LOG_TEXT( KDefaultLog, "CImapProtocolController::DoComplete() - END - KErrCancel" );
 | 
|  |   1729 | 		return;
 | 
|  |   1730 | 		}
 | 
|  |   1731 | 
 | 
|  |   1732 | 	// Non-fatal errors should have been handled prior to this.
 | 
|  |   1733 | 	__LOG_TEXT( KDefaultLog, "CImapProtocolController::DoComplete() - fatal error - disconnect all..." );
 | 
|  |   1734 | 	// iServiceId = 0, indicates we are already disconnected.
 | 
|  |   1735 | 	if(iServiceId!=0)
 | 
|  |   1736 | 		{
 | 
|  |   1737 | 		DisconnectAll();
 | 
|  |   1738 | 		}
 | 
|  |   1739 | 	
 | 
|  |   1740 | 	// Save error code in progress and flag the disconnect
 | 
|  |   1741 | 	iProgress.iGenericProgress.iState=TImap4GenericProgress::EDisconnected;
 | 
|  |   1742 | 	iProgress.iGenericProgress.iErrorCode=aErr;
 | 
|  |   1743 | 
 | 
|  |   1744 |     __LOG_TEXT( KDefaultLog, "CImapProtocolController::DoComplete() - END - fatal error" );
 | 
|  |   1745 | 	}
 | 
|  |   1746 | 	
 | 
|  |   1747 | 
 | 
|  |   1748 | /**
 | 
|  |   1749 | Cancels any outstanding client requested asynchronous operations and recovers
 | 
|  |   1750 | the primary session if required.
 | 
|  |   1751 | 
 | 
|  |   1752 | This function is exclusively for the use of the CImapServerMtm, and only calls
 | 
|  |   1753 | Cancel() if the PC is currently active performing the requested operation. 
 | 
|  |   1754 | If the PC is active for other reasons (for example, waiting for a bearer
 | 
|  |   1755 | migration to complete), the appropriate action is taken.
 | 
|  |   1756 | */
 | 
|  |   1757 | EXPORT_C void CImapProtocolController::CancelAndCleanup()
 | 
|  |   1758 | 	{
 | 
|  |   1759 | 	__LOG_FORMAT( (KDefaultLog, "CImapProtocolController::CancelAndCleanup() - START - iCurrentOp: %d, iRequestedOp: %d, iFlushPrimary: %d", iCurrentOp, iRequestedOp, iFlushPrimary ) );
 | 
|  |   1760 | 	if ( iMigrateState == ENotMigrating ||
 | 
|  |   1761 | 	     iMigrateState == EWaitingForOpToComplete ||
 | 
|  |   1762 | 	     iMigrateState == EWaitingForOpToStop )
 | 
|  |   1763 | 		{
 | 
|  |   1764 | 		// In these states the protocol controller is currently doing something
 | 
|  |   1765 | 		// at the clients request.
 | 
|  |   1766 | 		// iCancelInProgress
 | 
|  |   1767 | 		iCancelInProgress = ETrue;
 | 
|  |   1768 | 		Cancel();
 | 
|  |   1769 | 
 | 
|  |   1770 | 	    __LOG_TEXT(KDefaultLog, "CImapProtocolController::CancelAndCleanup() - done DoCancel");
 | 
|  |   1771 | 
 | 
|  |   1772 | 		// DoCancel() will set iFlushPrimary to ETrue for operations that require 
 | 
|  |   1773 | 		// a flush after being cancelled. This will cause DoRunL() to be called when the
 | 
|  |   1774 | 		// session has been flushed. In the case of bearer migration, the next step will
 | 
|  |   1775 | 		// be started in DoRunL.
 | 
|  |   1776 | 		if (iFlushPrimary) 
 | 
|  |   1777 | 			{
 | 
|  |   1778 | 			iRequestedOp = EIdle; // We want to return to idle when the flush has completed.
 | 
|  |   1779 | 			iCurrentOp = ECancelRecoverPrimary;
 | 
|  |   1780 | 			CImapSession* session = iImapSessionArray[0];
 | 
|  |   1781 | 			session->FlushCancelledCommand(iStatus);
 | 
|  |   1782 | 			SetActive();
 | 
|  |   1783 | 			iFlushPrimary = EFalse;
 | 
|  |   1784 | 			}
 | 
|  |   1785 | 		// clear the cancelling flag
 | 
|  |   1786 | 		iCancelInProgress = EFalse;
 | 
|  |   1787 | 		}
 | 
|  |   1788 | 	else			
 | 
|  |   1789 | 		{
 | 
|  |   1790 | 		// in other migration states, we don't want to cancel because we 
 | 
|  |   1791 | 		// are active for migration purposes. However, we do need to clean
 | 
|  |   1792 | 		// compound operation objects and complete the user.
 | 
|  |   1793 | 		iRequestedOp = iCurrentOp = EIdle;
 | 
|  |   1794 | 		
 | 
|  |   1795 | 		// Update the progress object
 | 
|  |   1796 | 		iProgress.iGenericProgress.iState = TImap4GenericProgress::EIdle;
 | 
|  |   1797 | 		iProgress.iGenericProgress.iErrorCode = KErrCancel;
 | 
|  |   1798 | 
 | 
|  |   1799 | 		delete iImapCompound;
 | 
|  |   1800 | 		iImapCompound = NULL;
 | 
|  |   1801 | 		CMsgActive::DoCancel(); // completes the user request.
 | 
|  |   1802 | 		}
 | 
|  |   1803 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::CancelAndCleanup() - END");
 | 
|  |   1804 | 	}
 | 
|  |   1805 | 
 | 
|  |   1806 | 
 | 
|  |   1807 | /**
 | 
|  |   1808 | DoCancel - called by CMsgActive::Cancel() to cancel asychronous services:
 | 
|  |   1809 | 
 | 
|  |   1810 | Cancel() must not be called on this class to cancel a requested async
 | 
|  |   1811 | service - CancelAndCleanup() should be used instead. CancelAndCleanup()
 | 
|  |   1812 | provides support for cancelling requested operations while this class
 | 
|  |   1813 | has become active for migration purposes.
 | 
|  |   1814 | 
 | 
|  |   1815 | However, Cancel() must always be called eventually as the iStatus needs 
 | 
|  |   1816 | to be cleared. Hence this function must support all cancel operations.
 | 
|  |   1817 | 
 | 
|  |   1818 | This class is allows for Cancel() to be called internally to cancel
 | 
|  |   1819 | async operations that have been launched internally for migration 
 | 
|  |   1820 | purposes, without completing the CImapServerMtm.
 | 
|  |   1821 | */
 | 
|  |   1822 | void CImapProtocolController::DoCancel()
 | 
|  |   1823 | 	{
 | 
|  |   1824 | 	__LOG_FORMAT( (KDefaultLog, "CImapProtocolController::DoCancel() - START - iCurrentOp: %d, iRequestedOp: %d, iFlushPrimary: %d", iCurrentOp, iRequestedOp, iFlushPrimary ) );
 | 
|  |   1825 | 
 | 
|  |   1826 | 	if (iMigrateState==ENotMigrating)
 | 
|  |   1827 | 		{
 | 
|  |   1828 | 		DoCancelClientOp();
 | 
|  |   1829 | 		}
 | 
|  |   1830 | 	else
 | 
|  |   1831 | 		{
 | 
|  |   1832 | 		switch (iMigrateState)
 | 
|  |   1833 | 			{
 | 
|  |   1834 | 			case ESuspendingForMigrate:
 | 
|  |   1835 | 				{
 | 
|  |   1836 | 				// Special handling for cancelling current operation to allow
 | 
|  |   1837 | 				// migration to occur.
 | 
|  |   1838 | 				DoCancelForMigrate();
 | 
|  |   1839 | 				break;
 | 
|  |   1840 | 				}
 | 
|  |   1841 | 			case EWaitingForOpToComplete:
 | 
|  |   1842 | 			case EWaitingForOpToStop:
 | 
|  |   1843 | 				{
 | 
|  |   1844 | 				// we have an outstanding request on the compound operation
 | 
|  |   1845 | 				// call the default DoCancelClientOp(). This will also
 | 
|  |   1846 | 				// complete the client's iStatus with KErrCancel
 | 
|  |   1847 | 				DoCancelClientOp();
 | 
|  |   1848 | 				break;
 | 
|  |   1849 | 				}
 | 
|  |   1850 | 			case EDisconnectingForMigrate:
 | 
|  |   1851 | 				{
 | 
|  |   1852 | 				// outstanding op is on the iMigrateCompound
 | 
|  |   1853 | 				iMigrateCompound->Cancel();
 | 
|  |   1854 | 				delete iMigrateCompound;
 | 
|  |   1855 | 				iMigrateCompound = NULL;
 | 
|  |   1856 | 				break;
 | 
|  |   1857 | 				}
 | 
|  |   1858 | 			case EConnectingAfterMigrate:
 | 
|  |   1859 | 				{
 | 
|  |   1860 | 				// This state represents re-connection of the primary session,
 | 
|  |   1861 | 				// it is safe to simply clear the imap session array.
 | 
|  |   1862 | 				iImapSessionManager->Cancel();
 | 
|  |   1863 | 				iImapSessionArray.ResetAndDestroy();
 | 
|  |   1864 | 				break;
 | 
|  |   1865 | 				}
 | 
|  |   1866 | 			case EWaitingForNewCarrier:
 | 
|  |   1867 | 			case EWaitingInitialCarrierRejected:
 | 
|  |   1868 | 				{
 | 
|  |   1869 | 				// in these states, we are in a self-induced active state
 | 
|  |   1870 | 				// Cancel it:
 | 
|  |   1871 | 				TRequestStatus* status = &iStatus;
 | 
|  |   1872 | 				User::RequestComplete(status, KErrCancel);
 | 
|  |   1873 | 				break;
 | 
|  |   1874 | 				}
 | 
|  |   1875 | 
 | 
|  |   1876 | 			case EStartingReconnect: // nothing to cancel
 | 
|  |   1877 | 			case EHandlingConnectError: // nothing to cancel
 | 
|  |   1878 | 			case ENotMigrating:		 // somethings gone wrong
 | 
|  |   1879 | 			default:
 | 
|  |   1880 | 				{
 | 
|  |   1881 | 				__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EProtocolControllerCancelBadMigrateState));
 | 
|  |   1882 | 				}
 | 
|  |   1883 | 			} // switch (iMigrateState)
 | 
|  |   1884 | 		}
 | 
|  |   1885 | 
 | 
|  |   1886 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancel() - END");
 | 
|  |   1887 | 	}
 | 
|  |   1888 | 
 | 
|  |   1889 | void CImapProtocolController::DoCancelClientOp()
 | 
|  |   1890 | 	{
 | 
|  |   1891 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - START");
 | 
|  |   1892 | 
 | 
|  |   1893 | 	// Update the requested and current operations
 | 
|  |   1894 | 	// the implication is that a return to EIdle is required
 | 
|  |   1895 | 	// current op may be updated later if an async op is issued.
 | 
|  |   1896 | 	TImapProtocolOp cancelledOp = iCurrentOp;
 | 
|  |   1897 | 	iRequestedOp = iCurrentOp = EIdle;
 | 
|  |   1898 | 
 | 
|  |   1899 | 	switch (cancelledOp)
 | 
|  |   1900 | 		{
 | 
|  |   1901 | 		case EConnect:
 | 
|  |   1902 | 			{
 | 
|  |   1903 | 			__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - EConnect");
 | 
|  |   1904 | 			iImapSessionManager->Cancel();
 | 
|  |   1905 | 			
 | 
|  |   1906 | 			// As this state represents connection of the primary session,
 | 
|  |   1907 | 			// it is safe to simply clear the imap session array.
 | 
|  |   1908 | 			iImapSessionArray.ResetAndDestroy();
 | 
|  |   1909 | 
 | 
|  |   1910 | 			// delete the background sync operation if it exists.
 | 
|  |   1911 | 			if (iBackgroundSyncOp != NULL)
 | 
|  |   1912 | 				{
 | 
|  |   1913 | 				iBackgroundSyncOp->Cancel();
 | 
|  |   1914 | 				delete iBackgroundSyncOp;
 | 
|  |   1915 | 				iBackgroundSyncOp=NULL;
 | 
|  |   1916 | 				}
 | 
|  |   1917 | 
 | 
|  |   1918 | 			// delete the sync manager		
 | 
|  |   1919 | 			delete iImapSyncManager;
 | 
|  |   1920 | 			iImapSyncManager = NULL;
 | 
|  |   1921 | 
 | 
|  |   1922 | 			break;
 | 
|  |   1923 | 			}
 | 
|  |   1924 | 		
 | 
|  |   1925 | 		case EConnectSecondary:
 | 
|  |   1926 | 			{
 | 
|  |   1927 | 	        __LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - EConnectSecondary");
 | 
|  |   1928 | 			// Cancel the connect request
 | 
|  |   1929 | 			iImapSessionManager->Cancel();
 | 
|  |   1930 | 			iForegroundSession=0;
 | 
|  |   1931 | 			
 | 
|  |   1932 | 			// Remove the session pointer from the array
 | 
|  |   1933 | 			// The session has already been deleted - see note above.
 | 
|  |   1934 | 			TInt numSessions = iImapSessionArray.Count();
 | 
|  |   1935 | 			iImapSessionArray.Remove(numSessions-1);
 | 
|  |   1936 | 			
 | 
|  |   1937 | 			if (iImapCompound!=NULL)
 | 
|  |   1938 | 				{
 | 
|  |   1939 | 				// The requested op hasn't actually started yet
 | 
|  |   1940 | 				// so don't cancel on the compound operation..
 | 
|  |   1941 | 				// update last operation progress state
 | 
|  |   1942 | 				iImapCompound->Progress(iProgress);
 | 
|  |   1943 | 				
 | 
|  |   1944 | 				delete iImapCompound;
 | 
|  |   1945 | 				iImapCompound = NULL;
 | 
|  |   1946 | 				}
 | 
|  |   1947 | 			
 | 
|  |   1948 | 			// The progress will not report cancel at this stage - force it here.
 | 
|  |   1949 | 			iProgress.iGenericProgress.iState = TImap4GenericProgress::EIdle;
 | 
|  |   1950 | 			iProgress.iGenericProgress.iErrorCode = KErrCancel;
 | 
|  |   1951 | 
 | 
|  |   1952 | 			break;
 | 
|  |   1953 | 			}
 | 
|  |   1954 | 
 | 
|  |   1955 | 		case EDisconnect:
 | 
|  |   1956 | 			{
 | 
|  |   1957 | 	        __LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - EDisconnect");
 | 
|  |   1958 | 			// Cancel the disconnect compound operation
 | 
|  |   1959 | 			iImapCompound->Cancel();
 | 
|  |   1960 | 
 | 
|  |   1961 | 			delete iImapCompound;
 | 
|  |   1962 | 			iImapCompound = NULL;
 | 
|  |   1963 | 			
 | 
|  |   1964 | 			// A cancelled disconnect will leave the sessions disconnected
 | 
|  |   1965 | 			// but not deleted. Reset and destroy the session array.
 | 
|  |   1966 | 			iImapSessionArray.ResetAndDestroy();
 | 
|  |   1967 | 			
 | 
|  |   1968 | 			break;
 | 
|  |   1969 | 			}
 | 
|  |   1970 | 		
 | 
|  |   1971 | 		case EIdle:
 | 
|  |   1972 | 			{
 | 
|  |   1973 | 			// This is unexpected - in this state there should be no
 | 
|  |   1974 | 			// outstanding asynconous requests on the Protocol Controller.
 | 
|  |   1975 | 			// Protocol Controller has no outstanding requests in this state
 | 
|  |   1976 | 			// however a sync may be running in the background. This is
 | 
|  |   1977 | 			// cancelled when the background sync object's destructor is called.
 | 
|  |   1978 | 			// So.. Nothing to do.
 | 
|  |   1979 | 			break;
 | 
|  |   1980 | 			}
 | 
|  |   1981 | 		
 | 
|  |   1982 | 		case EStopIdle:
 | 
|  |   1983 | 			{
 | 
|  |   1984 | 			if (iImapCompound!=NULL)
 | 
|  |   1985 | 				{
 | 
|  |   1986 | 				// The requested op hasn't actually started yet
 | 
|  |   1987 | 				// so don't cancel on the compound operation..
 | 
|  |   1988 | 				// update last operation progress state
 | 
|  |   1989 | 				iImapCompound->Progress(iProgress);
 | 
|  |   1990 | 				
 | 
|  |   1991 | 				delete iImapCompound;
 | 
|  |   1992 | 				iImapCompound = NULL;
 | 
|  |   1993 | 				}
 | 
|  |   1994 | 			
 | 
|  |   1995 | 			// The progress will not report cancel at this stage - force it here.
 | 
|  |   1996 | 			iProgress.iGenericProgress.iState = TImap4GenericProgress::EIdle;
 | 
|  |   1997 | 			iProgress.iGenericProgress.iErrorCode = KErrCancel;
 | 
|  |   1998 | 			
 | 
|  |   1999 | 			// Cancel the idle controller.
 | 
|  |   2000 | 			iImapIdleController->Cancel();
 | 
|  |   2001 | 			
 | 
|  |   2002 | 			// Cancelling the idle controller is likely to leave the IMAP Session
 | 
|  |   2003 | 			// with data left on the input stream to be dealt with. We need to 
 | 
|  |   2004 | 			// flush the session if we wish to re-use it.
 | 
|  |   2005 | 			iFlushPrimary = ETrue;
 | 
|  |   2006 | 
 | 
|  |   2007 | 			break;
 | 
|  |   2008 | 			}
 | 
|  |   2009 | 
 | 
|  |   2010 | 		case ESync:
 | 
|  |   2011 | 		case ESelect:
 | 
|  |   2012 | 		case ECopyToLocal:
 | 
|  |   2013 | 		case ECopyWithinService:
 | 
|  |   2014 | 		case ECopyFromLocal:
 | 
|  |   2015 | 		case EMoveToLocal:
 | 
|  |   2016 | 		case EMoveWithinService:
 | 
|  |   2017 | 		case EMoveFromLocal:
 | 
|  |   2018 | 		case EPopulate:
 | 
|  |   2019 | 		case EDelete:
 | 
|  |   2020 | 		case EDeleteFolder:
 | 
|  |   2021 | 		case ECreate:
 | 
|  |   2022 | 		case ERename:
 | 
|  |   2023 | 	case EUpdateFlag:
 | 
|  |   2024 | 			{
 | 
|  |   2025 | 			__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - ESync/ESelect/ECopyToLocal/ECopyWithinService/ECopyFromLocal/EMoveToLocal/EMoveWithinService/EMoveFromLocal/EPopulate/EDelete/EDeleteFolder/ECreate/ERename/");
 | 
|  |   2026 | 			// This is the normal case, a requested operation is
 | 
|  |   2027 | 			// being performed by a compound operation object.
 | 
|  |   2028 | 			// First of all, check one exists.
 | 
|  |   2029 | 			if (iImapCompound!=NULL)
 | 
|  |   2030 | 				{
 | 
|  |   2031 | 				// Cancel the compound operation
 | 
|  |   2032 | 				__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - cancelling iImapCompound...");
 | 
|  |   2033 | 				iImapCompound->Cancel();
 | 
|  |   2034 | 
 | 
|  |   2035 | 				// update last operation progress state
 | 
|  |   2036 | 				__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - getting progres...");
 | 
|  |   2037 | 				iImapCompound->Progress(iProgress);
 | 
|  |   2038 | 
 | 
|  |   2039 | 				// Delete the compound object
 | 
|  |   2040 | 				__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - deleting compound...");
 | 
|  |   2041 | 				delete iImapCompound;
 | 
|  |   2042 | 				iImapCompound = NULL;
 | 
|  |   2043 | 				
 | 
|  |   2044 | 				// Cancelling the compound operation is likely to leave 
 | 
|  |   2045 | 				// the IMAP Session in an incomplete state. We need to 
 | 
|  |   2046 | 				// flush the session if we wish to re-use it.
 | 
|  |   2047 | 				if (iForegroundSession==0)
 | 
|  |   2048 | 					{
 | 
|  |   2049 | 					__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - flush primary = ETrue...");
 | 
|  |   2050 | 					iFlushPrimary = ETrue;
 | 
|  |   2051 | 					}
 | 
|  |   2052 | 				else
 | 
|  |   2053 | 					{
 | 
|  |   2054 | 					__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - drop session...");
 | 
|  |   2055 | 					DropSession(iForegroundSession);
 | 
|  |   2056 | 					iForegroundSession=0;
 | 
|  |   2057 | 					}
 | 
|  |   2058 | 
 | 
|  |   2059 | 				__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - main iImapCompound handling complete...");
 | 
|  |   2060 | 				}
 | 
|  |   2061 | 			break;
 | 
|  |   2062 | 			}
 | 
|  |   2063 | 	
 | 
|  |   2064 | 		case ECancelRecoverPrimary:
 | 
|  |   2065 | 			{
 | 
|  |   2066 | 			// The recover must be taking too long.
 | 
|  |   2067 | 			// cancel the recover request..
 | 
|  |   2068 | 			(iImapSessionArray[0])->Cancel();
 | 
|  |   2069 | 			// Delete all sessions, go offline etc.
 | 
|  |   2070 | 			DisconnectAll();
 | 
|  |   2071 | 			break;
 | 
|  |   2072 | 			}
 | 
|  |   2073 | 		default:
 | 
|  |   2074 | 			{
 | 
|  |   2075 | 			// nothing to do..
 | 
|  |   2076 | 			break;
 | 
|  |   2077 | 			}
 | 
|  |   2078 | 		} // end of switch (cancelledOp)
 | 
|  |   2079 | 
 | 
|  |   2080 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - about to call CMsgActive::DoCancel()...");
 | 
|  |   2081 | 	CMsgActive::DoCancel();
 | 
|  |   2082 | 
 | 
|  |   2083 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelClientOp() - END");
 | 
|  |   2084 | 	}
 | 
|  |   2085 | 
 | 
|  |   2086 | 
 | 
|  |   2087 | /**
 | 
|  |   2088 | Performs a fast disconnect on all sessions
 | 
|  |   2089 | 
 | 
|  |   2090 | Ensures that the compound, background sync and sync manager objects are
 | 
|  |   2091 | deleted following the disconnect.
 | 
|  |   2092 | @param aMarkOffline - indicates if the service is to be marked offline.
 | 
|  |   2093 | */
 | 
|  |   2094 | void CImapProtocolController::DisconnectAll()
 | 
|  |   2095 | 	{
 | 
|  |   2096 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - START");
 | 
|  |   2097 | 
 | 
|  |   2098 | 	// Delete the background sync op
 | 
|  |   2099 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - deleting iBackgroundSyncOp");
 | 
|  |   2100 | 	delete iBackgroundSyncOp;
 | 
|  |   2101 | 	iBackgroundSyncOp=NULL;
 | 
|  |   2102 | 
 | 
|  |   2103 | 	// Delete the imap compound operation
 | 
|  |   2104 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - deleting iImapCompound");
 | 
|  |   2105 | 	delete iImapCompound;
 | 
|  |   2106 | 	iImapCompound=NULL;
 | 
|  |   2107 | 	
 | 
|  |   2108 | 	// Delete the migrate compound operation
 | 
|  |   2109 | 	delete iMigrateCompound;
 | 
|  |   2110 | 	iMigrateCompound = NULL;
 | 
|  |   2111 | 
 | 
|  |   2112 | 	// delete the sync manager
 | 
|  |   2113 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - deleting iImapSyncManager");
 | 
|  |   2114 | 	delete iImapSyncManager;
 | 
|  |   2115 | 	iImapSyncManager = NULL;
 | 
|  |   2116 | 	
 | 
|  |   2117 | 	// delete the mobility manager (de-register for mobility notifications)
 | 
|  |   2118 | 	delete iMobilityManager;
 | 
|  |   2119 | 	iMobilityManager = NULL;
 | 
|  |   2120 | 
 | 
|  |   2121 | 	// delete the imap idle controller
 | 
|  |   2122 | 	delete iImapIdleController;
 | 
|  |   2123 | 	iImapIdleController = NULL;
 | 
|  |   2124 | 
 | 
|  |   2125 | 	// Drop connection on each of the imap sessions
 | 
|  |   2126 | 	TInt numSessions = iImapSessionArray.Count();
 | 
|  |   2127 | 	for (TInt i=0; i<numSessions; ++i)
 | 
|  |   2128 | 		{
 | 
|  |   2129 | 		if (iImapSessionArray[i])
 | 
|  |   2130 | 			{
 | 
|  |   2131 | 	        __LOG_FORMAT( (KDefaultLog, "CImapProtocolController::DisconnectAll() - disconnecting session: %d/%d", i, numSessions ) );
 | 
|  |   2132 | 			iImapSessionManager->Disconnect(*(iImapSessionArray[i]));
 | 
|  |   2133 | 			}
 | 
|  |   2134 | 		}
 | 
|  |   2135 | 		
 | 
|  |   2136 | 	// The current network connection will be closed
 | 
|  |   2137 |  	iImapSessionManager->CloseNetworkConnection();
 | 
|  |   2138 | 
 | 
|  |   2139 | 
 | 
|  |   2140 | 	// empty the session array
 | 
|  |   2141 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - resetting and destroying sessions...");
 | 
|  |   2142 | 	iImapSessionArray.ResetAndDestroy();
 | 
|  |   2143 | 	
 | 
|  |   2144 | 	// force the state to IDLE
 | 
|  |   2145 | 	iRequestedOp = EIdle;
 | 
|  |   2146 | 	iCurrentOp = EIdle;
 | 
|  |   2147 | 	
 | 
|  |   2148 | 	// Clear serviceid and mark the service as offline
 | 
|  |   2149 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - about to MarkOnOrOffline...");
 | 
|  |   2150 | 	TRAP_IGNORE(MarkOnOrOfflineL(EFalse));
 | 
|  |   2151 | 	iServiceId=0;
 | 
|  |   2152 | 
 | 
|  |   2153 |     __LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectAll() - END");
 | 
|  |   2154 | 	}
 | 
|  |   2155 | 
 | 
|  |   2156 | /**
 | 
|  |   2157 | Performs an immediate disconnect of specifed session and removes it from
 | 
|  |   2158 | the session array.
 | 
|  |   2159 | 
 | 
|  |   2160 | @param sessionId - the index in the session array of the session to drop.
 | 
|  |   2161 | */
 | 
|  |   2162 | void CImapProtocolController::DropSession(TInt sessionId)
 | 
|  |   2163 | 	{
 | 
|  |   2164 | 	if (sessionId < iImapSessionArray.Count())
 | 
|  |   2165 | 		{
 | 
|  |   2166 | 		CImapSession* tempSession = iImapSessionArray[sessionId];
 | 
|  |   2167 | 		if (tempSession)
 | 
|  |   2168 | 			{
 | 
|  |   2169 | 			iImapSessionManager->Disconnect(*tempSession);
 | 
|  |   2170 | 			delete tempSession;
 | 
|  |   2171 | 			}
 | 
|  |   2172 | 		iImapSessionArray.Remove(sessionId);
 | 
|  |   2173 | 		}
 | 
|  |   2174 | 	}
 | 
|  |   2175 | 
 | 
|  |   2176 | /**
 | 
|  |   2177 | Private method to select session from the session array for use for operations
 | 
|  |   2178 | that are supported while background operations are in progress.
 | 
|  |   2179 | Issues a request to connect a secondary session if the primary session is busy
 | 
|  |   2180 | and a secondary session is not already available. In this case the requested op
 | 
|  |   2181 | is updated to show a secondary connect request, and the original requested op
 | 
|  |   2182 | is saved.
 | 
|  |   2183 | 
 | 
|  |   2184 | @param  aIndexToUse updated to indicate the index of the session to be used
 | 
|  |   2185 | @return ETrue if the session is connected and ready to use immediately.
 | 
|  |   2186 | 		EFalse if a request to connect a secondary session has been issued.
 | 
|  |   2187 | */
 | 
|  |   2188 | TBool CImapProtocolController::SelectSessionL(TInt& aIndexToUse)
 | 
|  |   2189 | 	{
 | 
|  |   2190 | 	__ASSERT_DEBUG(iCurrentOp != ECancelRecoverPrimary, TImapServerPanic::ImapPanic(TImapServerPanic::EProtocolControllerUnexpectedCurrentOp));
 | 
|  |   2191 | 	
 | 
|  |   2192 | 	aIndexToUse = 0; // default to primary session.
 | 
|  |   2193 | 	TBool sessionReady = ETrue;
 | 
|  |   2194 | 	if (iBackgroundSyncOp != NULL)
 | 
|  |   2195 | 		{
 | 
|  |   2196 | 		TInt sessionCount = iImapSessionArray.Count();
 | 
|  |   2197 | 		if (sessionCount>=2)
 | 
|  |   2198 | 			{
 | 
|  |   2199 | 			// already a secondary session available - use this
 | 
|  |   2200 | 			aIndexToUse = sessionCount-1;
 | 
|  |   2201 | 			}
 | 
|  |   2202 | 		else
 | 
|  |   2203 | 			{
 | 
|  |   2204 | 			// Create a new session and get it connected.
 | 
|  |   2205 | 			iCurrentOp = EConnectSecondary;
 | 
|  |   2206 | 			
 | 
|  |   2207 | 			CImapSession* imapSession = NULL;
 | 
|  |   2208 | 			iImapSessionArray.AppendL(imapSession);
 | 
|  |   2209 | 			iImapSessionManager->GetSessionL(iStatus, iImapSessionArray[sessionCount]);
 | 
|  |   2210 | 			aIndexToUse = sessionCount;
 | 
|  |   2211 | 			sessionReady = EFalse;
 | 
|  |   2212 | 			}
 | 
|  |   2213 | 		}
 | 
|  |   2214 | 	return sessionReady;
 | 
|  |   2215 | 	}
 | 
|  |   2216 | 
 | 
|  |   2217 | /**
 | 
|  |   2218 | Called to kick off a foreground operation, ie a user requested
 | 
|  |   2219 | operation that is being performed on the primary IMAP session.
 | 
|  |   2220 | 
 | 
|  |   2221 | If the session is in IMAP IDLE, a request is issued to stop this
 | 
|  |   2222 | and the requested operation is started when the stop-idle operation
 | 
|  |   2223 | has completed. Otherwise the operation is started immediately.
 | 
|  |   2224 | */
 | 
|  |   2225 | void CImapProtocolController::StartPrimaryOperation()
 | 
|  |   2226 | 	{
 | 
|  |   2227 | 	// Make sure the foreground session id is correct
 | 
|  |   2228 | 	iForegroundSession = 0;
 | 
|  |   2229 | 	// imap idle controller is active in any state after
 | 
|  |   2230 | 	// idle has been requested.
 | 
|  |   2231 | 	if (iImapIdleController->IsActive())
 | 
|  |   2232 | 		{
 | 
|  |   2233 | 		iCurrentOp = EStopIdle;
 | 
|  |   2234 | 		iImapIdleController->StopIdle(iStatus);
 | 
|  |   2235 | 		}
 | 
|  |   2236 | 	else
 | 
|  |   2237 | 		{
 | 
|  |   2238 | 		iCurrentOp = iRequestedOp;
 | 
|  |   2239 | 		iImapCompound->StartOperation(iStatus, *iImapSessionArray[iForegroundSession]);
 | 
|  |   2240 | 		}
 | 
|  |   2241 | 	}
 | 
|  |   2242 | 
 | 
|  |   2243 | /**
 | 
|  |   2244 | Starts the background IDLE process.
 | 
|  |   2245 | If IDLE is not supported by the server, or if IDLE is disabled via the
 | 
|  |   2246 | account settings, a "dummy read" is issued, to manage any unsolicited
 | 
|  |   2247 | server messages.
 | 
|  |   2248 | 
 | 
|  |   2249 | This is called when user-requested compound operations have completed
 | 
|  |   2250 | to return the primary session to IDLE state. Note that some operations
 | 
|  |   2251 | require that IDLE is not re-issued, eg "select". It is also called
 | 
|  |   2252 | when a background sync operation has completed, if there is no foreground
 | 
|  |   2253 | operation currently in progress
 | 
|  |   2254 | 
 | 
|  |   2255 | Idle is only issued on the primary session.
 | 
|  |   2256 | 
 | 
|  |   2257 | Idle is not started if there is a background operation in progress 
 | 
|  |   2258 | */
 | 
|  |   2259 | void CImapProtocolController::StartIdle()
 | 
|  |   2260 | 	{
 | 
|  |   2261 | 	iCurrentOp = EIdle;
 | 
|  |   2262 | 	if (iBackgroundSyncOp==NULL)
 | 
|  |   2263 | 		{
 | 
|  |   2264 | 		iImapIdleController->StartIdle();
 | 
|  |   2265 | 		}
 | 
|  |   2266 | 	}
 | 
|  |   2267 | 
 | 
|  |   2268 | /**
 | 
|  |   2269 | Called by the CImapIdleController in the case of an error being observed
 | 
|  |   2270 | while in IDLE state.
 | 
|  |   2271 | 
 | 
|  |   2272 | @param aError - the observed error
 | 
|  |   2273 | */
 | 
|  |   2274 | void CImapProtocolController::OnIdleError(TInt aError)
 | 
|  |   2275 | 	{
 | 
|  |   2276 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::OnIdleError(aError = %d)", aError));
 | 
|  |   2277 | 	if (aError>0)
 | 
|  |   2278 | 		{
 | 
|  |   2279 | 		aError = KErrImapServerFail;
 | 
|  |   2280 | 		}
 | 
|  |   2281 | 	iProgress.iGenericProgress.iErrorCode = aError;
 | 
|  |   2282 | 	iProgress.iGenericProgress.iState=TImap4GenericProgress::EDisconnected;
 | 
|  |   2283 | 	DisconnectAll();
 | 
|  |   2284 | 	// Nothing to complete.
 | 
|  |   2285 | 	}
 | 
|  |   2286 | 
 | 
|  |   2287 | /**
 | 
|  |   2288 | Returns the progress information for the outstanding command.
 | 
|  |   2289 | 
 | 
|  |   2290 | @return progress information
 | 
|  |   2291 | */
 | 
|  |   2292 | EXPORT_C TImap4CompoundProgress CImapProtocolController::Progress()
 | 
|  |   2293 | 	{
 | 
|  |   2294 | 	// Progress of foreground operation is returned	over that of a
 | 
|  |   2295 | 	// background sync operation.
 | 
|  |   2296 | 	// Do not refresh the progress while migrating.
 | 
|  |   2297 | 	if (iCurrentOp!=EIdle && iMigrateState == ENotMigrating)
 | 
|  |   2298 | 		{
 | 
|  |   2299 | 		// do not update if IDLEing - return the stored progress object
 | 
|  |   2300 | 		// this should have been populated correctly on completion of
 | 
|  |   2301 | 		// requested operation, whether successful or otherwise.
 | 
|  |   2302 | 		switch (iCurrentOp)
 | 
|  |   2303 | 			{
 | 
|  |   2304 | 		case EConnect:
 | 
|  |   2305 | 			{
 | 
|  |   2306 | 			iImapSessionManager->Progress(iProgress.iGenericProgress);
 | 
|  |   2307 | 			break;
 | 
|  |   2308 | 			}
 | 
|  |   2309 | 		case EStopIdle:
 | 
|  |   2310 | 		case ESync:
 | 
|  |   2311 | 		case ESelect:
 | 
|  |   2312 | 		case ECopyToLocal:
 | 
|  |   2313 | 		case ECopyWithinService:
 | 
|  |   2314 | 		case ECopyFromLocal:
 | 
|  |   2315 | 		case EMoveToLocal:
 | 
|  |   2316 | 		case EMoveWithinService:
 | 
|  |   2317 | 		case EMoveFromLocal:
 | 
|  |   2318 | 		case EPopulate:
 | 
|  |   2319 | 		case EDelete:
 | 
|  |   2320 | 		case EDeleteFolder:
 | 
|  |   2321 | 		case ECreate:
 | 
|  |   2322 | 		case ERename:
 | 
|  |   2323 | 		case EDisconnect:
 | 
|  |   2324 | 		case EUpdateFlag: 
 | 
|  |   2325 | 			{
 | 
|  |   2326 | 			// Obtain progress from compound object if it exists
 | 
|  |   2327 | 			// Otherwise the last progress obtained on completion
 | 
|  |   2328 | 			// of the compound object is returned.
 | 
|  |   2329 | 			if (iImapCompound!=NULL)
 | 
|  |   2330 | 				{
 | 
|  |   2331 | 				iImapCompound->Progress(iProgress);
 | 
|  |   2332 | 				}
 | 
|  |   2333 | 			break;
 | 
|  |   2334 | 			}
 | 
|  |   2335 | 		case EIdle:
 | 
|  |   2336 | 		default:
 | 
|  |   2337 | 			break;
 | 
|  |   2338 | 			}
 | 
|  |   2339 | 		}
 | 
|  |   2340 | 		else if (iBackgroundSyncOp!=NULL)
 | 
|  |   2341 | 		{
 | 
|  |   2342 | 		// update sync progress if background sync is being performed.
 | 
|  |   2343 | 		iBackgroundSyncOp->Progress(iProgress);
 | 
|  |   2344 | 		}
 | 
|  |   2345 | 
 | 
|  |   2346 | 	return iProgress;
 | 
|  |   2347 | 	}
 | 
|  |   2348 | 
 | 
|  |   2349 | /**
 | 
|  |   2350 | changes local subscription flag on a folder immediately.
 | 
|  |   2351 | If unsubscribing, the folder is marked as invisible, and the invisible
 | 
|  |   2352 | flag is propagated to any parent folders that are not themselves subscribed
 | 
|  |   2353 | or contain subscribed folders.
 | 
|  |   2354 | 
 | 
|  |   2355 | @param aFolder
 | 
|  |   2356 | @param aSubscribed
 | 
|  |   2357 | @return Error code
 | 
|  |   2358 | */
 | 
|  |   2359 | EXPORT_C TInt CImapProtocolController::SetLocalSubscription(const TMsvId aFolder, 
 | 
|  |   2360 | 															TBool aSubscribed)
 | 
|  |   2361 | 	{
 | 
|  |   2362 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::SetLocalSubscription()");
 | 
|  |   2363 | 
 | 
|  |   2364 | 	TInt err;
 | 
|  |   2365 | 
 | 
|  |   2366 | 	// Move to the entry
 | 
|  |   2367 | 	if ((err=iEntry.SetEntry(aFolder))!=KErrNone)
 | 
|  |   2368 | 		return(err);
 | 
|  |   2369 | 
 | 
|  |   2370 | 	// Check it's a folder
 | 
|  |   2371 | 	if (iEntry.Entry().iType!=KUidMsvFolderEntry)
 | 
|  |   2372 | 		return(KErrNotSupported);
 | 
|  |   2373 | 
 | 
|  |   2374 | 	// update subscription flag
 | 
|  |   2375 | 	TMsvEmailEntry entry=iEntry.Entry();
 | 
|  |   2376 | 	entry.SetLocalSubscription(aSubscribed);
 | 
|  |   2377 | 	entry.SetVisible(aSubscribed);
 | 
|  |   2378 | 	
 | 
|  |   2379 | 	err = iEntry.ChangeEntry(entry);
 | 
|  |   2380 | 		
 | 
|  |   2381 | 	// Return if error or if setting subscribed
 | 
|  |   2382 | 	if (err!=KErrNone || !aSubscribed)
 | 
|  |   2383 | 		{
 | 
|  |   2384 | 		TRAP(err, PropagateUnsubscribeL(aFolder));
 | 
|  |   2385 | 		return err;
 | 
|  |   2386 | 		}
 | 
|  |   2387 | 	else
 | 
|  |   2388 | 		{
 | 
|  |   2389 | 		return KErrNone;
 | 
|  |   2390 | 		}
 | 
|  |   2391 | 	}
 | 
|  |   2392 | 
 | 
|  |   2393 | /**
 | 
|  |   2394 | Marks aFolder as invisible and propagates the invisible flag to parent folder.
 | 
|  |   2395 | 
 | 
|  |   2396 | @param aFolder the unsubscribed folder.
 | 
|  |   2397 | */
 | 
|  |   2398 | void CImapProtocolController::PropagateUnsubscribeL(const TMsvId aFolder)
 | 
|  |   2399 | 	{
 | 
|  |   2400 | 	// Settings may not yet be loaded.
 | 
|  |   2401 | 	if (iImapSettings->SettingsLoaded()==EFalse)
 | 
|  |   2402 | 		{
 | 
|  |   2403 | 		iImapSettings->LoadSettingsL(aFolder);
 | 
|  |   2404 | 		}
 | 
|  |   2405 | 
 | 
|  |   2406 | 	// if synchronisation setting is not remote only then
 | 
|  |   2407 | 	// update the invisibility flags
 | 
|  |   2408 | 	if (iImapSettings->Synchronise() != EUseRemote)
 | 
|  |   2409 | 		{
 | 
|  |   2410 | 		PropagateInvisibleFlagL(aFolder);
 | 
|  |   2411 | 		ChangeVisibilityL(aFolder,ETrue,EFalse,KUidMsvMessageEntry);
 | 
|  |   2412 | 		}
 | 
|  |   2413 | 	}
 | 
|  |   2414 | 
 | 
|  |   2415 | 
 | 
|  |   2416 | // Mark service as on or offline
 | 
|  |   2417 | void CImapProtocolController::MarkOnOrOfflineL( const TBool aOnline )
 | 
|  |   2418 | 	{
 | 
|  |   2419 | 	// Mark service entry as on/offline	
 | 
|  |   2420 | 	User::LeaveIfError( iEntry.SetEntry( iServiceId ) );
 | 
|  |   2421 | 
 | 
|  |   2422 | 	TMsvEntry entry=iEntry.Entry();
 | 
|  |   2423 | 	entry.SetConnected( aOnline );
 | 
|  |   2424 | 	User::LeaveIfError( iEntry.ChangeEntry( entry ) );
 | 
|  |   2425 | 
 | 
|  |   2426 | 	// Release the service entry
 | 
|  |   2427 | 	User::LeaveIfError( iEntry.SetEntry( KMsvNullIndexEntryId ) );
 | 
|  |   2428 | 
 | 
|  |   2429 | 	// Going offline?
 | 
|  |   2430 | 	if ( !aOnline && iImapSettings->DisconnectedUserMode() )
 | 
|  |   2431 | 		{
 | 
|  |   2432 | 		// We're an expert user going offline: don't touch anything
 | 
|  |   2433 | 		return;
 | 
|  |   2434 | 		}
 | 
|  |   2435 | 
 | 
|  |   2436 | 	// Mark all immediate children of the service as invisible
 | 
|  |   2437 | 	if ( !aOnline )
 | 
|  |   2438 | 		ChangeVisibilityL( iServiceId, !aOnline );
 | 
|  |   2439 | 	}
 | 
|  |   2440 | 	
 | 
|  |   2441 | void CImapProtocolController::ChangeVisibilityL(TMsvId aParent, TBool aInvisible)
 | 
|  |   2442 | 	{
 | 
|  |   2443 | 	ChangeVisibilityL(aParent, aInvisible, ETrue, KUidMsvFolderEntry);
 | 
|  |   2444 | 	}
 | 
|  |   2445 | 
 | 
|  |   2446 | 
 | 
|  |   2447 | void CImapProtocolController::ChangeVisibilityL(TMsvId aParent, TBool aInvisible, TBool aRecurse, TUid aType)
 | 
|  |   2448 | 	{
 | 
|  |   2449 | 	// Get children at this level
 | 
|  |   2450 | 	CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection;
 | 
|  |   2451 | 	CleanupStack::PushL( selection );
 | 
|  |   2452 | 
 | 
|  |   2453 | 	CMsvEntrySelection* folders = new (ELeave) CMsvEntrySelection;
 | 
|  |   2454 | 	CleanupStack::PushL( folders );
 | 
|  |   2455 | 
 | 
|  |   2456 | 	User::LeaveIfError( iEntry.SetEntry( aParent ) );
 | 
|  |   2457 | 	User::LeaveIfError( iEntry.GetChildren( *selection ) );
 | 
|  |   2458 | 
 | 
|  |   2459 | 	if ( selection->Count() )
 | 
|  |   2460 | 		{
 | 
|  |   2461 | 		for( TInt child=0; child < selection->Count(); child++ )
 | 
|  |   2462 | 			{
 | 
|  |   2463 | 			// Move to this child
 | 
|  |   2464 | 			User::LeaveIfError( iEntry.SetEntry( (*selection)[child] ) );
 | 
|  |   2465 | 			
 | 
|  |   2466 | 			TMsvEntry message=iEntry.Entry();
 | 
|  |   2467 | 			
 | 
|  |   2468 | 			// Is this the type we want to change?
 | 
|  |   2469 | 			if (message.iType==aType)
 | 
|  |   2470 | 				{
 | 
|  |   2471 | 				// Add to selection to do bulk change on, if necessary
 | 
|  |   2472 | 				if ((message.Visible() && aInvisible) ||
 | 
|  |   2473 | 					(!message.Visible() && !aInvisible))
 | 
|  |   2474 | 					{
 | 
|  |   2475 | 					folders->AppendL(message.Id());
 | 
|  |   2476 | 					}
 | 
|  |   2477 | 				}
 | 
|  |   2478 | 			
 | 
|  |   2479 | 			// Recurse downwards
 | 
|  |   2480 | 			if (aRecurse && message.iType==KUidMsvFolderEntry)
 | 
|  |   2481 | 				ChangeVisibilityL(message.Id(),aInvisible,aRecurse,aType);
 | 
|  |   2482 | 			}
 | 
|  |   2483 | 
 | 
|  |   2484 | 		// Change its visibility off all children if necessary
 | 
|  |   2485 | 		if (folders->Count())
 | 
|  |   2486 | 			{
 | 
|  |   2487 | 			// Do the change to the invisible flag (actual constant for the
 | 
|  |   2488 | 			// flag we want is private:()
 | 
|  |   2489 | 			
 | 
|  |   2490 | 			User::LeaveIfError( iEntry.SetEntry( aParent ) );
 | 
|  |   2491 | 			User::LeaveIfError( iEntry.ChangeAttributes(*folders,
 | 
|  |   2492 | 								aInvisible?0:KMsvVisibilityAttribute,
 | 
|  |   2493 | 								aInvisible?KMsvVisibilityAttribute:0));
 | 
|  |   2494 | 			}
 | 
|  |   2495 | 		}
 | 
|  |   2496 | 
 | 
|  |   2497 | 	// Release the service entry
 | 
|  |   2498 | 	User::LeaveIfError( iEntry.SetEntry( KMsvNullIndexEntryId ) );
 | 
|  |   2499 | 
 | 
|  |   2500 | 	// Get rid of selection
 | 
|  |   2501 | 	CleanupStack::PopAndDestroy(2);
 | 
|  |   2502 | 	}
 | 
|  |   2503 | 
 | 
|  |   2504 | /**
 | 
|  |   2505 | Propagates invisible flag for unsubscribed folders.
 | 
|  |   2506 | aId has been unsubscribed. If it has no visible child folders then
 | 
|  |   2507 | it is made invisible and its parent checked with the same test
 | 
|  |   2508 | 
 | 
|  |   2509 | @param aId the folder that has been unsubscribed
 | 
|  |   2510 | */
 | 
|  |   2511 | void CImapProtocolController::PropagateInvisibleFlagL(TMsvId aId)
 | 
|  |   2512 | 	{
 | 
|  |   2513 | 	__LOG_FORMAT((KDefaultLog, "PropagateInvisibleFlagL: 0x%x", aId));
 | 
|  |   2514 | 
 | 
|  |   2515 | 	// finish if we've reached the top
 | 
|  |   2516 | 	if (aId == KMsvRootIndexEntryId)
 | 
|  |   2517 | 		{
 | 
|  |   2518 | 		return;
 | 
|  |   2519 | 		}
 | 
|  |   2520 | 	
 | 
|  |   2521 | 	User::LeaveIfError(iEntry.SetEntry(aId));
 | 
|  |   2522 | 
 | 
|  |   2523 | 	// finish if we've reached a service
 | 
|  |   2524 | 	if (iEntry.Entry().iType == KUidMsvServiceEntry)
 | 
|  |   2525 | 		{
 | 
|  |   2526 | 		return;
 | 
|  |   2527 | 		}
 | 
|  |   2528 | 
 | 
|  |   2529 | 	// return if we've found a subscribed folder since we can't make
 | 
|  |   2530 | 	// it invisible
 | 
|  |   2531 | 	if (((TMsvEmailEntry)iEntry.Entry()).LocalSubscription())
 | 
|  |   2532 | 		{
 | 
|  |   2533 | 		return;
 | 
|  |   2534 | 		}
 | 
|  |   2535 | 	
 | 
|  |   2536 | 	// check the children of this unsubscribed folder
 | 
|  |   2537 | 	CMsvEntrySelection* selection=new (ELeave) CMsvEntrySelection;
 | 
|  |   2538 | 	CleanupStack::PushL(selection);
 | 
|  |   2539 | 
 | 
|  |   2540 | 	User::LeaveIfError(iEntry.GetChildren(*selection));
 | 
|  |   2541 | 
 | 
|  |   2542 | 	TBool visible=EFalse;
 | 
|  |   2543 | 	TInt count = selection->Count();
 | 
|  |   2544 | 	for (TInt i=0; i < count; ++i)
 | 
|  |   2545 | 		{
 | 
|  |   2546 | 		User::LeaveIfError(iEntry.SetEntry((*selection)[i]));
 | 
|  |   2547 | 
 | 
|  |   2548 | 		// look for a visible folder
 | 
|  |   2549 | 		TMsvEmailEntry entry = (TMsvEmailEntry)iEntry.Entry();
 | 
|  |   2550 | 		if (entry.iType == KUidMsvFolderEntry && entry.Visible())
 | 
|  |   2551 | 			{
 | 
|  |   2552 | 			visible=ETrue;
 | 
|  |   2553 | 			break;
 | 
|  |   2554 | 			}
 | 
|  |   2555 | 		}
 | 
|  |   2556 | 	
 | 
|  |   2557 | 	CleanupStack::PopAndDestroy(selection);
 | 
|  |   2558 | 
 | 
|  |   2559 | 	// if no child folders were visible then make this folder
 | 
|  |   2560 | 	// invisible and continue up
 | 
|  |   2561 | 	if (!visible)
 | 
|  |   2562 | 		{
 | 
|  |   2563 | 		User::LeaveIfError(iEntry.SetEntry(aId));
 | 
|  |   2564 | 		
 | 
|  |   2565 | 		// make this invisible
 | 
|  |   2566 | 		TMsvEntry entry = iEntry.Entry();
 | 
|  |   2567 | 		entry.SetVisible(EFalse);
 | 
|  |   2568 | 		User::LeaveIfError(iEntry.ChangeEntry(entry));
 | 
|  |   2569 | 
 | 
|  |   2570 | 		// go up
 | 
|  |   2571 | 		PropagateInvisibleFlagL(entry.Parent());
 | 
|  |   2572 | 		}
 | 
|  |   2573 | 	}
 | 
|  |   2574 | 
 | 
|  |   2575 | 
 | 
|  |   2576 | /**
 | 
|  |   2577 | Is this id in the local service?
 | 
|  |   2578 | @param  aId   the id of the entry to check
 | 
|  |   2579 | @return true, if the message id belongs to the local service.
 | 
|  |   2580 | */
 | 
|  |   2581 | TBool CImapProtocolController::IdIsLocalL(TMsvId aId)
 | 
|  |   2582 | 	{
 | 
|  |   2583 | 	return ServiceOfL(aId) == KMsvLocalServiceIndexEntryIdValue;
 | 
|  |   2584 | 	}
 | 
|  |   2585 | 
 | 
|  |   2586 | /**
 | 
|  |   2587 | Returns the id of the service containing this id
 | 
|  |   2588 | @param  aId   the id of the entry to check
 | 
|  |   2589 | @return       the id of the containing service
 | 
|  |   2590 | */
 | 
|  |   2591 | TMsvId CImapProtocolController::ServiceOfL(TMsvId aId)
 | 
|  |   2592 | 	{
 | 
|  |   2593 | 	TMsvId current=aId;
 | 
|  |   2594 | 	while(current!=KMsvRootIndexEntryIdValue)
 | 
|  |   2595 | 		{
 | 
|  |   2596 | 		// Visit this entry
 | 
|  |   2597 | 		User::LeaveIfError(iEntry.SetEntry(current));
 | 
|  |   2598 | 
 | 
|  |   2599 | 		TMsvEmailEntry entry = iEntry.Entry();
 | 
|  |   2600 | 		
 | 
|  |   2601 | 		// if service then searched far enough
 | 
|  |   2602 | 		if (entry.iType==KUidMsvServiceEntry)
 | 
|  |   2603 | 			break;
 | 
|  |   2604 | 
 | 
|  |   2605 | 		// Go upwards
 | 
|  |   2606 | 		current=entry.Parent();
 | 
|  |   2607 | 		}
 | 
|  |   2608 | 
 | 
|  |   2609 | 	return current;
 | 
|  |   2610 |  	}
 | 
|  |   2611 |  	
 | 
|  |   2612 | /**
 | 
|  |   2613 | Processes positive error codes returned by asynchronous service requests.
 | 
|  |   2614 | Specifically, these will be error codes returned by the CImapSession,
 | 
|  |   2615 | indicating error conditions in communication with the remote server.
 | 
|  |   2616 | 
 | 
|  |   2617 | See cimapsessionconsts.h for full definition of error codes, summarised here:
 | 
|  |   2618 | 
 | 
|  |   2619 | KErrImapNo 		 	 IMAP server returned a tagged NO response
 | 
|  |   2620 | KErrImapBad 	 	 IMAP server returned a tagged BAD response
 | 
|  |   2621 | KErrImapClosed		 indicates one of the streams has closed
 | 
|  |   2622 | KErrImapFlushTimeout an attempt to flush a cancelled command has timed out
 | 
|  |   2623 | KErrImapCorrupt		 corrupt data was enountered during parsing of IMAP server data
 | 
|  |   2624 | 
 | 
|  |   2625 | @param  aError - the positive error code received on completion 
 | 
|  |   2626 |                  of an asynchronous service
 | 
|  |   2627 | 
 | 
|  |   2628 | @return ETrue  - if this function has called Complete() due to a fatal error.
 | 
|  |   2629 | 		EFalse - otherwise
 | 
|  |   2630 | */
 | 
|  |   2631 | TBool CImapProtocolController::ProcessError(TInt aError)
 | 
|  |   2632 | 	{
 | 
|  |   2633 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::ProcessError(iCurrentOp = %d, aError = %d)", iCurrentOp, aError));
 | 
|  |   2634 | 	
 | 
|  |   2635 | 	// Bearer mobility support for initially connect failure 
 | 
|  |   2636 | 	if (iMobilityManager && aError == KErrImapConnectError && iImapSessionManager->HasConnection())
 | 
|  |   2637 | 		{
 | 
|  |   2638 | 		// Change migration state, so the connect error can be dealt with, 
 | 
|  |   2639 | 		// using the migration state machine.
 | 
|  |   2640 | 		iMigrateState = EHandlingConnectError;
 | 
|  |   2641 | 
 | 
|  |   2642 | 		SetActive();
 | 
|  |   2643 | 		TRequestStatus* status = &iStatus;
 | 
|  |   2644 | 		User::RequestComplete(status, KErrNone);
 | 
|  |   2645 | 
 | 
|  |   2646 | 		return ETrue;
 | 
|  |   2647 | 		}
 | 
|  |   2648 | 	
 | 
|  |   2649 | 
 | 
|  |   2650 | 	// weed out non-fatal server errors
 | 
|  |   2651 | 	ThranslateSessionError(aError);
 | 
|  |   2652 | 	if (aError == KErrNone)
 | 
|  |   2653 | 		{
 | 
|  |   2654 | 		return EFalse;
 | 
|  |   2655 | 		}
 | 
|  |   2656 | 	
 | 
|  |   2657 | 	if (iForegroundSession>0)
 | 
|  |   2658 | 		{
 | 
|  |   2659 | 		// error has occurred on a secondary session.
 | 
|  |   2660 | 		// This is not fatal to the whole protocol controller's
 | 
|  |   2661 | 		// existance, but it is fatal to the requested operation
 | 
|  |   2662 | 		
 | 
|  |   2663 | 		// get final progress state...
 | 
|  |   2664 | 		if (iCurrentOp==EConnectSecondary)
 | 
|  |   2665 | 			{
 | 
|  |   2666 | 			iImapSessionManager->Progress(iProgress.iGenericProgress);
 | 
|  |   2667 | 			}
 | 
|  |   2668 | 		else
 | 
|  |   2669 | 			{
 | 
|  |   2670 | 			iImapCompound->Progress(iProgress);
 | 
|  |   2671 | 			}
 | 
|  |   2672 | 		
 | 
|  |   2673 | 		//... and update reported error code
 | 
|  |   2674 | 		iProgress.iGenericProgress.iErrorCode=aError;
 | 
|  |   2675 | 		
 | 
|  |   2676 | 		// delete the compound operation object
 | 
|  |   2677 | 		delete iImapCompound;
 | 
|  |   2678 | 		iImapCompound = NULL;
 | 
|  |   2679 | 		
 | 
|  |   2680 | 		// drop the secondary session
 | 
|  |   2681 | 		DropSession(iForegroundSession);
 | 
|  |   2682 | 		
 | 
|  |   2683 | 		// complete the user request with KErrNone..
 | 
|  |   2684 | 		Complete(KErrNone);
 | 
|  |   2685 | 		}
 | 
|  |   2686 | 	else
 | 
|  |   2687 | 		{
 | 
|  |   2688 | 		// DoComplete normally handles the session tidyup, but
 | 
|  |   2689 | 		// is not called if the error has occurred during a background
 | 
|  |   2690 | 		// operation, for example ECancelRecoverPrimary
 | 
|  |   2691 | 		if (iCurrentOp==ECancelRecoverPrimary)
 | 
|  |   2692 | 			{
 | 
|  |   2693 | 			// Non-fatal errors should have been handled prior to this.
 | 
|  |   2694 | 			DisconnectAll();
 | 
|  |   2695 | 	
 | 
|  |   2696 | 			// Save error code in progress and flag the disconnect
 | 
|  |   2697 | 			// this is defensive as the client should not be watching progress
 | 
|  |   2698 | 			iProgress.iGenericProgress.iState=TImap4GenericProgress::EDisconnected;
 | 
|  |   2699 | 			iProgress.iGenericProgress.iErrorCode=aError;
 | 
|  |   2700 | 			}
 | 
|  |   2701 | 		Complete(aError);
 | 
|  |   2702 | 		}
 | 
|  |   2703 | 	return ETrue;
 | 
|  |   2704 | 	}
 | 
|  |   2705 | 
 | 
|  |   2706 | /**
 | 
|  |   2707 | Translates session error codes for reporting to the Server MTM.
 | 
|  |   2708 | KErrImapNo and KErrImapBad are non-fatal to the session, and 
 | 
|  |   2709 | should have been fielded by the compound operation, sync manager
 | 
|  |   2710 | or session manager (during session connect), however they are
 | 
|  |   2711 | translated to KErrNone here.
 | 
|  |   2712 | 
 | 
|  |   2713 | All other session errors are fatal to the connection. If an
 | 
|  |   2714 | error occurs on the primary session, all connected sessions 
 | 
|  |   2715 | should be disconnected and the client completed.
 | 
|  |   2716 | */
 | 
|  |   2717 | void CImapProtocolController::ThranslateSessionError(TInt& errCode)
 | 
|  |   2718 | 	{
 | 
|  |   2719 | 	if ( errCode == KErrNone 
 | 
|  |   2720 | 	  || errCode == KErrImapNo 
 | 
|  |   2721 | 	  || errCode == KErrImapBad )
 | 
|  |   2722 | 		{
 | 
|  |   2723 | 		// No and bad should have been handled by the compound 
 | 
|  |   2724 | 		// operation and are non-fatal to the connection.
 | 
|  |   2725 | 		errCode = KErrNone;
 | 
|  |   2726 | 		}
 | 
|  |   2727 | 	else
 | 
|  |   2728 | 		{
 | 
|  |   2729 | 		errCode = KErrImapServerFail;
 | 
|  |   2730 | 		}
 | 
|  |   2731 | 	}
 | 
|  |   2732 | 
 | 
|  |   2733 | /**
 | 
|  |   2734 | Resets the progress object
 | 
|  |   2735 | */
 | 
|  |   2736 | void CImapProtocolController::ResetProgress()
 | 
|  |   2737 | 	{
 | 
|  |   2738 | 	//initialise the TImap4SyncProgress part
 | 
|  |   2739 | 	iProgress.iSyncProgress.iFoldersToDo = 0;
 | 
|  |   2740 | 	iProgress.iSyncProgress.iFoldersDone = 0;
 | 
|  |   2741 | 	iProgress.iSyncProgress.iMsgsToDo = 0;
 | 
|  |   2742 | 	iProgress.iSyncProgress.iMsgsDone = 0;
 | 
|  |   2743 | 	iProgress.iSyncProgress.iHeadersFetched = 0;
 | 
|  |   2744 | 	iProgress.iSyncProgress.iOrphanedFolders = 0;
 | 
|  |   2745 | 	iProgress.iSyncProgress.iNewFolders = 0;
 | 
|  |   2746 | 	iProgress.iSyncProgress.iOrphanedMessages = 0;
 | 
|  |   2747 | 	iProgress.iSyncProgress.iRemoteMessagesDeleteTagged = 0;
 | 
|  |   2748 | 	iProgress.iSyncProgress.iMessagesFetchedOK = 0;
 | 
|  |   2749 | 	iProgress.iSyncProgress.iMessagePartsFetchedOK = 0;
 | 
|  |   2750 | 	iProgress.iSyncProgress.iMessagePartsNotFound = 0;
 | 
|  |   2751 | 	iProgress.iSyncProgress.iFoldersNotFound = 0;
 | 
|  |   2752 | 	iProgress.iSyncProgress.iErrorCode = KErrNone;	
 | 
|  |   2753 | 	iProgress.iSyncProgress.iType = EImap4SyncProgressType;
 | 
|  |   2754 | 	
 | 
|  |   2755 | 	//initialise the TImap4GenericProgress part
 | 
|  |   2756 | 	iProgress.iGenericProgress.iMsgsToDo = 0;
 | 
|  |   2757 | 	iProgress.iGenericProgress.iMsgsDone = 0;
 | 
|  |   2758 | 	iProgress.iGenericProgress.iPartsToDo = 0;
 | 
|  |   2759 | 	iProgress.iGenericProgress.iPartsDone = 0;
 | 
|  |   2760 | 	iProgress.iGenericProgress.iBytesToDo = 0;
 | 
|  |   2761 | 	iProgress.iGenericProgress.iBytesDone = 0;
 | 
|  |   2762 | 	iProgress.iGenericProgress.iReturnedMsvId = 0;
 | 
|  |   2763 | 	iProgress.iGenericProgress.iTotalSize = 0;
 | 
|  |   2764 | 	iProgress.iGenericProgress.iErrorCode = KErrNone;
 | 
|  |   2765 | 	iProgress.iGenericProgress.iType = EImap4GenericProgressType;
 | 
|  |   2766 | 
 | 
|  |   2767 | 	}
 | 
|  |   2768 | 
 | 
|  |   2769 | /**
 | 
|  |   2770 | Notice that a preferred carrier has become available, and migration to that bearer has been accepted.
 | 
|  |   2771 | The protocol controller shall either pause or allow any current operation to complete
 | 
|  |   2772 | according to the action specified in parameter aAction. Once the current operation 
 | 
|  |   2773 | is paused or complete, the protocol controller shall close any existing sockets
 | 
|  |   2774 | and finally notify the mobility framework that it is ready to migrate to the new
 | 
|  |   2775 | carrier.
 | 
|  |   2776 | 
 | 
|  |   2777 | @param aAction      - indicates the action that should be taken re: current operations
 | 
|  |   2778 | @param aIsSeamless  - indicates if the 
 | 
|  |   2779 | */
 | 
|  |   2780 | void CImapProtocolController::PrepareForNewCarrier(TImMobilityAction aAction, TBool /*aIsSeamless*/)
 | 
|  |   2781 | 	{
 | 
|  |   2782 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::PrepareForNewCarrier(iMigrateState=%d, aAction = %d)", iMigrateState, aAction));
 | 
|  |   2783 | 	// Handle being called in an already-migrating state before handling usual case
 | 
|  |   2784 | 	if (iMigrateState!=ENotMigrating)
 | 
|  |   2785 | 		{
 | 
|  |   2786 | 		switch (iMigrateState)
 | 
|  |   2787 | 			{
 | 
|  |   2788 | 			case EDisconnectingForMigrate:
 | 
|  |   2789 | 			case EWaitingForOpToStop:
 | 
|  |   2790 | 				{
 | 
|  |   2791 | 				// Do not allow change from EWaitingForOpToStop to EWaitingForOpToComplete
 | 
|  |   2792 | 				// but do allow an operation to be stopped suddenly if necessary.
 | 
|  |   2793 | 				if (aAction==KAcceptImmediately)
 | 
|  |   2794 | 					{
 | 
|  |   2795 | 					CarrierLost();
 | 
|  |   2796 | 					iMigrateState = EWaitingForNewCarrier;
 | 
|  |   2797 | 					iMobilityManager->MigrateToNewCarrier();
 | 
|  |   2798 | 		
 | 
|  |   2799 | 					// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   2800 | 					if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   2801 | 						{
 | 
|  |   2802 | 						// Now in a waiting state, set self active
 | 
|  |   2803 | 						iStatus = KRequestPending;
 | 
|  |   2804 | 						SetActive();
 | 
|  |   2805 | 						}
 | 
|  |   2806 | 					}
 | 
|  |   2807 | 				// else already preparing for new carrier, nothing to do.
 | 
|  |   2808 | 				return;
 | 
|  |   2809 | 				}
 | 
|  |   2810 | 
 | 
|  |   2811 | 			case EWaitingForOpToComplete:	// async wait on compound op/bground op/idle controller
 | 
|  |   2812 | 				{
 | 
|  |   2813 | 				// Allow change from EWaitingForOpToComplete to EWaitingForOpToStop
 | 
|  |   2814 | 				// also allow an operation to be stopped suddenly if necessary.
 | 
|  |   2815 | 				if (aAction==KAcceptImmediately)
 | 
|  |   2816 | 					{
 | 
|  |   2817 | 					CarrierLost();
 | 
|  |   2818 | 					iMigrateState = EWaitingForNewCarrier;
 | 
|  |   2819 | 					iMobilityManager->MigrateToNewCarrier();
 | 
|  |   2820 | 		
 | 
|  |   2821 | 					// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   2822 | 					if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   2823 | 						{
 | 
|  |   2824 | 						// Now in a waiting state, set self active
 | 
|  |   2825 | 						iStatus = KRequestPending;
 | 
|  |   2826 | 						SetActive();
 | 
|  |   2827 | 						}
 | 
|  |   2828 | 					}
 | 
|  |   2829 | 				else if (aAction==KAcceptStopCurrent)
 | 
|  |   2830 | 					{
 | 
|  |   2831 | 					// change from EWaitingForOpToComplete to EWaitingForOpToStop
 | 
|  |   2832 | 					StopCurrentForMigrate();
 | 
|  |   2833 | 					}
 | 
|  |   2834 | 				// else already preparing for new carrier, nothing to do.
 | 
|  |   2835 | 				return;
 | 
|  |   2836 | 				}
 | 
|  |   2837 | 			case EHandlingConnectError:
 | 
|  |   2838 | 				{
 | 
|  |   2839 | 				// We have a Connect Error, from previous connect attempt
 | 
|  |   2840 | 				// We are ready to (migrate) reconnect
 | 
|  |   2841 | 				iMigrateState = EWaitingForNewCarrier;
 | 
|  |   2842 | 				iMobilityManager->MigrateToNewCarrier();
 | 
|  |   2843 | 				
 | 
|  |   2844 | 				// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   2845 | 				if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   2846 | 					{
 | 
|  |   2847 | 					// Now in a waiting state, set self active
 | 
|  |   2848 | 					iStatus = KRequestPending;
 | 
|  |   2849 | 					SetActive();
 | 
|  |   2850 | 					}
 | 
|  |   2851 | 				break;
 | 
|  |   2852 | 				}
 | 
|  |   2853 | 			case EConnectingAfterMigrate:	// async wait on session manager
 | 
|  |   2854 | 				{
 | 
|  |   2855 | 				// cancelling in this state tidies up the session array, so
 | 
|  |   2856 | 				// nothing extra to do here - now ready for migration.
 | 
|  |   2857 | 				Cancel();
 | 
|  |   2858 | 				iMigrateState = EWaitingForNewCarrier;
 | 
|  |   2859 | 				iMobilityManager->MigrateToNewCarrier();
 | 
|  |   2860 | 	
 | 
|  |   2861 | 				// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   2862 | 				if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   2863 | 					{
 | 
|  |   2864 | 					// Now in a waiting state, set self active
 | 
|  |   2865 | 					iStatus = KRequestPending;
 | 
|  |   2866 | 					SetActive();
 | 
|  |   2867 | 					}
 | 
|  |   2868 | 				return;				
 | 
|  |   2869 | 				}
 | 
|  |   2870 | 
 | 
|  |   2871 | 			case EWaitingInitialCarrierRejected:	// async wait state on mobility engine
 | 
|  |   2872 | 			case EWaitingForNewCarrier:		// async wait state on mobility engine
 | 
|  |   2873 | 			case EStartingReconnect:		// intermediate state
 | 
|  |   2874 | 				{
 | 
|  |   2875 | 				// already ready and waiting for a new carrier - Cancel dummy request
 | 
|  |   2876 | 				// and tell the Mobility framework we are ready
 | 
|  |   2877 | 				Cancel();
 | 
|  |   2878 | 				iMigrateState = EWaitingForNewCarrier;
 | 
|  |   2879 | 				iMobilityManager->MigrateToNewCarrier();
 | 
|  |   2880 | 	
 | 
|  |   2881 | 				// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   2882 | 				if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   2883 | 					{
 | 
|  |   2884 | 					// Now in a waiting state, set self active
 | 
|  |   2885 | 					iStatus = KRequestPending;
 | 
|  |   2886 | 					SetActive();
 | 
|  |   2887 | 					}
 | 
|  |   2888 | 				return;
 | 
|  |   2889 | 				}
 | 
|  |   2890 | 			case ESuspendingForMigrate:     // intermediate state
 | 
|  |   2891 | 			case ENotMigrating:				// already checked this isn't true
 | 
|  |   2892 | 			default:
 | 
|  |   2893 | 				{
 | 
|  |   2894 | 				__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EProConPreForNewCarBadMigrateState));
 | 
|  |   2895 | 				}
 | 
|  |   2896 | 			}
 | 
|  |   2897 | 		}
 | 
|  |   2898 | 
 | 
|  |   2899 | 	// Do the requested action...
 | 
|  |   2900 | 	switch (aAction)
 | 
|  |   2901 | 		{
 | 
|  |   2902 | 		case KAcceptCompleteCurrent:
 | 
|  |   2903 | 			{
 | 
|  |   2904 | 			// Any current operation shall be allowed to complete prior
 | 
|  |   2905 | 			// to indicating that the server MTM is ready to migrate to
 | 
|  |   2906 | 			// the new bearer.
 | 
|  |   2907 | 			CompleteCurrentForMigrate();
 | 
|  |   2908 | 			break;
 | 
|  |   2909 | 			}
 | 
|  |   2910 | 		case KAcceptStopCurrent:
 | 
|  |   2911 | 			{
 | 
|  |   2912 | 			// Any current operation shall be allowed to continue until
 | 
|  |   2913 | 			// such a point that it may be resumed without re-sending or
 | 
|  |   2914 | 			// re-receiveing a significant amount to data prior to 
 | 
|  |   2915 | 			// indicating that the server MTM is ready to migrate to the 
 | 
|  |   2916 | 			// new bearer.
 | 
|  |   2917 | 			StopCurrentForMigrate();
 | 
|  |   2918 | 			break;
 | 
|  |   2919 | 			}
 | 
|  |   2920 | 		case KAcceptImmediately:
 | 
|  |   2921 | 		default:
 | 
|  |   2922 | 			{
 | 
|  |   2923 | 			// accept immediately is an instruction to immediately suspend any
 | 
|  |   2924 | 			// current operation (cancel any outstanding server communication)
 | 
|  |   2925 | 			// and close any open sockets. This is the same behaviour as required
 | 
|  |   2926 | 			// for a downgrade situation.
 | 
|  |   2927 | 			CarrierLost();
 | 
|  |   2928 | 			iMigrateState = EWaitingForNewCarrier;
 | 
|  |   2929 | 			iMobilityManager->MigrateToNewCarrier();
 | 
|  |   2930 | 
 | 
|  |   2931 | 			// do not set waiting if NewCarrierActive has been called synchronously.
 | 
|  |   2932 | 			if (iMigrateState == EWaitingForNewCarrier)
 | 
|  |   2933 | 				{
 | 
|  |   2934 | 				// Now in a waiting state, set self active
 | 
|  |   2935 | 				iStatus = KRequestPending;
 | 
|  |   2936 | 				SetActive();
 | 
|  |   2937 | 				}
 | 
|  |   2938 | 			break;
 | 
|  |   2939 | 			}
 | 
|  |   2940 | 		} // end switch (aAction)
 | 
|  |   2941 | 	}
 | 
|  |   2942 | 
 | 
|  |   2943 | /**
 | 
|  |   2944 | Configures the protocol controller (PC) to allow any current operation in progress
 | 
|  |   2945 | to complete prior to indicating to the mobility framework that it is ready to
 | 
|  |   2946 | migrate to the new carrier.
 | 
|  |   2947 | 
 | 
|  |   2948 | Note the protocol controller may be in any of the following states
 | 
|  |   2949 |  - IDLE (only one session exists)
 | 
|  |   2950 |  - background sync in progress only (only one session exists)
 | 
|  |   2951 |  - foreground op in progress only (only one session exists)
 | 
|  |   2952 |  - background sync and foreground operation in progress (2 sessions exist)
 | 
|  |   2953 |  - background sync in progress and connecting second session for foreground op
 | 
|  |   2954 | 
 | 
|  |   2955 | */ 	
 | 
|  |   2956 | void CImapProtocolController::CompleteCurrentForMigrate()	
 | 
|  |   2957 | 	{
 | 
|  |   2958 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::CompleteCurrentForMigrate()");
 | 
|  |   2959 | 	// set the migrating flag
 | 
|  |   2960 | 	iMigrateState = EWaitingForOpToComplete;
 | 
|  |   2961 | 	
 | 
|  |   2962 | 	if (BackgroundSyncInProgress())
 | 
|  |   2963 | 		{
 | 
|  |   2964 | 		// 2-phase background sync is always delayed till after migration
 | 
|  |   2965 | 		iBackgroundSyncOp->StopForMigrate();
 | 
|  |   2966 | 		}
 | 
|  |   2967 | 
 | 
|  |   2968 | 	// If no operation in progress, stop the IDLE
 | 
|  |   2969 | 	if (iCurrentOp == EIdle && iImapIdleController->IsActive())
 | 
|  |   2970 | 		{
 | 
|  |   2971 | 		iCurrentOp = EStopIdle;
 | 
|  |   2972 | 		iImapIdleController->StopIdle(iStatus);
 | 
|  |   2973 | 		SetActive();
 | 
|  |   2974 | 		return;
 | 
|  |   2975 | 		}
 | 
|  |   2976 | 
 | 
|  |   2977 | 	// cancel a secondary session connect
 | 
|  |   2978 | 	if (iCurrentOp == EConnectSecondary)
 | 
|  |   2979 | 		{
 | 
|  |   2980 | 		CancelForMigrate();
 | 
|  |   2981 | 		iMigrateState = EWaitingForOpToComplete;
 | 
|  |   2982 | 		
 | 
|  |   2983 | 		// defensive: it is possible that the background sync has completed
 | 
|  |   2984 | 		// while the secondary connect is still in progress. In this case
 | 
|  |   2985 | 		// neither DoRunL() nor BackgroundSyncComplete() will not be called.
 | 
|  |   2986 | 		if (!BackgroundSyncInProgress())
 | 
|  |   2987 | 			{
 | 
|  |   2988 | 			// fake a stop-idle op
 | 
|  |   2989 | 			iCurrentOp = EStopIdle;
 | 
|  |   2990 | 			SetActive();
 | 
|  |   2991 | 			TRequestStatus* status = &iStatus;
 | 
|  |   2992 | 			User::RequestComplete(status, KErrNone);
 | 
|  |   2993 | 			}
 | 
|  |   2994 | 		}
 | 
|  |   2995 | 	}
 | 
|  |   2996 | 
 | 
|  |   2997 | /**
 | 
|  |   2998 | CancelForMigrate() - cancels any outstanding service without deleting the
 | 
|  |   2999 | compound operation or completing the user request.
 | 
|  |   3000 | 
 | 
|  |   3001 | This does not cancel a background sync.
 | 
|  |   3002 | 
 | 
|  |   3003 | iMigrateState must be set to a new state immediately after calling this.
 | 
|  |   3004 | */
 | 
|  |   3005 | void CImapProtocolController::CancelForMigrate()
 | 
|  |   3006 | 	{
 | 
|  |   3007 | 	iMigrateState = ESuspendingForMigrate;
 | 
|  |   3008 | 	Cancel();
 | 
|  |   3009 | 	}
 | 
|  |   3010 | 
 | 
|  |   3011 | /**
 | 
|  |   3012 | */
 | 
|  |   3013 | void CImapProtocolController::DoCancelForMigrate()
 | 
|  |   3014 | 	{
 | 
|  |   3015 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DoCancelForMigrate()");
 | 
|  |   3016 | 	switch (iCurrentOp)
 | 
|  |   3017 | 		{
 | 
|  |   3018 | 		case EConnectSecondary:
 | 
|  |   3019 | 			{
 | 
|  |   3020 | 			// Cancel the connect request
 | 
|  |   3021 | 			iImapSessionManager->Cancel();
 | 
|  |   3022 | 			// Remove the session pointer from the array
 | 
|  |   3023 | 			// The session has already been deleted - see note above.
 | 
|  |   3024 | 			TInt numSessions = iImapSessionArray.Count();
 | 
|  |   3025 | 			iImapSessionArray.Remove(numSessions-1);
 | 
|  |   3026 | 			break;
 | 
|  |   3027 | 			}
 | 
|  |   3028 | 
 | 
|  |   3029 | 		case EIdle:
 | 
|  |   3030 | 		case EStopIdle:
 | 
|  |   3031 | 			{
 | 
|  |   3032 | 			// Cancel the IDLE controller.
 | 
|  |   3033 | 			iImapIdleController->Cancel();
 | 
|  |   3034 | 			break;
 | 
|  |   3035 | 			}
 | 
|  |   3036 | 
 | 
|  |   3037 | 		case ESync:
 | 
|  |   3038 | 		case ESelect:
 | 
|  |   3039 | 		case ECopyToLocal:
 | 
|  |   3040 | 		case ECopyWithinService:
 | 
|  |   3041 | 		case ECopyFromLocal:
 | 
|  |   3042 | 		case EMoveToLocal:
 | 
|  |   3043 | 		case EMoveWithinService:
 | 
|  |   3044 | 		case EMoveFromLocal:
 | 
|  |   3045 | 		case EPopulate:
 | 
|  |   3046 | 		case EDelete:
 | 
|  |   3047 | 		case EDeleteFolder:
 | 
|  |   3048 | 		case ECreate:
 | 
|  |   3049 | 		case ERename:
 | 
|  |   3050 | 			{
 | 
|  |   3051 | 			// Cancel the compound operation
 | 
|  |   3052 | 			iImapCompound->CancelForMigrate();
 | 
|  |   3053 | 			break;
 | 
|  |   3054 | 			}
 | 
|  |   3055 | 
 | 
|  |   3056 | 		case ECancelRecoverPrimary:
 | 
|  |   3057 | 			{
 | 
|  |   3058 | 			// Cancel the session recovery.
 | 
|  |   3059 | 			(iImapSessionArray[0])->Cancel();
 | 
|  |   3060 | 			}
 | 
|  |   3061 | 
 | 
|  |   3062 | 		case EConnect:
 | 
|  |   3063 | //		case EConnectAndSync:
 | 
|  |   3064 | 		case EDisconnect:
 | 
|  |   3065 | 		default:
 | 
|  |   3066 | 			{
 | 
|  |   3067 | 			// nothing to do..
 | 
|  |   3068 | 			break;
 | 
|  |   3069 | 			}
 | 
|  |   3070 | 			
 | 
|  |   3071 | 		} // end of switch (iCurrentOp)
 | 
|  |   3072 | 
 | 
|  |   3073 | 	// Do NOT call CMsgActive::DoCancel()
 | 
|  |   3074 | 	// - the client requested operation is not being cancelled
 | 
|  |   3075 | 	}
 | 
|  |   3076 | 
 | 
|  |   3077 | 
 | 
|  |   3078 | /**
 | 
|  |   3079 | Configures the protocol controller (PC) to stop any current operation in 
 | 
|  |   3080 | progress at the next convenient point - the meaning of this depends on the 
 | 
|  |   3081 | specific compound operations. For example, for simple operations such as 
 | 
|  |   3082 | creating a folder, this will be when the operation has completed but for
 | 
|  |   3083 | operations for which multiple messages are processed in sequence (eg 
 | 
|  |   3084 | fetching several messages), it shall be once the current message has been
 | 
|  |   3085 | processed (eg fetched). At this point the operation shall complete the
 | 
|  |   3086 | protocol controller's iStatus
 | 
|  |   3087 | 
 | 
|  |   3088 | Note the protocol controller may be in any of the following states
 | 
|  |   3089 |  - IDLE (only one session exists)
 | 
|  |   3090 |  - background sync in progress only (only one session exists)
 | 
|  |   3091 |  - foreground op in progress only (only one session exists)
 | 
|  |   3092 |  - background sync and foreground operation in progress (2 sessions exist)
 | 
|  |   3093 |  - background sync in progress and connecting second session for foreground op
 | 
|  |   3094 | 
 | 
|  |   3095 | */ 
 | 
|  |   3096 | void CImapProtocolController::StopCurrentForMigrate()	
 | 
|  |   3097 | 	{
 | 
|  |   3098 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::StopCurrentForMigrate()");
 | 
|  |   3099 | 	// set the migrating flag
 | 
|  |   3100 | 	iMigrateState = EWaitingForOpToStop;
 | 
|  |   3101 | 	
 | 
|  |   3102 | 	if (BackgroundSyncInProgress())
 | 
|  |   3103 | 		{
 | 
|  |   3104 | 		iBackgroundSyncOp->StopForMigrate();
 | 
|  |   3105 | 		}
 | 
|  |   3106 | 	
 | 
|  |   3107 | 	if (iCurrentOp == EIdle && iImapIdleController->IsActive())
 | 
|  |   3108 | 		{
 | 
|  |   3109 | 		// If no operation in progress, stop the IDLE
 | 
|  |   3110 | 		iCurrentOp = EStopIdle;
 | 
|  |   3111 | 		iImapIdleController->StopIdle(iStatus);
 | 
|  |   3112 | 		SetActive();
 | 
|  |   3113 | 		return;
 | 
|  |   3114 | 		}
 | 
|  |   3115 | 	else if (iCurrentOp == EConnectSecondary)
 | 
|  |   3116 | 		{
 | 
|  |   3117 | 		// cancel a secondary session connect
 | 
|  |   3118 | 		Cancel();
 | 
|  |   3119 | 		
 | 
|  |   3120 | 		// defensive: it is possible that the background sync has completed
 | 
|  |   3121 | 		// while the secondary connect is still in progress. In this case
 | 
|  |   3122 | 		// neither DoRunL() nor BackgroundSyncComplete() will not be called.
 | 
|  |   3123 | 		if (!BackgroundSyncInProgress())
 | 
|  |   3124 | 			{
 | 
|  |   3125 | 			// fake a stop-idle op
 | 
|  |   3126 | 			iCurrentOp = EStopIdle;
 | 
|  |   3127 | 			SetActive();
 | 
|  |   3128 | 			TRequestStatus* status = &iStatus;
 | 
|  |   3129 | 			User::RequestComplete(status, KErrNone);
 | 
|  |   3130 | 			}
 | 
|  |   3131 | 		}
 | 
|  |   3132 | 	else if (iCurrentOp != ECancelRecoverPrimary)
 | 
|  |   3133 | 		{
 | 
|  |   3134 | 		// nothing to do for ECancelRecoverPrimary - just wait for the
 | 
|  |   3135 | 		// session to flush.
 | 
|  |   3136 | 		// all other operations are told to stop:
 | 
|  |   3137 | 		iImapCompound->StopForMigrate();		
 | 
|  |   3138 | 		}
 | 
|  |   3139 | 	}		
 | 
|  |   3140 | 
 | 
|  |   3141 | /**
 | 
|  |   3142 | This API is called by the Bearer Mobility Manager. It is typically called in the 
 | 
|  |   3143 | case that a downgrade is occuring, and the original sockets are no longer valid
 | 
|  |   3144 | for use. It may also be called if an immediate migration to an preferred bearer is
 | 
|  |   3145 | required, without graceful closing of the original sockets.
 | 
|  |   3146 | 
 | 
|  |   3147 | Any operations are cancelled immediately using the CancelForMigrate() API. This
 | 
|  |   3148 | cancels the operations in such a way that they may be restarted following migration
 | 
|  |   3149 | to a new carrier.
 | 
|  |   3150 | */
 | 
|  |   3151 | void CImapProtocolController::CarrierLost()
 | 
|  |   3152 | 	{
 | 
|  |   3153 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::CarrierLost(iMigrateState=%d)", iMigrateState));
 | 
|  |   3154 | 
 | 
|  |   3155 | 	// Handle being called in an already-migrating state before handling usual case
 | 
|  |   3156 | 	if (iMigrateState!=ENotMigrating)
 | 
|  |   3157 | 		{
 | 
|  |   3158 | 		switch (iMigrateState)
 | 
|  |   3159 | 			{
 | 
|  |   3160 | 			case EWaitingForOpToStop:
 | 
|  |   3161 | 			case EWaitingForOpToComplete:
 | 
|  |   3162 | 				{
 | 
|  |   3163 | 				// break to default behaviour
 | 
|  |   3164 | 				break;
 | 
|  |   3165 | 				}
 | 
|  |   3166 | 			
 | 
|  |   3167 | 			case EStartingReconnect:		// intermediate state
 | 
|  |   3168 | 			case EDisconnectingForMigrate:
 | 
|  |   3169 | 			case EConnectingAfterMigrate:
 | 
|  |   3170 | 				{
 | 
|  |   3171 | 				// cancel the disconnect/connect, then break to default behaviour
 | 
|  |   3172 | 				// (calling CancelForMigrate() shouldn't do anything as any compound
 | 
|  |   3173 | 				// operations will not themselves be active)
 | 
|  |   3174 | 				Cancel();
 | 
|  |   3175 | 				break;
 | 
|  |   3176 | 				}
 | 
|  |   3177 | 				
 | 
|  |   3178 | 			case EHandlingConnectError:
 | 
|  |   3179 | 				{
 | 
|  |   3180 | 				// empty the session array
 | 
|  |   3181 | 				TInt numSessions = iImapSessionArray.Count();
 | 
|  |   3182 | 				for (TInt i=0; i<numSessions; ++i)
 | 
|  |   3183 | 					{
 | 
|  |   3184 | 					if (iImapSessionArray[i])
 | 
|  |   3185 | 						{
 | 
|  |   3186 | 						iImapSessionManager->Disconnect(*(iImapSessionArray[i]));
 | 
|  |   3187 | 						}
 | 
|  |   3188 | 					}
 | 
|  |   3189 | 				iImapSessionArray.ResetAndDestroy();
 | 
|  |   3190 | 
 | 
|  |   3191 | 				// Set the migration state:
 | 
|  |   3192 | 				iMigrateState = EWaitingForNewCarrier;
 | 
|  |   3193 | 				
 | 
|  |   3194 | 				// Now in an waiting state, set self active
 | 
|  |   3195 | 				iStatus = KRequestPending;
 | 
|  |   3196 | 				SetActive();
 | 
|  |   3197 | 				return;
 | 
|  |   3198 | 				}
 | 
|  |   3199 | 					
 | 
|  |   3200 | 			case EWaitingInitialCarrierRejected:
 | 
|  |   3201 | 			case EWaitingForNewCarrier:
 | 
|  |   3202 | 				{
 | 
|  |   3203 | 				// already ready and waiting for a new carrier - nothing to do.
 | 
|  |   3204 | 				return;
 | 
|  |   3205 | 				}
 | 
|  |   3206 | 			
 | 
|  |   3207 | 			case ESuspendingForMigrate:     // intermediate state
 | 
|  |   3208 | 			case ENotMigrating:				// normal state
 | 
|  |   3209 | 			default:
 | 
|  |   3210 | 				{
 | 
|  |   3211 | 				__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EProConKillCurrentBadMigrateState));
 | 
|  |   3212 | 				break;
 | 
|  |   3213 | 				}
 | 
|  |   3214 | 			}
 | 
|  |   3215 | 		}
 | 
|  |   3216 | 
 | 
|  |   3217 | 
 | 
|  |   3218 | 	// stop any background operation
 | 
|  |   3219 | 	if (iBackgroundSyncOp)
 | 
|  |   3220 | 		{
 | 
|  |   3221 | 		iBackgroundSyncOp->CancelForMigrate();
 | 
|  |   3222 | 		}
 | 
|  |   3223 | 
 | 
|  |   3224 | 	// Cancel foreground operations
 | 
|  |   3225 | 	CancelForMigrate();
 | 
|  |   3226 | 		
 | 
|  |   3227 | 	// delete the imap idle controller - this will be re-created on reconnect.
 | 
|  |   3228 | 	delete iImapIdleController;
 | 
|  |   3229 | 	iImapIdleController=NULL;
 | 
|  |   3230 | 		
 | 
|  |   3231 | 	// Drop connection on each of the imap sessions
 | 
|  |   3232 | 	TInt numSessions = iImapSessionArray.Count();
 | 
|  |   3233 | 	for (TInt i=0; i<numSessions; ++i)
 | 
|  |   3234 | 		{
 | 
|  |   3235 | 		if (iImapSessionArray[i])
 | 
|  |   3236 | 			{
 | 
|  |   3237 | 			iImapSessionManager->Disconnect(*(iImapSessionArray[i]));
 | 
|  |   3238 | 			}
 | 
|  |   3239 | 		}
 | 
|  |   3240 | 
 | 
|  |   3241 | 	// empty the session array
 | 
|  |   3242 | 	iImapSessionArray.ResetAndDestroy();
 | 
|  |   3243 | 	
 | 
|  |   3244 | 	// Set the migration state:
 | 
|  |   3245 | 	iMigrateState = EWaitingForNewCarrier;
 | 
|  |   3246 | 	
 | 
|  |   3247 | 	// Now in an waiting state, set self active
 | 
|  |   3248 | 	iStatus = KRequestPending;
 | 
|  |   3249 | 	SetActive();
 | 
|  |   3250 | 	}
 | 
|  |   3251 | 	
 | 
|  |   3252 | /**
 | 
|  |   3253 | Called to indicate the migration has completed and the RConnection is ready to
 | 
|  |   3254 | provide new sockets via the new bearer.
 | 
|  |   3255 | 
 | 
|  |   3256 | Initiates the creation of a new IMAP session, following which any suspended
 | 
|  |   3257 | operation shall be restarted.
 | 
|  |   3258 | */
 | 
|  |   3259 | void CImapProtocolController::NewCarrierActive(TAccessPointInfo /*aNewAp*/, TBool /*aIsSeamless*/)
 | 
|  |   3260 | 	{
 | 
|  |   3261 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::NewCarrierActive()");
 | 
|  |   3262 | 	__ASSERT_DEBUG((iMigrateState == EWaitingForNewCarrier || iMigrateState == EWaitingInitialCarrierRejected),
 | 
|  |   3263 | 	               TImapServerPanic::ImapPanic(TImapServerPanic::ENewCarrierActiveUnexpectedMigrateState));
 | 
|  |   3264 | 
 | 
|  |   3265 | 	// Cancel the dummy active state
 | 
|  |   3266 | 	Cancel();
 | 
|  |   3267 | 
 | 
|  |   3268 | 	// set the new migration state
 | 
|  |   3269 | 	iMigrateState = EStartingReconnect;
 | 
|  |   3270 | 
 | 
|  |   3271 | 	// complete self - this requires some memory allocation, do it within the RunL.
 | 
|  |   3272 | 	TRequestStatus* status = &iStatus;
 | 
|  |   3273 | 	User::RequestComplete(status, KErrNone);
 | 
|  |   3274 | 	SetActive();	
 | 
|  |   3275 | 	}
 | 
|  |   3276 | 
 | 
|  |   3277 | 	
 | 
|  |   3278 | void CImapProtocolController::NewPrimarySessionL()
 | 
|  |   3279 | 	{
 | 
|  |   3280 | 	// Create the primary session pointer
 | 
|  |   3281 | 	CImapSession* imapSession = NULL;
 | 
|  |   3282 | 	iImapSessionArray.AppendL(imapSession);
 | 
|  |   3283 | 
 | 
|  |   3284 | 	// Request the session manager to connect the session
 | 
|  |   3285 | 	iImapSessionManager->GetSessionL(iStatus, iImapSessionArray[0]);
 | 
|  |   3286 | 	iMigrateState = EConnectingAfterMigrate;
 | 
|  |   3287 | 
 | 
|  |   3288 | 	SetActive();
 | 
|  |   3289 | 	}
 | 
|  |   3290 | 	
 | 
|  |   3291 | /**
 | 
|  |   3292 | Indicates that the RConnection is no longer valid.
 | 
|  |   3293 | Therefore disconnect and mark the service as offline.
 | 
|  |   3294 | */
 | 
|  |   3295 | #ifdef __IMAP_LOGGING
 | 
|  |   3296 | void CImapProtocolController::MobilityError(TUint aError)
 | 
|  |   3297 | #else //__IMAP_LOGGING
 | 
|  |   3298 | void CImapProtocolController::MobilityError(TUint /*aError*/)
 | 
|  |   3299 | #endif //__IMAP_LOGGING
 | 
|  |   3300 | 	{
 | 
|  |   3301 | 	__LOG_FORMAT((KDefaultLog, "CImapProtocolController::MobilityError(iMigrateState=%d, aError=%d)", iMigrateState, aError));
 | 
|  |   3302 | 	
 | 
|  |   3303 | 	// Cancel any async request
 | 
|  |   3304 | 	Cancel();
 | 
|  |   3305 | 	
 | 
|  |   3306 | 	if (iRequestedOp != EIdle)
 | 
|  |   3307 | 		{
 | 
|  |   3308 | 		// Complete the user request - calls DisconnectAll()
 | 
|  |   3309 | 		Complete(KErrDisconnected);
 | 
|  |   3310 | 		}
 | 
|  |   3311 | 	else
 | 
|  |   3312 | 		{
 | 
|  |   3313 | 		// Disconnect all sessions and mark the service as offline
 | 
|  |   3314 | 		DisconnectAll();
 | 
|  |   3315 | 		}
 | 
|  |   3316 | 	
 | 
|  |   3317 | 	// the RConnection is no longer valid - delete the session manager
 | 
|  |   3318 | 	// (will be recreated on ConnectL())
 | 
|  |   3319 | 	delete iImapSessionManager;
 | 
|  |   3320 | 	iImapSessionManager = NULL;
 | 
|  |   3321 | 	
 | 
|  |   3322 | 	// no longer migrating...
 | 
|  |   3323 | 	iMigrateState = ENotMigrating;
 | 
|  |   3324 | 
 | 
|  |   3325 | 	// Save error code in progress and flag the disconnect
 | 
|  |   3326 | 	// this is defensive as the client should not be watching progress
 | 
|  |   3327 | 	iProgress.iGenericProgress.iState=TImap4GenericProgress::EDisconnected;
 | 
|  |   3328 | 	iProgress.iGenericProgress.iErrorCode=KErrDisconnected;
 | 
|  |   3329 | 	}
 | 
|  |   3330 | 
 | 
|  |   3331 | void CImapProtocolController::ProcessOpCompleteForMigrate()
 | 
|  |   3332 | 	{
 | 
|  |   3333 | 	// Any tidying up to do for the current user-requested operation
 | 
|  |   3334 | 	switch (iCurrentOp)
 | 
|  |   3335 | 		{
 | 
|  |   3336 | 		case ECancelRecoverPrimary:
 | 
|  |   3337 | 		case EIdle:
 | 
|  |   3338 | 		case EStopIdle:
 | 
|  |   3339 | 			{
 | 
|  |   3340 | 			// engine was IDLE or recovering from a cancel when the 
 | 
|  |   3341 | 			// migrate notice arrived... nothing to do before disconnecting.
 | 
|  |   3342 | 			break;
 | 
|  |   3343 | 			}
 | 
|  |   3344 | 
 | 
|  |   3345 | 		case ESync:
 | 
|  |   3346 | 		case ESelect:
 | 
|  |   3347 | 		case ECopyToLocal:
 | 
|  |   3348 | 		case ECopyWithinService:
 | 
|  |   3349 | 		case ECopyFromLocal:
 | 
|  |   3350 | 		case EMoveToLocal:
 | 
|  |   3351 | 		case EMoveWithinService:
 | 
|  |   3352 | 		case EMoveFromLocal:
 | 
|  |   3353 | 		case EPopulate:
 | 
|  |   3354 | 		case EDelete:
 | 
|  |   3355 | 		case EDeleteFolder:
 | 
|  |   3356 | 		case ECreate:
 | 
|  |   3357 | 		case ERename:
 | 
|  |   3358 | 			{
 | 
|  |   3359 | 			// update last operation progress state
 | 
|  |   3360 | 			iImapCompound->Progress(iProgress);
 | 
|  |   3361 | 			
 | 
|  |   3362 | 			// if the user requested operation has finished, 
 | 
|  |   3363 | 			// tidyup and inform the client 
 | 
|  |   3364 | 			if (iProgress.iGenericProgress.iState == TImap4GenericProgress::EIdle)
 | 
|  |   3365 | 				{
 | 
|  |   3366 | 				delete iImapCompound;
 | 
|  |   3367 | 				iImapCompound = NULL;
 | 
|  |   3368 | 		
 | 
|  |   3369 | 				// Complete the server mtm request.
 | 
|  |   3370 | 				Complete(iStatus.Int());
 | 
|  |   3371 | 				}
 | 
|  |   3372 | 			break;
 | 
|  |   3373 | 			}
 | 
|  |   3374 | 
 | 
|  |   3375 | 		case EConnect:
 | 
|  |   3376 | 		case EDisconnect:
 | 
|  |   3377 | 		case EConnectSecondary:
 | 
|  |   3378 | 		default:
 | 
|  |   3379 | 			{
 | 
|  |   3380 | 			__ASSERT_DEBUG(EFalse, TImapServerPanic::ImapPanic(TImapServerPanic::EProcessOpCompleteForMigrateUnexpectedState));
 | 
|  |   3381 | 			}
 | 
|  |   3382 | 		} // end of switch (iCurrentOp)
 | 
|  |   3383 | 	}
 | 
|  |   3384 | 
 | 
|  |   3385 | /**
 | 
|  |   3386 | Logs out and disconnects all connected sessions with the remote server.
 | 
|  |   3387 | */
 | 
|  |   3388 | void CImapProtocolController::DisconnectForMigrateL()
 | 
|  |   3389 | 	{
 | 
|  |   3390 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::DisconnectForMigrateL()");
 | 
|  |   3391 | 	__ASSERT_DEBUG(iMigrateCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::EMigrateCompoundIsNotNull));
 | 
|  |   3392 | 	
 | 
|  |   3393 | 	// Background operations will have been taken care of already - just disconnect.
 | 
|  |   3394 | 	// Do not perform the late-delete offline operations.
 | 
|  |   3395 | 	delete iMigrateCompound;
 | 
|  |   3396 | 	iMigrateCompound = NULL;
 | 
|  |   3397 | 	
 | 
|  |   3398 | 	iMigrateCompound = CImapCompoundDisconnect::NewL( *iImapSyncManager, 
 | 
|  |   3399 | 												      iEntry, 
 | 
|  |   3400 | 												      *iImapSettings,
 | 
|  |   3401 | 												      *iImapSessionManager,
 | 
|  |   3402 | 												      *iImapMailStore,
 | 
|  |   3403 | 												      iImapSessionArray,
 | 
|  |   3404 | 												      iImapOfflineControl,
 | 
|  |   3405 | 												      EFalse );
 | 
|  |   3406 | 
 | 
|  |   3407 | 	iMigrateState = EDisconnectingForMigrate;
 | 
|  |   3408 | 	iMigrateCompound->StartOperation(iStatus, *iImapSessionArray[0]);
 | 
|  |   3409 | 	SetActive();	
 | 
|  |   3410 | 	}
 | 
|  |   3411 | 
 | 
|  |   3412 | 
 | 
|  |   3413 | /**
 | 
|  |   3414 | Resumes operations that were stopped to allow migration to occur,
 | 
|  |   3415 | or operations that were requested while migration was in progress.
 | 
|  |   3416 | */
 | 
|  |   3417 | void CImapProtocolController::RestartAfterMigrateL()
 | 
|  |   3418 | 	{
 | 
|  |   3419 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::RestartAfterMigrateL()");
 | 
|  |   3420 | 	
 | 
|  |   3421 | 	// The migration has completed. Restart anything that was going on
 | 
|  |   3422 | 	// before the migration started, or has been requested in the meantime.
 | 
|  |   3423 | 	iMigrateState = ENotMigrating;
 | 
|  |   3424 | 	
 | 
|  |   3425 | 	// was the initial carrier rejected during the connect operation?
 | 
|  |   3426 | 	// if so, mark as online and get the final connection progress info.
 | 
|  |   3427 | 	if (iCurrentOp == EConnect)
 | 
|  |   3428 | 		{
 | 
|  |   3429 | 		TRAP_IGNORE(MarkOnOrOfflineL(ETrue));
 | 
|  |   3430 | 
 | 
|  |   3431 | 		// Collect the final connect progress information		
 | 
|  |   3432 | 		iImapSessionManager->Progress(iProgress.iGenericProgress);
 | 
|  |   3433 | 
 | 
|  |   3434 | 		// Set last socket activity timeout to iMtmData1. This is used by Imcm.
 | 
|  |   3435 | 		User::LeaveIfError( iEntry.SetEntry( iServiceId ) );
 | 
|  |   3436 | 		TMsvEntry entry=iEntry.Entry();
 | 
|  |   3437 | 		entry.SetMtmData1(iImapSessionManager->LastSocketActivityTimeout());
 | 
|  |   3438 | 		User::LeaveIfError( iEntry.ChangeEntry( entry ) );
 | 
|  |   3439 | 				
 | 
|  |   3440 | 		// complete the connect request
 | 
|  |   3441 | 		Complete(iStatus.Int());		
 | 
|  |   3442 | 		}
 | 
|  |   3443 | 	
 | 
|  |   3444 | 	// Create a new IDLE controller - the old one was deleted.
 | 
|  |   3445 | 	delete iImapIdleController;
 | 
|  |   3446 | 	iImapIdleController=NULL;
 | 
|  |   3447 | 	iImapIdleController = CImapIdleController::NewL(*this, iImapSessionArray[0], *iImapSyncManager, iEntry, *iImapSettings, *iImapMailStore);
 | 
|  |   3448 | 
 | 
|  |   3449 | 	//	was there a background sync in progress prior to migration?
 | 
|  |   3450 | 	if (iBackgroundSyncOp)
 | 
|  |   3451 | 		{
 | 
|  |   3452 | 		// restart any background operation, using the new primary session.
 | 
|  |   3453 | 		iBackgroundSyncOp->ResumeOperationL(*iImapSessionArray[0]);
 | 
|  |   3454 | 		
 | 
|  |   3455 | 		// was there a forground operation paused as well?
 | 
|  |   3456 | 		if (iImapCompound)
 | 
|  |   3457 | 			{
 | 
|  |   3458 | 			// Create a second connected session.
 | 
|  |   3459 | 			iCurrentOp = EConnectSecondary;
 | 
|  |   3460 | 			// iRequestedOp should not have been changed...
 | 
|  |   3461 | 			CImapSession* imapSession = NULL;
 | 
|  |   3462 | 			iImapSessionArray.AppendL(imapSession);
 | 
|  |   3463 | 			TInt sessionCount = iImapSessionArray.Count();
 | 
|  |   3464 | 			iImapSessionManager->GetSessionL(iStatus, iImapSessionArray[sessionCount-1]);
 | 
|  |   3465 | 			SetActive();
 | 
|  |   3466 | 			}
 | 
|  |   3467 | 		else
 | 
|  |   3468 | 			{
 | 
|  |   3469 | 			iCurrentOp = EIdle;
 | 
|  |   3470 | 			}
 | 
|  |   3471 | 		return;
 | 
|  |   3472 | 		}
 | 
|  |   3473 | 
 | 
|  |   3474 | 	if (iImapCompound)
 | 
|  |   3475 | 		{
 | 
|  |   3476 | 		// Idle has not been restarted after the migration, so the requested 
 | 
|  |   3477 | 		// operation can be re-started without calling StopIdle()
 | 
|  |   3478 | 		// resume the suspended operation
 | 
|  |   3479 | 		iCurrentOp = iRequestedOp;
 | 
|  |   3480 | 		iImapCompound->ResumeOperationL(iStatus, *iImapSessionArray[0]);
 | 
|  |   3481 | 		SetActive();		
 | 
|  |   3482 | 		}
 | 
|  |   3483 | 	else
 | 
|  |   3484 | 		{
 | 
|  |   3485 | 		// otherwise just start Idle
 | 
|  |   3486 | 		iCurrentOp = EIdle;
 | 
|  |   3487 | 		iRequestedOp = EIdle;
 | 
|  |   3488 | 		StartIdle();
 | 
|  |   3489 | 		}
 | 
|  |   3490 | 	}
 | 
|  |   3491 | 
 | 
|  |   3492 | /**
 | 
|  |   3493 | Returns a packaged copy of the current progress for passing to the
 | 
|  |   3494 | mobility policy plugin when a preferred carrier available notice
 | 
|  |   3495 | is received.
 | 
|  |   3496 | */
 | 
|  |   3497 | const TDesC8& CImapProtocolController::MobilityProgress()
 | 
|  |   3498 | 	{
 | 
|  |   3499 | 	Progress();
 | 
|  |   3500 | 	iProgressBuffer = TImap4ProgressBuf(iProgress);
 | 
|  |   3501 | 	return iProgressBuffer;
 | 
|  |   3502 | 	}
 | 
|  |   3503 | /**
 | 
|  |   3504 | Updates  the specified messages read/unread status from the remote server.
 | 
|  |   3505 | @param aStatus
 | 
|  |   3506 | */	
 | 
|  |   3507 | EXPORT_C void CImapProtocolController::UpdateFlagL( TRequestStatus& aStatus)
 | 
|  |   3508 |  
 | 
|  |   3509 | 	{
 | 
|  |   3510 | 	__LOG_TEXT(KDefaultLog, "CImapProtocolController::UpdateFlagL()");
 | 
|  |   3511 | 	__ASSERT_DEBUG(iImapCompound==NULL, TImapServerPanic::ImapPanic(TImapServerPanic::ECreateCompoundIsNotNull));
 | 
|  |   3512 | 	ResetProgress();
 | 
|  |   3513 | 	if (!CompleteIfBackgroundOpInProgress(aStatus))	
 | 
|  |   3514 | 		{
 | 
|  |   3515 | 		iImapCompound = CImapUpdateFlagOperation::NewL(*iImapSyncManager,
 | 
|  |   3516 | 												   iEntry,
 | 
|  |   3517 | 												   *iImapSettings
 | 
|  |   3518 | 												   );
 | 
|  |   3519 | 		iRequestedOp = EUpdateFlag;
 | 
|  |   3520 | 		StartPrimaryOperation();
 | 
|  |   3521 | 		Queue(aStatus);
 | 
|  |   3522 | 		SetActive();
 | 
|  |   3523 | 		}
 | 
|  |   3524 | 	}
 | 
|  |   3525 | 	
 | 
|  |   3526 | 
 |