|
1 // Copyright (c) 2006-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 #define _MSVAPI_DONT_INCLUDE_FLOGGER_ |
|
17 |
|
18 #include <e32std.h> |
|
19 |
|
20 #include "POPSMTM.H" |
|
21 |
|
22 #include "POPSMBX.H" |
|
23 #include "POPS.H" |
|
24 #include "POPSOFFL.H" |
|
25 #include <iapprefs.h> |
|
26 // panics |
|
27 #include "POPS.PAN" |
|
28 |
|
29 #include <pop3set.h> |
|
30 #include <miutset.h> // internet mail settings |
|
31 #include <miuthdr.h> |
|
32 #include <offop.h> |
|
33 #include <commdb.h> |
|
34 #include <pop3cmds.h> |
|
35 #include <imcvutil.h> |
|
36 #include <cemailaccounts.h> |
|
37 #include <tmsvsystemprogress.h> |
|
38 |
|
39 #include "msventry.h" // CMsvServerEntry |
|
40 #include "POPSMTM.H" |
|
41 #include "POPS.H" |
|
42 #include "POPSOFFL.H" |
|
43 #include "iapprefs.h" |
|
44 #include "PopsDele.h" |
|
45 #include "POPSRFSH.h" |
|
46 #include "PopsCpMv.h" |
|
47 #include "PopsTopPop.h" |
|
48 #include "cpopsessionmanager.h" |
|
49 #include "imutcon.h" |
|
50 #include "cimmobilitymanager.h" |
|
51 #include "mobilitytestmtmapi.h" |
|
52 |
|
53 const TUid KUidPop3ServerMtm = {0x10003C77}; |
|
54 |
|
55 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
56 #include "cpopupsresponsewaiter.h" |
|
57 #endif |
|
58 |
|
59 // |
|
60 // factory function |
|
61 // |
|
62 EXPORT_C CImppServerMtm* CImppServerMtm::NewL(CRegisteredMtmDll& aPopServerMtmDll, |
|
63 CMsvServerEntry* aEntry) |
|
64 { |
|
65 CImppServerMtm* popServerMtm=new CImppServerMtm(aPopServerMtmDll, aEntry); |
|
66 if (popServerMtm==NULL) |
|
67 { |
|
68 aPopServerMtmDll.ReleaseLibrary(); |
|
69 User::Leave(KErrNoMemory); |
|
70 } |
|
71 CleanupStack::PushL(popServerMtm); |
|
72 popServerMtm->ConstructL(); |
|
73 CleanupStack::Pop(); |
|
74 return popServerMtm; |
|
75 } |
|
76 |
|
77 |
|
78 // |
|
79 void CImppServerMtm::CopyFromLocalL(const CMsvEntrySelection& /*aSelection*/, TMsvId/* aDestination*/, TRequestStatus& /*aStatus*/) |
|
80 { |
|
81 User::Leave(KErrNotSupported); |
|
82 } |
|
83 |
|
84 // |
|
85 // IMPPCPMV |
|
86 // |
|
87 void CImppServerMtm::CopyToLocalL(const CMsvEntrySelection& aSelection, |
|
88 TMsvId aDestination, |
|
89 TRequestStatus& aStatus) |
|
90 { |
|
91 if (AcceptingOfflineOperationsL(aSelection)) |
|
92 { |
|
93 AddOfflineOperationL(aSelection, aDestination, CImOffLineOperation::EOffLineOpCopyToLocal, aStatus); |
|
94 } |
|
95 else if (iMigrationState!=ENotMigrating && !iState.iRunningOfflineOperations) |
|
96 { |
|
97 // do not accept new operations if currently migrating |
|
98 User::Leave(KErrServerBusy); |
|
99 } |
|
100 else |
|
101 { |
|
102 DoCopyMoveL( aSelection, aDestination, aStatus, EImppCopy); |
|
103 } |
|
104 } |
|
105 |
|
106 void CImppServerMtm::MoveToLocalL(const CMsvEntrySelection& aSelection,TMsvId aDestination, TRequestStatus& aStatus) |
|
107 { |
|
108 if (AcceptingOfflineOperationsL(aSelection)) |
|
109 { |
|
110 AddOfflineOperationL(aSelection, aDestination, CImOffLineOperation::EOffLineOpMoveToLocal, aStatus); |
|
111 } |
|
112 else if (iMigrationState!=ENotMigrating && !iState.iRunningOfflineOperations) |
|
113 { |
|
114 // do not accept new operations if currently migrating |
|
115 User::Leave(KErrServerBusy); |
|
116 } |
|
117 else |
|
118 { |
|
119 DoCopyMoveL( aSelection, aDestination, aStatus, EImppMove); |
|
120 } |
|
121 } |
|
122 |
|
123 // |
|
124 // IMPPDELE |
|
125 // |
|
126 void CImppServerMtm::DeleteAllL(const CMsvEntrySelection& aSelection, TRequestStatus& aStatus) |
|
127 { |
|
128 if (iMigrationState!=ENotMigrating && !iState.iRunningOfflineOperations) |
|
129 { |
|
130 // do not accept new operations if currently migrating |
|
131 User::Leave(KErrServerBusy); |
|
132 } |
|
133 |
|
134 if (PruneMessages(aSelection, aStatus)) |
|
135 { |
|
136 // Was this call to DeleteAllL an instruction to delete local parts of a message ? |
|
137 // If so then we don't need to continue. |
|
138 return; |
|
139 } |
|
140 |
|
141 if (iPopSettings == 0) |
|
142 { |
|
143 GetPopDetailsL(aSelection); |
|
144 } |
|
145 |
|
146 |
|
147 if ((iPopSettings->DisconnectedUserMode()) && (!iState.iQuitting)) |
|
148 // If we are in disconnected mode (although not necessarily disconnected) |
|
149 // and we are not quitting then add the delete as an offline operation. |
|
150 { |
|
151 AddOfflineOperationL(aSelection, 0, CImOffLineOperation::EOffLineOpDelete, aStatus); |
|
152 } |
|
153 else |
|
154 // If we are not in disconnected mode or we are quitting then do the delete now. |
|
155 { |
|
156 __ASSERT_DEBUG(iConnectedToPopMbox, Panic(EPopNotConnectedToMbox)); |
|
157 |
|
158 if(iConnectedToPopMbox==EFalse) |
|
159 { |
|
160 TRAP_IGNORE( DoShowMessagesL( EFalse ) ); |
|
161 User::Leave(KErrDisconnected); |
|
162 } |
|
163 __ASSERT_DEBUG(iState.iCurrentOperation==EPopConnectedAndIdle,Panic(EImppAlreadyActive)); |
|
164 |
|
165 if(iState.iCurrentOperation!=EPopConnectedAndIdle) |
|
166 { |
|
167 User::Leave(KErrInUse); |
|
168 } |
|
169 |
|
170 iReportStatus=&aStatus; |
|
171 Cancel(); |
|
172 ResetProgress(); |
|
173 |
|
174 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
175 // make sure iServerEntry is set to the service entry |
|
176 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
177 |
|
178 CMsvEntrySelection* sel=StripInvalidEntriesLC(aSelection); |
|
179 // set selected entries invisible (hopefully so they wont be selected twice) |
|
180 TInt err=iServerEntry->ChangeAttributes( *sel, 0, KMsvVisibilityAttribute); |
|
181 if (err) |
|
182 { |
|
183 iServerEntry->ChangeAttributes( *sel,KMsvVisibilityAttribute,0); |
|
184 User::Leave(err); |
|
185 } |
|
186 delete iPopDelete; |
|
187 iPopDelete=NULL; |
|
188 iPopDelete=CImPop3Delete::NewL(*iServerEntry,*sel,iPopSession, iServiceId); |
|
189 CleanupStack::PopAndDestroy(); //sel |
|
190 iPopDelete->Start(iStatus); |
|
191 SetActive(); |
|
192 aStatus = KRequestPending; |
|
193 iOperationActive=ETrue; |
|
194 iState.iCurrentOperation=EPopDeleting; |
|
195 } |
|
196 } |
|
197 |
|
198 void CImppServerMtm::CopyWithinServiceL(const CMsvEntrySelection& aSelection,TMsvId aDestination, TRequestStatus& aStatus) |
|
199 { |
|
200 if (aDestination == iServiceId) |
|
201 // If the service id is given as the destination then the message selection is populated. |
|
202 { |
|
203 if (AcceptingOfflineOperationsL(aSelection)) |
|
204 { |
|
205 AddOfflineOperationL(aSelection, aDestination, CImOffLineOperation::EOffLineOpCopyWithinService, aStatus); |
|
206 } |
|
207 else if (iMigrationState!=ENotMigrating && !iState.iRunningOfflineOperations) |
|
208 { |
|
209 // do not accept new operations if currently migrating |
|
210 User::Leave(KErrServerBusy); |
|
211 } |
|
212 else |
|
213 { |
|
214 DoCopyMoveL( aSelection, 0 /*ignored when populating*/, aStatus, EImppPopulate); |
|
215 } |
|
216 } |
|
217 else |
|
218 { |
|
219 User::Leave(KErrNotSupported); |
|
220 } |
|
221 } |
|
222 |
|
223 void CImppServerMtm::CreateL(TMsvEntry/* aNewEntry*/, TRequestStatus& /*aStatus*/) |
|
224 { |
|
225 User::Leave(KErrNotSupported); |
|
226 } |
|
227 |
|
228 void CImppServerMtm::ChangeL(TMsvEntry aNewEntry, TRequestStatus& aStatus) |
|
229 { |
|
230 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
231 User::LeaveIfError(iServerEntry->SetEntry( aNewEntry.Id() )); |
|
232 User::LeaveIfError(iServerEntry->ChangeEntry( aNewEntry )); |
|
233 |
|
234 TRequestStatus* status = &aStatus; |
|
235 User::RequestComplete(status, KErrNone); |
|
236 } |
|
237 |
|
238 void CImppServerMtm::MoveFromLocalL(const CMsvEntrySelection& /*aSelection*/,TMsvId /*aDestination*/, TRequestStatus& /*aStatus*/) |
|
239 { |
|
240 User::Leave(KErrNotSupported); |
|
241 } |
|
242 |
|
243 void CImppServerMtm::MoveWithinServiceL(const CMsvEntrySelection& /*aSelection*/,TMsvId /*aDestination*/, TRequestStatus& /*aStatus*/) |
|
244 { |
|
245 User::Leave(KErrNotSupported); |
|
246 } |
|
247 |
|
248 // |
|
249 // Connect and refresh mailbox or quit |
|
250 // |
|
251 void CImppServerMtm::StartCommandL(CMsvEntrySelection& aSelection, TInt aCommand, const TDesC8& aParameter, TRequestStatus& aStatus) |
|
252 { |
|
253 |
|
254 if (iMigrationState!=ENotMigrating && aCommand!=KPOP3MTMDisconnect && !iState.iRunningOfflineOperations) |
|
255 { |
|
256 // do not accept new operations (except disconnect) if currently migrating |
|
257 User::Leave(KErrServerBusy); |
|
258 } |
|
259 |
|
260 switch(aCommand) |
|
261 { |
|
262 case KPOP3MTMConnect: // KPop3MtmConnectUID |
|
263 DoConnectL(aStatus, aSelection); |
|
264 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopConnecting); |
|
265 break; |
|
266 case KPOP3MTMDisconnect: |
|
267 DoQuitL(aStatus); |
|
268 break; |
|
269 case KPOP3MTMCancelOfflineOperations: |
|
270 if (iPopSettings == 0) |
|
271 { |
|
272 GetPopDetailsL(aSelection); |
|
273 } |
|
274 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopCancellingOfflineOps); |
|
275 CancelOfflineOperationsL(aSelection, aStatus); |
|
276 break; |
|
277 case KPOP3MTMPopulate: |
|
278 { |
|
279 GetPopDetailsL(aSelection); |
|
280 // unpackage the destination from aParameter |
|
281 TImPop3PopulateOptions info; |
|
282 TImPop3PopulateOptions::UnpackL(aParameter,info); |
|
283 DoTopPopulateL(aSelection,info.PopulationLimit(),aStatus); |
|
284 } |
|
285 break; |
|
286 |
|
287 case KPOP3MTMIsConnected: |
|
288 default: |
|
289 User::Leave(KErrNotSupported); |
|
290 break; |
|
291 } |
|
292 } |
|
293 |
|
294 // |
|
295 // |
|
296 // |
|
297 void CImppServerMtm::DoConnectL(TRequestStatus& aStatus, CMsvEntrySelection& aSelection) |
|
298 { |
|
299 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
300 if(IsActive()) |
|
301 { |
|
302 User::Leave(KErrPop3ServerAlreadyConnected); |
|
303 } |
|
304 iNotConnectToPopMailBox = EFalse ; |
|
305 // set this here so progress can be set |
|
306 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
307 iState.iCurrentOperation = EPopAuthoriseAndConnect; |
|
308 #else |
|
309 iState.iCurrentOperation = EPopConnecting; |
|
310 #endif |
|
311 ResetProgress(); |
|
312 // POP3 settings |
|
313 // attempt to open POP3 service settings leave if we cant |
|
314 GetPopDetailsL(aSelection); |
|
315 |
|
316 delete iMessagesToKeep; |
|
317 iMessagesToKeep = NULL; |
|
318 iMessagesToKeep = aSelection.CopyL(); |
|
319 |
|
320 iReportStatus=&aStatus; |
|
321 |
|
322 // Clear the new attribute on all entries if we are connecting |
|
323 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
324 CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection; |
|
325 CleanupStack::PushL(selection); |
|
326 User::LeaveIfError(iServerEntry->GetChildren(*selection)); |
|
327 User::LeaveIfError(iServerEntry->ChangeAttributes(*selection, 0, KMsvNewAttribute)); |
|
328 CleanupStack::PopAndDestroy(); // selection |
|
329 |
|
330 // create session manager |
|
331 if (!iSessionManager) |
|
332 { |
|
333 iSessionManager = CPopSessionManager::NewL(); |
|
334 } |
|
335 |
|
336 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
337 // Connect to UPS server and check if connection to remote server is permitted. |
|
338 iWaiter->AuthoriseAndConnectL(iPopSettings, iClientThreadId, iHasCapability, iStatus); |
|
339 #else |
|
340 // obtain a connected pop session |
|
341 iSessionManager->GetSessionL(*iPopSettings, *iIAPPreferences, iPopSession, iStatus); |
|
342 #endif |
|
343 iOperationActive=ETrue; |
|
344 SetActive(); |
|
345 aStatus = KRequestPending; |
|
346 } |
|
347 |
|
348 |
|
349 void CImppServerMtm::ResetProgress() |
|
350 { |
|
351 iPopProgress.iTotalMsgs=0; |
|
352 iPopProgress.iMsgsToProcess=0; |
|
353 iPopProgress.iBytesDone=0; |
|
354 iPopProgress.iTotalBytes=0; |
|
355 iPopProgress.iErrorCode=KErrNone; |
|
356 |
|
357 iPopProgressBuf.Zero(); |
|
358 } |
|
359 |
|
360 // utlity method - check state of mailbox and make sure it's raeady |
|
361 void CImppServerMtm::CheckMailboxStateL() |
|
362 { |
|
363 __ASSERT_DEBUG(iConnectedToPopMbox, Panic(EPopNotConnectedToMbox)); |
|
364 if(!iConnectedToPopMbox) |
|
365 { |
|
366 TRAP_IGNORE( DoShowMessagesL( EFalse ) ); |
|
367 User::Leave(KErrDisconnected); |
|
368 } |
|
369 __ASSERT_DEBUG(iState.iCurrentOperation==EPopConnectedAndIdle,Panic(EImppAlreadyActive)); |
|
370 if(iState.iCurrentOperation!=EPopConnectedAndIdle) |
|
371 { |
|
372 User::Leave(KErrInUse); |
|
373 } |
|
374 } |
|
375 |
|
376 |
|
377 // |
|
378 // Do the refresh |
|
379 // |
|
380 void CImppServerMtm::DoRefreshL() |
|
381 { |
|
382 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
383 ResetProgress(); |
|
384 delete iMsvIdArray; |
|
385 iMsvIdArray=NULL; |
|
386 iMsvIdArray=new(ELeave)CArrayFixFlat<TMsvId>(8); |
|
387 // context of entry should be set to service entry |
|
388 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
389 delete iPopRefreshMailbox; |
|
390 iPopRefreshMailbox=NULL; |
|
391 iPopRefreshMailbox = CImPop3RefreshMailBox::NewL(*iServerEntry, *iPopSession, iServerEntry->FileSession()); |
|
392 iPopRefreshMailbox->SetMessagesToKeepL(iMessagesToKeep); |
|
393 iPopRefreshMailbox->Start(iStatus,iMsvIdArray); |
|
394 iOperationActive=ETrue; |
|
395 SetActive(); |
|
396 iState.iCurrentOperation=EPopRefreshing; |
|
397 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopRefreshing); |
|
398 } |
|
399 |
|
400 void CImppServerMtm::DoCopyMoveL(const CMsvEntrySelection& aSelection, TMsvId aDestination, TRequestStatus& aStatus, TImppCopyMethod aCopyMethod) |
|
401 { |
|
402 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
403 CheckMailboxStateL(); |
|
404 |
|
405 Cancel(); |
|
406 iReportStatus=&aStatus; |
|
407 ResetProgress(); |
|
408 |
|
409 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
410 CMsvEntrySelection* sel=StripInvalidEntriesLC(aSelection); |
|
411 |
|
412 |
|
413 if( aCopyMethod == EImppMove) |
|
414 { |
|
415 // set selected entries invisible (hopefully so they wont be selected twice) |
|
416 TInt err=iServerEntry->ChangeAttributes(*sel, 0, KMsvVisibilityAttribute); |
|
417 if (err) |
|
418 { |
|
419 iServerEntry->ChangeAttributes(*sel,KMsvVisibilityAttribute,0); |
|
420 User::Leave(err); |
|
421 } |
|
422 } |
|
423 delete iPopCopyMove; |
|
424 iPopCopyMove=NULL; |
|
425 |
|
426 if (aCopyMethod == EImppPopulate) |
|
427 { |
|
428 iPopCopyMove = CImPop3CopyMove::NewL(*sel,*iServerEntry,iPopSession,ETrue,iServerEntry->FileSession(), iLogMessage, iPopSettings->DisconnectedUserMode()); |
|
429 } |
|
430 else |
|
431 { |
|
432 iPopCopyMove = CImPop3CopyMove::NewL(*sel,*iServerEntry,iPopSession,(aCopyMethod == EImppCopy),iServerEntry->FileSession(),aDestination, iLogMessage, iPopSettings->DisconnectedUserMode()); |
|
433 } |
|
434 |
|
435 CleanupStack::PopAndDestroy(); //sel |
|
436 |
|
437 switch (aCopyMethod) |
|
438 { |
|
439 case EImppCopy: |
|
440 iState.iCurrentOperation = EPopCopying; |
|
441 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopCopying); |
|
442 break; |
|
443 case EImppMove: |
|
444 iState.iCurrentOperation = EPopMoving; |
|
445 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopMoving); |
|
446 break; |
|
447 case EImppPopulate: |
|
448 iState.iCurrentOperation = EPopPopulating; |
|
449 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopPopulating); |
|
450 break; |
|
451 default: |
|
452 User::Leave(KErrNotSupported); |
|
453 break; |
|
454 }; |
|
455 |
|
456 iPopCopyMove->StartL(iStatus); |
|
457 |
|
458 SetActive(); |
|
459 aStatus = KRequestPending; |
|
460 iOperationActive = ETrue; |
|
461 } |
|
462 |
|
463 void CImppServerMtm::DoTopPopulateL(const CMsvEntrySelection& aSelection, TInt aLimit, TRequestStatus& aStatus) |
|
464 { |
|
465 // Deletion of service entry from entrySelection which is added at client |
|
466 CMsvEntrySelection* sel=StripInvalidEntriesLC(aSelection); |
|
467 if(sel->At(0) == iServiceId) |
|
468 { |
|
469 sel->Delete(0); |
|
470 } |
|
471 |
|
472 if ( aLimit==KErrNotFound ) |
|
473 { |
|
474 // A full populate is required |
|
475 DoCopyMoveL(*sel,sel->At(0),aStatus,EImppPopulate); |
|
476 CleanupStack::PopAndDestroy(sel); |
|
477 return; |
|
478 } |
|
479 |
|
480 CheckMailboxStateL(); |
|
481 |
|
482 Cancel(); |
|
483 iReportStatus=&aStatus; |
|
484 ResetProgress(); |
|
485 |
|
486 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
487 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
488 |
|
489 RArray<TUint> sizes; |
|
490 CleanupClosePushL(sizes); |
|
491 |
|
492 TInt count=sel->Count(); |
|
493 |
|
494 for(TInt i=0;i<count;i++) |
|
495 { |
|
496 User::LeaveIfError(sizes.Append(iPopRefreshMailbox->RemoteMessageSizeL(sel->At(i)))); |
|
497 } |
|
498 |
|
499 delete iPopTopPop; |
|
500 iPopTopPop=NULL; |
|
501 |
|
502 iPopTopPop = CImPop3TopPopulate::NewL(*sel,*iServerEntry,aLimit,iPopSession,iServerEntry->FileSession(), iLogMessage, iPopSettings->DisconnectedUserMode(),sizes); |
|
503 CleanupStack::Pop(&sizes); |
|
504 |
|
505 CleanupStack::PopAndDestroy(sel); |
|
506 iState.iCurrentOperation = EPopTopPopulating; |
|
507 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopTopPopulating); |
|
508 iPopTopPop->StartL(iStatus); |
|
509 SetActive(); |
|
510 aStatus = KRequestPending; |
|
511 iOperationActive = ETrue; |
|
512 } |
|
513 |
|
514 // |
|
515 // quit |
|
516 // |
|
517 void CImppServerMtm::DoQuitL(TRequestStatus& aStatus) |
|
518 { |
|
519 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
520 iReportStatus=&aStatus; |
|
521 |
|
522 // delete the mobility manager - we don't want to migrate during a disconnect |
|
523 delete iMobilityManager; |
|
524 iMobilityManager = NULL; |
|
525 |
|
526 if (!iConnectedToPopMbox) |
|
527 { |
|
528 aStatus=KRequestPending; |
|
529 CommandComplete(KErrNone); |
|
530 return; |
|
531 } |
|
532 Cancel(); |
|
533 // set connected to false immed. on calling QUIT |
|
534 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
535 TMsvEntry entry = iServerEntry->Entry(); |
|
536 entry.SetConnected( EFalse ); |
|
537 User::LeaveIfError(iServerEntry->ChangeEntry(entry)); |
|
538 iState.iQuitting = ETrue; |
|
539 |
|
540 if (iMigrationState != ENotMigrating && |
|
541 iMigrationState != EWaitingForOpToComplete && |
|
542 iMigrationState != EWaitingForOpToStop) |
|
543 { |
|
544 iMigrationState = ENotMigrating; |
|
545 iState.iCurrentOperation=EPopQuitting; |
|
546 ResetProgress(); |
|
547 TRequestStatus *pS = &iStatus; |
|
548 User::RequestComplete(pS,KErrNone); |
|
549 SetActive(); |
|
550 return; |
|
551 } |
|
552 |
|
553 if(iState.iCurrentOperation != EPopConnectedAndIdle) // stopping in mid operation so just die |
|
554 { |
|
555 SetActive(); |
|
556 iState.iCurrentOperation=EPopDisconnected; |
|
557 ResetProgress(); |
|
558 TRequestStatus *pS = &iStatus; |
|
559 User::RequestComplete(pS,KErrNone); |
|
560 } |
|
561 else // quit gracefully |
|
562 { |
|
563 // Run any pending delete operations. |
|
564 // The quit operation will be started after this operation has completed. |
|
565 FindFirstOfflineOperationL(ETrue); |
|
566 } |
|
567 aStatus = KRequestPending; |
|
568 } |
|
569 |
|
570 // |
|
571 // Report some progess |
|
572 // |
|
573 const TDesC8& CImppServerMtm::Progress() |
|
574 { |
|
575 GetProgress(); |
|
576 |
|
577 iPopProgressBuf=TPop3ProgressBuf(iPopProgress); |
|
578 return iPopProgressBuf; |
|
579 } |
|
580 |
|
581 /** |
|
582 Obtain the progress information for POPS MTM |
|
583 */ |
|
584 void CImppServerMtm::GetProgress() |
|
585 { |
|
586 TBool progress = EFalse; |
|
587 TInt progressError; |
|
588 if (iState.iRunningOfflineOperations) |
|
589 { |
|
590 const CImPop3OfflineOperationFinder::TOperationDetails operationDetails = iOfflineOpFinder->OperationDetails(); |
|
591 |
|
592 switch (operationDetails.iOpType) |
|
593 { |
|
594 case CImOffLineOperation::EOffLineOpCopyToLocal: |
|
595 case CImOffLineOperation::EOffLineOpCopyWithinService: |
|
596 case CImOffLineOperation::EOffLineOpMoveToLocal: |
|
597 if (iPopCopyMove) |
|
598 { |
|
599 iPopProgress = iPopCopyMove->Progress(); |
|
600 } |
|
601 break; |
|
602 case CImOffLineOperation::EOffLineOpDelete: |
|
603 iPopProgress.iPop3Progress = TPop3Progress::EPopDeleting; |
|
604 break; |
|
605 default: |
|
606 break; |
|
607 } |
|
608 |
|
609 iPopProgress.iMsgsToProcess = operationDetails.iOperationsOfType - (operationDetails.iOperationNumber + 1); |
|
610 iPopProgress.iTotalMsgs = operationDetails.iOperationsOfType; |
|
611 } |
|
612 else |
|
613 { |
|
614 TPopsMtmState state; |
|
615 // If there has been an error which has cause disconnection then we are interested |
|
616 // in the state that caused the failure rather than the Disconnected state. Therefore |
|
617 // we need to report the iState.ILastCurrentOperation in this case. |
|
618 if ((iPopProgress.iErrorCode != KErrNone) && (iState.iCurrentOperation == EPopDisconnected)) |
|
619 { |
|
620 state = iState.iLastCurrentOperation; |
|
621 } |
|
622 else |
|
623 { |
|
624 state = iState.iCurrentOperation; |
|
625 } |
|
626 |
|
627 switch(state) |
|
628 { |
|
629 case EPopAuthoriseAndConnect: |
|
630 { |
|
631 iPopProgress.iPop3Progress = TPop3Progress::EPopConnecting; |
|
632 iPopProgress.iTotalMsgs = KErrNotFound; |
|
633 iPopProgress.iTotalBytes = KErrNotFound; |
|
634 break; |
|
635 } |
|
636 |
|
637 case EPopConnecting: |
|
638 { |
|
639 iPopProgress.iPop3Progress = TPop3Progress::EPopConnecting; |
|
640 |
|
641 // Check that session manager exists and get the progress information |
|
642 // from it if it does. |
|
643 // Under some circumstances the session manager might have been deleted |
|
644 // such as when a the networking bearer mobility framework has indicated |
|
645 // an error that means the RConnection is invalid. |
|
646 if (iSessionManager) |
|
647 { |
|
648 iSessionManager->ConnectionProgress(iPopProgress); |
|
649 } |
|
650 else |
|
651 { |
|
652 iPopProgress.iTotalMsgs = KErrNotFound; |
|
653 iPopProgress.iTotalBytes = KErrNotFound; |
|
654 } |
|
655 break; |
|
656 } |
|
657 |
|
658 case EPopFindingFirstOfflineOp: |
|
659 iPopProgress.iPop3Progress = TPop3Progress::EPopConnecting; |
|
660 break; |
|
661 case EPopRefreshing: |
|
662 progressError = iPopProgress.iErrorCode; |
|
663 if(progressError != KErrNone) |
|
664 { |
|
665 progress = ETrue; |
|
666 } |
|
667 if(iPopRefreshMailbox!=NULL) |
|
668 { |
|
669 iPopProgress=iPopRefreshMailbox->Progress(); |
|
670 } |
|
671 if(progress) |
|
672 { |
|
673 iPopProgress.iErrorCode = progressError; |
|
674 } |
|
675 iPopProgress.iPop3Progress = TPop3Progress::EPopRefreshing; |
|
676 break; |
|
677 case EPopTidying: |
|
678 if(iPopRefreshMailbox!=NULL) |
|
679 { |
|
680 iPopProgress=iPopRefreshMailbox->Progress(); |
|
681 } |
|
682 iPopProgress.iPop3Progress = TPop3Progress::EPopRefreshing; |
|
683 break; |
|
684 case EPopConnectedAndIdle: |
|
685 if (iState.iLastCurrentOperation==EPopAddingOfflineOp || iState.iLastCurrentOperation==EPopCancellingOfflineOps) |
|
686 { |
|
687 iOfflineOpSetter->Progress(iPopProgress); |
|
688 } |
|
689 if (iState.iLastCurrentOperation==EPopPopulating || iState.iLastCurrentOperation==EPopMoving || iState.iLastCurrentOperation==EPopCopying ) |
|
690 { |
|
691 if(iPopCopyMove) |
|
692 { |
|
693 iPopProgress=iPopCopyMove->Progress(); |
|
694 } |
|
695 else |
|
696 { |
|
697 iPopProgress.iMsgsToProcess = 0; |
|
698 } |
|
699 } |
|
700 break; |
|
701 case EPopCopying: |
|
702 if(iPopCopyMove) |
|
703 { |
|
704 iPopProgress=iPopCopyMove->Progress(); |
|
705 } |
|
706 iPopProgress.iPop3Progress = TPop3Progress::EPopCopying; |
|
707 break; |
|
708 case EPopPopulating: |
|
709 if(iPopCopyMove) |
|
710 { |
|
711 iPopProgress=iPopCopyMove->Progress(); |
|
712 } |
|
713 iPopProgress.iPop3Progress = TPop3Progress::EPopPopulating; |
|
714 break; |
|
715 case EPopTopPopulating: |
|
716 if(iPopTopPop) |
|
717 { |
|
718 iPopProgress=iPopTopPop->Progress(); |
|
719 } |
|
720 iPopProgress.iPop3Progress = TPop3Progress::EPopTopPopulating; |
|
721 break; |
|
722 case EPopMoving: |
|
723 if(iPopCopyMove) |
|
724 { |
|
725 iPopProgress=iPopCopyMove->Progress(); |
|
726 } |
|
727 iPopProgress.iPop3Progress = TPop3Progress::EPopMoving; |
|
728 break; |
|
729 case EPopDeleting: |
|
730 if(iPopDelete) |
|
731 { |
|
732 iPopProgress=iPopDelete->Progress(); |
|
733 } |
|
734 iPopProgress.iPop3Progress = TPop3Progress::EPopDeleting; |
|
735 break; |
|
736 case EPopQuitting: |
|
737 iPopProgress.iPop3Progress = TPop3Progress::EPopDisconnecting; |
|
738 break; |
|
739 case EPopDisconnected: |
|
740 iPopProgress.iPop3Progress = TPop3Progress::EPopDisconnected; |
|
741 break; |
|
742 case EPopAddingOfflineOp: |
|
743 case EPopCancellingOfflineOps: |
|
744 iOfflineOpSetter->Progress(iPopProgress); |
|
745 break; |
|
746 default: |
|
747 break; |
|
748 } |
|
749 |
|
750 if ((state != EPopConnecting || state != EPopAuthoriseAndConnect) && iPopProgress.iMsgsToProcess > iPopProgress.iTotalMsgs) |
|
751 { |
|
752 iPopProgress.iMsgsToProcess = iPopProgress.iTotalMsgs; |
|
753 } |
|
754 |
|
755 if (iPopProgress.iMsgsToProcess<0) |
|
756 { |
|
757 iPopProgress.iMsgsToProcess = 0; |
|
758 } |
|
759 } |
|
760 iPopProgress.iServiceId = iServiceId; |
|
761 } |
|
762 |
|
763 /** |
|
764 This call leads to calling GetProgress() to populate the TPop3Progress structure. |
|
765 @param aOutSysProg The TMsvSystemProgress structure to be populated |
|
766 */ |
|
767 void CImppServerMtm::GetSystemProgress(TMsvSystemProgress& aOutSysProg) |
|
768 { |
|
769 GetProgress(); |
|
770 aOutSysProg.iErrorCode = iPopProgress.iErrorCode; |
|
771 } |
|
772 |
|
773 /** |
|
774 The extension method provides a polymorphic behaviour to call the correct |
|
775 MTM. |
|
776 @param aExtensionId The Uid passed in as KUIDMsgMsvSystemProgress to obtain the |
|
777 System Progress. |
|
778 @return KErrNone if GetSystemProgress is called successfully. |
|
779 */ |
|
780 TInt CImppServerMtm::Extension_(TUint aExtensionId, TAny *&a0, TAny *a1) |
|
781 { |
|
782 switch(aExtensionId) |
|
783 { |
|
784 case KUIDMsgMsvSystemProgress: |
|
785 { |
|
786 TMsvSystemProgress* systemProgress = reinterpret_cast<TMsvSystemProgress*>(a1); |
|
787 GetSystemProgress(*systemProgress); |
|
788 return KErrNone; |
|
789 } |
|
790 |
|
791 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
792 case KUIDMsgClientThreadInfo: |
|
793 { |
|
794 iClientThreadId = *(TThreadId*) (a1); |
|
795 iHasCapability = (TBool)*(TInt*)(a0); |
|
796 return KErrNone; |
|
797 } |
|
798 #endif |
|
799 |
|
800 case KUidMsgNonOperationMtmData: |
|
801 { |
|
802 TNonOperationMtmDataType* mtmDataType = reinterpret_cast<TNonOperationMtmDataType*>(a0); |
|
803 TPtrC8* mtmDataBuffer = reinterpret_cast<TPtrC8*>(a1); |
|
804 return GetNonOperationMtmData(*mtmDataType, *mtmDataBuffer); |
|
805 } |
|
806 |
|
807 default: |
|
808 { |
|
809 // Chain to base class |
|
810 return CBaseServerMtm::Extension_(aExtensionId, a0, a1); |
|
811 } |
|
812 } |
|
813 } |
|
814 |
|
815 // |
|
816 // return current state of connection? |
|
817 // |
|
818 TBool CImppServerMtm::CommandExpected() |
|
819 { |
|
820 return iConnectedToPopMbox; |
|
821 } |
|
822 |
|
823 // |
|
824 // Special cancel for migration purposes. |
|
825 // Stops the current operation without completing the user/client request. |
|
826 // The cancelled operation may then be restarted once migration to a new |
|
827 // bearer has completed. |
|
828 // |
|
829 void CImppServerMtm::CancelToMigrate() |
|
830 { |
|
831 iCancelForBMMigration = ETrue; |
|
832 Cancel(); |
|
833 iCancelForBMMigration = EFalse; |
|
834 } |
|
835 |
|
836 // |
|
837 // Implements the Cancel(). Unless called via the special method for handling |
|
838 // cancelling for migration (above), calling DoCancel will cancel the user |
|
839 // requested operation, delete the pop session, mark the server offline and |
|
840 // complete the user request if outstanding. |
|
841 // |
|
842 // If called via the special method, the server is not marked offline, and |
|
843 // user requests are not completed. |
|
844 // |
|
845 void CImppServerMtm::DoCancel() |
|
846 { |
|
847 // Cancel current outstanding request according to current state... |
|
848 switch (iMigrationState) |
|
849 { |
|
850 case ENotMigrating: |
|
851 case EWaitingForOpToStop: |
|
852 case EWaitingForOpToComplete: |
|
853 { |
|
854 // Cancels the current operation according to iState.iCurrentOperation |
|
855 // If cancelling for bearer migration, operations are able to be resumed. |
|
856 DoCancelCurrentOp(); |
|
857 break; |
|
858 } |
|
859 case EDisconnectingForMigrate: |
|
860 case EConnectingAfterMigrate: |
|
861 { |
|
862 // Cancel the connect/disconnect on the session manager |
|
863 iSessionManager->Cancel(); |
|
864 break; |
|
865 } |
|
866 case EWaitingForNewCarrier: |
|
867 case EWaitingCarrierRejected: |
|
868 { |
|
869 // self-induced dummy wait state on the mobility manager |
|
870 // Cancel it: |
|
871 TRequestStatus* status = &iStatus; |
|
872 User::RequestComplete(status, KErrCancel); |
|
873 break; |
|
874 } |
|
875 default: |
|
876 { |
|
877 break; |
|
878 } |
|
879 } |
|
880 |
|
881 // Final tidying for non-migration caused cancels |
|
882 if (!iCancelForBMMigration) |
|
883 { |
|
884 if(iState.iCurrentOperation != EPopConnectedAndIdle) |
|
885 { |
|
886 iState.iCurrentOperation = EPopDisconnected; |
|
887 TRAP_IGNORE(DoShowMessagesL( EFalse ) ); |
|
888 |
|
889 // delete the mobility manager |
|
890 delete iMobilityManager; |
|
891 iMobilityManager = NULL; |
|
892 |
|
893 TInt err = iServerEntry->SetEntry(iServiceId); |
|
894 if (err == KErrNone) |
|
895 { |
|
896 TMsvEntry entry = iServerEntry->Entry(); |
|
897 entry.SetConnected( EFalse ); |
|
898 iServerEntry->ChangeEntry( entry ); // ignore any error |
|
899 } |
|
900 } |
|
901 |
|
902 if(iOperationActive) |
|
903 { |
|
904 // Complete the client request now |
|
905 CommandComplete(KErrCancel); |
|
906 } |
|
907 } |
|
908 } |
|
909 |
|
910 |
|
911 /** |
|
912 Cancel according to iState.iCurrentOperation |
|
913 |
|
914 If the cancel is to allow a migration, the operation object in use |
|
915 is cancelled, but not deleted. This means it is possible to restart it |
|
916 later. |
|
917 */ |
|
918 void CImppServerMtm::DoCancelCurrentOp() |
|
919 { |
|
920 switch(iState.iCurrentOperation) |
|
921 { |
|
922 case EPopAuthoriseAndConnect: |
|
923 { |
|
924 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
925 iWaiter->Cancel(); |
|
926 #endif |
|
927 break; |
|
928 } |
|
929 |
|
930 case EPopDisconnected: |
|
931 case EPopTidying: // self completed state |
|
932 { |
|
933 break; |
|
934 } |
|
935 case EPopConnecting: |
|
936 case EPopQuitting: |
|
937 { |
|
938 __ASSERT_ALWAYS(iSessionManager, Panic(EPopNullPointer)); |
|
939 iSessionManager->Cancel(); |
|
940 break; |
|
941 } |
|
942 case EPopConnectedAndIdle: |
|
943 { |
|
944 __ASSERT_ALWAYS(iPopSession, Panic(EPopNullPointer)); |
|
945 iPopSession->Cancel(); |
|
946 break; |
|
947 } |
|
948 case EPopRefreshing: |
|
949 { |
|
950 if (iCancelForBMMigration) |
|
951 { |
|
952 iPopRefreshMailbox->CancelAllowResume(); |
|
953 } |
|
954 else |
|
955 { |
|
956 iPopRefreshMailbox->Cancel(); |
|
957 } |
|
958 delete iPopSession; |
|
959 iPopSession = NULL; |
|
960 break; |
|
961 } |
|
962 case EPopCopying: |
|
963 case EPopMoving: |
|
964 case EPopPopulating: |
|
965 { |
|
966 if (iCancelForBMMigration) |
|
967 { |
|
968 iPopCopyMove->CancelAllowResume(); |
|
969 } |
|
970 else |
|
971 { |
|
972 delete iPopCopyMove; |
|
973 iPopCopyMove=NULL; |
|
974 } |
|
975 delete iPopSession; |
|
976 iPopSession = NULL; |
|
977 break; |
|
978 } |
|
979 case EPopTopPopulating: |
|
980 { |
|
981 if (iCancelForBMMigration) |
|
982 { |
|
983 iPopTopPop->CancelAllowResume(); |
|
984 } |
|
985 else |
|
986 { |
|
987 delete iPopTopPop; |
|
988 iPopTopPop=NULL; |
|
989 } |
|
990 delete iPopSession; |
|
991 iPopSession = NULL; |
|
992 break; |
|
993 } |
|
994 case EPopDeleting: |
|
995 { |
|
996 if (iCancelForBMMigration) |
|
997 { |
|
998 iPopDelete->CancelAllowResume(); |
|
999 } |
|
1000 else |
|
1001 { |
|
1002 delete iPopDelete; |
|
1003 iPopDelete=NULL; |
|
1004 } |
|
1005 delete iPopSession; |
|
1006 iPopSession = NULL; |
|
1007 break; |
|
1008 } |
|
1009 case EPopAddingOfflineOp: |
|
1010 { |
|
1011 iOfflineOpSetter->Cancel(); |
|
1012 break; |
|
1013 } |
|
1014 case EPopFindingFirstOfflineOp: |
|
1015 { |
|
1016 iOfflineOpFinder->Cancel(); |
|
1017 break; |
|
1018 } |
|
1019 case EPopCancellingOfflineOps: |
|
1020 { |
|
1021 if (iCancelForBMMigration) |
|
1022 { |
|
1023 // RJS: update this Cancel() to enable resume |
|
1024 iOfflineOpSetter->Cancel(); |
|
1025 } |
|
1026 else |
|
1027 { |
|
1028 iOfflineOpSetter->Cancel(); |
|
1029 } |
|
1030 break; |
|
1031 } |
|
1032 } |
|
1033 } |
|
1034 |
|
1035 // |
|
1036 // |
|
1037 // |
|
1038 void CImppServerMtm::DoRunL() |
|
1039 { |
|
1040 TInt err = KErrNone; |
|
1041 TInt eCode=iStatus.Int(); |
|
1042 iState.iLastCurrentOperation = iState.iCurrentOperation; |
|
1043 TBool quitSuccessfully = EFalse; |
|
1044 TPop3Progress progress; |
|
1045 |
|
1046 if (iMigrationState != ENotMigrating && |
|
1047 iMigrationState != EWaitingForOpToComplete && |
|
1048 iMigrationState != EWaitingForOpToStop) |
|
1049 { |
|
1050 if (DoMigrationRunL()) |
|
1051 { |
|
1052 return; |
|
1053 } |
|
1054 } |
|
1055 |
|
1056 switch(iState.iCurrentOperation) |
|
1057 { |
|
1058 case EPopAuthoriseAndConnect: |
|
1059 { |
|
1060 if (eCode == KErrNone) |
|
1061 { |
|
1062 iState.iCurrentOperation = EPopConnecting; |
|
1063 // obtain a connected pop session |
|
1064 iSessionManager->GetSessionL(*iPopSettings, *iIAPPreferences, iPopSession, iStatus); |
|
1065 SetActive(); |
|
1066 return; |
|
1067 } |
|
1068 break; |
|
1069 } |
|
1070 |
|
1071 case EPopConnecting: |
|
1072 { |
|
1073 // Register for bearer mobility, |
|
1074 if (StartBearerMobilityL(eCode)) |
|
1075 { |
|
1076 // Return now if the initial carrier has been rejected. |
|
1077 return; |
|
1078 } |
|
1079 |
|
1080 if (eCode == KErrNone) |
|
1081 { |
|
1082 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1083 // The POP session is now connected - update the connected flag. |
|
1084 User::LeaveIfError( iServerEntry->SetEntry(iServiceId) ); |
|
1085 TMsvEntry entry; |
|
1086 entry = iServerEntry->Entry(); |
|
1087 entry.SetConnected( ETrue ); |
|
1088 User::LeaveIfError( iServerEntry->ChangeEntry(entry) ); |
|
1089 |
|
1090 // if we've connected OK start the refresh |
|
1091 if (iPopSession->MaxHeaders()==0) |
|
1092 { |
|
1093 iState.iCurrentOperation=EPopQuitting; |
|
1094 CommandComplete(KErrNone); |
|
1095 } |
|
1096 else |
|
1097 { |
|
1098 TRAP_IGNORE( DoRefreshL() ); |
|
1099 } |
|
1100 } |
|
1101 break; |
|
1102 } |
|
1103 case EPopRefreshing: |
|
1104 { |
|
1105 // Check if stopping for migrate |
|
1106 if(iMigrationState == EWaitingForOpToStop && eCode == KErrNone) |
|
1107 { |
|
1108 StoreConfigurationToMigrateL(); |
|
1109 // We were waiting on this op to stop before we migrate. |
|
1110 // so start disconnecting for migration now |
|
1111 DisconnectForMigrate(); |
|
1112 return; |
|
1113 } |
|
1114 |
|
1115 // tidy up any dead messages |
|
1116 // should only be necessary if the refresh has failed |
|
1117 if(iMsvIdArray->Count()) |
|
1118 { |
|
1119 iArrayCtr=iMsvIdArray->Count(); |
|
1120 iState.iCurrentOperation=EPopTidying; |
|
1121 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopTidying); |
|
1122 QueueRemoteCleanup(); |
|
1123 } |
|
1124 else |
|
1125 { |
|
1126 if(eCode==KErrNone) |
|
1127 { |
|
1128 TRAP(eCode,DoShowMessagesL(ETrue)); |
|
1129 } |
|
1130 iState.iQuitting = EFalse; |
|
1131 if (eCode == KErrNone) |
|
1132 { |
|
1133 FindFirstOfflineOperationL(EFalse); |
|
1134 } |
|
1135 } |
|
1136 break; |
|
1137 } |
|
1138 case EPopTidying: |
|
1139 { |
|
1140 if(--iArrayCtr>=0) |
|
1141 { |
|
1142 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1143 // No appropriate error handling here... |
|
1144 // Refresh has failed: need to remove all of the partially |
|
1145 // loaded headers etc.. |
|
1146 err = iServerEntry->DeleteEntry((*iMsvIdArray)[iArrayCtr]); |
|
1147 __ASSERT_DEBUG(err == KErrNone, Panic(EPopFailedDebugAssert)); |
|
1148 QueueRemoteCleanup(); |
|
1149 } |
|
1150 else |
|
1151 { |
|
1152 if(iMigrationState == EWaitingForOpToStop && eCode == KErrNone) |
|
1153 { |
|
1154 // Stopping for migrate. RestartAfterMigrateL() calls |
|
1155 // FindFirstOfflineOperationL(EFalse) if restarting in |
|
1156 // state EPopFindingFirstOfflineOp, so set it up and go. |
|
1157 iState.iCurrentOperation = EPopFindingFirstOfflineOp; |
|
1158 StoreConfigurationToMigrateL(); |
|
1159 DisconnectForMigrate(); |
|
1160 return; |
|
1161 } |
|
1162 else |
|
1163 { |
|
1164 FindFirstOfflineOperationL(EFalse); |
|
1165 } |
|
1166 } |
|
1167 break; |
|
1168 } |
|
1169 case EPopFindingFirstOfflineOp: |
|
1170 { |
|
1171 if(iMigrationState == EWaitingForOpToStop && eCode == KErrNone) |
|
1172 { |
|
1173 // Stopping for migrate. RestartAfterMigrateL() calls |
|
1174 // FindFirstOfflineOperationL(EFalse) if restarting in |
|
1175 // state EPopFindingFirstOfflineOp. This is a little |
|
1176 // inefficient, but avoids adding an extra state. |
|
1177 iState.iCurrentOperation = EPopFindingFirstOfflineOp; |
|
1178 StoreConfigurationToMigrateL(); |
|
1179 DisconnectForMigrate(); |
|
1180 return; |
|
1181 } |
|
1182 |
|
1183 if (iOfflineOpFinder->OperationFound()) |
|
1184 { |
|
1185 // A pending offline operation has been found, so run it. |
|
1186 RunOfflineOperationL(); |
|
1187 } |
|
1188 else |
|
1189 // There are no more pending operations. |
|
1190 { |
|
1191 iState.iRunningOfflineOperations = EFalse; |
|
1192 if (iState.iQuitting) |
|
1193 { |
|
1194 // The offline operations are being run as part of the quitting process. |
|
1195 // As these operations have now been run the quitting process should be resumed. |
|
1196 iState.iCurrentOperation=EPopQuitting; |
|
1197 ResetProgress(); |
|
1198 if (iSessionManager && iPopSession) |
|
1199 { |
|
1200 iSessionManager->DeleteSession(*iPopSession, iStatus); |
|
1201 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopQuitting); |
|
1202 iPopSession=NULL; |
|
1203 } |
|
1204 iOperationActive=ETrue; |
|
1205 SetActive(); |
|
1206 } |
|
1207 else |
|
1208 { |
|
1209 // The offline operations are being run as part of the connection process. |
|
1210 // As these operations have now been run we are now connected. |
|
1211 iState.iCurrentOperation=EPopConnectedAndIdle; |
|
1212 iOperationActive=EFalse; |
|
1213 } |
|
1214 } |
|
1215 break; |
|
1216 } |
|
1217 case EPopCopying: |
|
1218 case EPopPopulating: |
|
1219 case EPopMoving: |
|
1220 { |
|
1221 // Check if we are migrating |
|
1222 if(iMigrationState == EWaitingForOpToStop && eCode == KErrNone) |
|
1223 { |
|
1224 // if the operation is incomplete, start migration here. Otherwise |
|
1225 // allow the user request to be completed, and handle migration |
|
1226 // as if the request was to complete op for migrate. |
|
1227 progress = iPopCopyMove->Progress(); |
|
1228 if (progress.iMsgsToProcess) |
|
1229 { |
|
1230 StoreConfigurationToMigrateL(); |
|
1231 DisconnectForMigrate(); |
|
1232 return; |
|
1233 } |
|
1234 } |
|
1235 |
|
1236 if (iState.iRunningOfflineOperations && iState.iCurrentOperation != EPopMoving) |
|
1237 // The operation was a pending offline operation and should be deleted. |
|
1238 { |
|
1239 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1240 CImPop3OfflineUtilities::DeleteL(iOfflineOpFinder->OfflineOperation(), *iServerEntry); |
|
1241 } |
|
1242 |
|
1243 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1244 delete iPopCopyMove; |
|
1245 iPopCopyMove=NULL; |
|
1246 iState.iCurrentOperation=EPopConnectedAndIdle; |
|
1247 iOperationActive=EFalse; |
|
1248 |
|
1249 // reset server entry context |
|
1250 err = iServerEntry->SetEntry( iServiceId ); |
|
1251 if(err != KErrNone) |
|
1252 { |
|
1253 CommandComplete( err ); |
|
1254 return; |
|
1255 } // should disconnect |
|
1256 |
|
1257 if ((iState.iRunningOfflineOperations) && (eCode == KErrNone)) |
|
1258 { |
|
1259 iOfflineOpFinder->FindNext(); |
|
1260 // if we are stopping for migrate and there is another operation to perform, |
|
1261 // allow the migration to happen now. Otherwise, allow the operation to finish. |
|
1262 if (iMigrationState == EWaitingForOpToStop && iOfflineOpFinder->OperationFound()) |
|
1263 { |
|
1264 StoreConfigurationToMigrateL(); |
|
1265 DisconnectForMigrate(); |
|
1266 return; |
|
1267 } |
|
1268 RunOfflineOperationL(); |
|
1269 } |
|
1270 break; |
|
1271 } |
|
1272 case EPopTopPopulating: |
|
1273 { |
|
1274 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1275 // Check if we are migrating |
|
1276 if(iMigrationState == EWaitingForOpToStop && eCode == KErrNone) |
|
1277 { |
|
1278 // if the operation is incomplete, start migration here. Otherwise |
|
1279 // allow the user request to be completed, and handle migration |
|
1280 // as if the request was to complete op for migrate. |
|
1281 progress = iPopTopPop->Progress(); |
|
1282 if (progress.iMsgsToProcess) |
|
1283 { |
|
1284 StoreConfigurationToMigrateL(); |
|
1285 DisconnectForMigrate(); |
|
1286 return; |
|
1287 } |
|
1288 } |
|
1289 |
|
1290 if (iState.iRunningOfflineOperations) |
|
1291 // The operation was a pending offline operation and should be deleted. |
|
1292 { |
|
1293 CImPop3OfflineUtilities::DeleteL(iOfflineOpFinder->OfflineOperation(), *iServerEntry); |
|
1294 } |
|
1295 |
|
1296 delete iPopTopPop; |
|
1297 iPopTopPop=NULL; |
|
1298 iState.iCurrentOperation=EPopConnectedAndIdle; |
|
1299 iOperationActive=EFalse; |
|
1300 |
|
1301 // reset server entry context |
|
1302 err = iServerEntry->SetEntry( iServiceId ); |
|
1303 if(err != KErrNone) |
|
1304 { |
|
1305 CommandComplete( err ); |
|
1306 return; |
|
1307 } // should disconnect |
|
1308 |
|
1309 if ((iState.iRunningOfflineOperations) && (eCode == KErrNone)) |
|
1310 { |
|
1311 iOfflineOpFinder->FindNext(); |
|
1312 // if we are stopping for migrate and there is another operation to perform, |
|
1313 // allow the migration to happen now. Otherwise, allow the operation to finish. |
|
1314 if (iMigrationState == EWaitingForOpToStop && iOfflineOpFinder->OperationFound()) |
|
1315 { |
|
1316 StoreConfigurationToMigrateL(); |
|
1317 DisconnectForMigrate(); |
|
1318 return; |
|
1319 } |
|
1320 RunOfflineOperationL(); |
|
1321 } |
|
1322 break; |
|
1323 } |
|
1324 case EPopDeleting: |
|
1325 { |
|
1326 // Check if we are migrating |
|
1327 if(iMigrationState == EWaitingForOpToStop && eCode == KErrNone) |
|
1328 { |
|
1329 // if the operation is incomplete, start migration here. Otherwise |
|
1330 // allow the user request to be completed, and handle migration |
|
1331 // as if the request was to complete op for migrate. |
|
1332 progress = iPopDelete->Progress(); |
|
1333 if (progress.iMsgsToProcess) |
|
1334 { |
|
1335 StoreConfigurationToMigrateL(); |
|
1336 DisconnectForMigrate(); |
|
1337 return; |
|
1338 } |
|
1339 } |
|
1340 |
|
1341 delete iPopDelete; |
|
1342 iPopDelete=NULL; |
|
1343 |
|
1344 iState.iCurrentOperation=EPopConnectedAndIdle; |
|
1345 iOperationActive=EFalse; |
|
1346 if ((iState.iRunningOfflineOperations) && (eCode == KErrNone)) |
|
1347 { |
|
1348 iOfflineOpFinder->FindNext(); |
|
1349 // if we are stopping for migrate and there is another operation to perform, |
|
1350 // allow the migration to happen now. Otherwise, allow the operation to finish. |
|
1351 if (iMigrationState == EWaitingForOpToStop && iOfflineOpFinder->OperationFound()) |
|
1352 { |
|
1353 StoreConfigurationToMigrateL(); |
|
1354 DisconnectForMigrate(); |
|
1355 return; |
|
1356 } |
|
1357 RunOfflineOperationL(); |
|
1358 } |
|
1359 break; |
|
1360 } |
|
1361 case EPopQuitting: |
|
1362 { |
|
1363 quitSuccessfully = ETrue; |
|
1364 break; |
|
1365 } |
|
1366 case EPopDisconnected: |
|
1367 { |
|
1368 // no change of state |
|
1369 break; |
|
1370 } |
|
1371 case EPopAddingOfflineOp: |
|
1372 case EPopCancellingOfflineOps: |
|
1373 { |
|
1374 iOperationActive = EFalse; |
|
1375 if (!iConnectedToPopMbox) |
|
1376 { |
|
1377 iState.iCurrentOperation=EPopDisconnected; |
|
1378 if(iNotConnectToPopMailBox) |
|
1379 { |
|
1380 CommandComplete(KErrDisconnected); |
|
1381 iNotConnectToPopMailBox = EFalse ; |
|
1382 } |
|
1383 else |
|
1384 { |
|
1385 CommandComplete(KErrNone); |
|
1386 } |
|
1387 } |
|
1388 else |
|
1389 { |
|
1390 if (eCode == KErrNotFound) |
|
1391 { |
|
1392 eCode = KErrNone; |
|
1393 } |
|
1394 iState.iCurrentOperation = EPopConnectedAndIdle; |
|
1395 } |
|
1396 break; |
|
1397 } |
|
1398 default: |
|
1399 { |
|
1400 iState.iCurrentOperation=(eCode==KErrNone) ? EPopConnectedAndIdle : EPopDisconnected; |
|
1401 break; |
|
1402 } |
|
1403 } // end of switch (iState.iCurrentOperation) |
|
1404 |
|
1405 // signal completion unless we're doing the refresh or tidying |
|
1406 if( quitSuccessfully || eCode!=KErrNone ) |
|
1407 { |
|
1408 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1409 if (iPopSession) |
|
1410 { |
|
1411 delete iPopSession; |
|
1412 iPopSession=NULL; |
|
1413 } |
|
1414 iState.iQuitting = EFalse; |
|
1415 |
|
1416 // delete the mobility manager |
|
1417 delete iMobilityManager; |
|
1418 iMobilityManager = NULL; |
|
1419 |
|
1420 TRAP_IGNORE( DoShowMessagesL(EFalse) ); |
|
1421 if( iState.iCurrentOperation != EPopQuitting) |
|
1422 { |
|
1423 TInt err = iServerEntry->SetEntry( iServiceId ); |
|
1424 if(err == KErrNone) |
|
1425 { |
|
1426 TMsvEntry entry = iServerEntry->Entry(); |
|
1427 entry.SetConnected( EFalse ); |
|
1428 iServerEntry->ChangeEntry( entry ); // ignore any error |
|
1429 } |
|
1430 } |
|
1431 if(!(iState.iLastCurrentOperation == EPopConnectedAndIdle && iState.iCurrentOperation == EPopDisconnected) ) |
|
1432 { |
|
1433 CommandComplete( eCode ); |
|
1434 } |
|
1435 else |
|
1436 { |
|
1437 iPopProgress.iErrorCode = eCode; |
|
1438 } |
|
1439 iServerEntry->SetEntry(KMsvNullIndexEntryId); // when it times out the server MTM doesn't get deleted and henc the iServerEntry is locked and cannot do anythig withit. If you set it to NULL it will solve the problem |
|
1440 iState.iCurrentOperation = EPopDisconnected; |
|
1441 return; |
|
1442 } |
|
1443 |
|
1444 if(iReportStatus == NULL && IsActive()) |
|
1445 { |
|
1446 // we are in an inconsistent state and should leave. |
|
1447 // since we want to complete the request and return to the client, |
|
1448 // we LEAVE with KErrUnknown. The completion of the request is done in the TRAP |
|
1449 // of the ServiceL method, where DoComplete is called. |
|
1450 User::Leave(KErrUnknown); |
|
1451 } |
|
1452 |
|
1453 |
|
1454 // set pop session idle waiting |
|
1455 if( iState.iCurrentOperation == EPopConnectedAndIdle && iConnectedToPopMbox |
|
1456 && iState.iCurrentOperation != iState.iLastCurrentOperation) |
|
1457 { |
|
1458 // Complete the waiting iStatus. Note this object stays active so that |
|
1459 // it can react to any connection failure, e.g. time-out |
|
1460 CommandComplete( eCode ); |
|
1461 if( (iMigrationState == EWaitingForOpToComplete) || |
|
1462 (iMigrationState == EWaitingForOpToStop) ) |
|
1463 { |
|
1464 // We were waiting on this op to complete before we migrate. |
|
1465 // so start disconnecting for migration now |
|
1466 DisconnectForMigrate(); |
|
1467 } |
|
1468 else |
|
1469 { |
|
1470 iPopSession->Waiting(iStatus); |
|
1471 SetActive(); |
|
1472 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopConnectedAndIdle); |
|
1473 } |
|
1474 } |
|
1475 } |
|
1476 |
|
1477 /** |
|
1478 Stores configuration to be re-used post Migration. |
|
1479 */ |
|
1480 void CImppServerMtm::StoreConfigurationToMigrateL() |
|
1481 { |
|
1482 iSavedValuesForMigration.iMessageArray = iPopSession->MessageArray(); |
|
1483 iSavedValuesForMigration.iNumMessages = iPopSession->GetNumMessages(); |
|
1484 |
|
1485 TInt32* IdTab = new(ELeave) TInt32[iSavedValuesForMigration.iNumMessages]; |
|
1486 // The copying of Array here is very crude and in-efficient |
|
1487 // Need to use an arraytype that has a copy constructor |
|
1488 for (TInt count=0; count < iSavedValuesForMigration.iNumMessages; count++) |
|
1489 { |
|
1490 IdTab[count] = iSavedValuesForMigration.iMessageArray[count]; |
|
1491 } |
|
1492 iSavedValuesForMigration.iMessageArray = IdTab; |
|
1493 iSavedValuesForMigration.iValuesSaved = ETrue; |
|
1494 } |
|
1495 |
|
1496 /** |
|
1497 Handles the migration state machine states. |
|
1498 This is called the Pop ServerMTM doRunL() routine. |
|
1499 |
|
1500 @return ETrue if the state has been handled and DoRunL can return |
|
1501 */ |
|
1502 TBool CImppServerMtm::DoMigrationRunL() |
|
1503 { |
|
1504 TBool migrationHandled = ETrue; |
|
1505 |
|
1506 // We are migrating so handle the migration states here |
|
1507 switch (iMigrationState) |
|
1508 { |
|
1509 case EDisconnectingForMigrate: |
|
1510 { |
|
1511 // Old session disconnected, tell the MM we are ready to migrate. |
|
1512 iMigrationState = EWaitingForNewCarrier; |
|
1513 iMobilityManager->MigrateToNewCarrier(); |
|
1514 // Set dummy request pending, unless state has been changed by MigrateToNewCarrier() |
|
1515 if (iMigrationState == EWaitingForNewCarrier) |
|
1516 { |
|
1517 iStatus = KRequestPending; |
|
1518 SetActive(); |
|
1519 } |
|
1520 break; |
|
1521 } |
|
1522 case EWaitingForNewCarrier: |
|
1523 case EWaitingCarrierRejected: |
|
1524 { |
|
1525 // Migration has completed, obtain a new connected POP session |
|
1526 iMigrationState = EConnectingAfterMigrate; |
|
1527 iSessionManager->GetSessionL(*iPopSettings, *iIAPPreferences, iPopSession, iStatus); |
|
1528 SetActive(); |
|
1529 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopConnecting); |
|
1530 break; |
|
1531 } |
|
1532 case EConnectingAfterMigrate: |
|
1533 { |
|
1534 if (iStatus.Int()!=KErrNone) |
|
1535 { |
|
1536 // An error has occurred while attempting to re-connect |
|
1537 // - reject this new carrier, wait to see if a new one turns up. |
|
1538 iMigrationState = EWaitingCarrierRejected; |
|
1539 iMobilityManager->NewCarrierRejected(); |
|
1540 |
|
1541 // Now in a waiting state, set self active |
|
1542 iStatus = KRequestPending; |
|
1543 SetActive(); |
|
1544 } |
|
1545 else |
|
1546 { |
|
1547 // We have a new pop session, set the state and tell the mobility manager |
|
1548 iMigrationState = ENotMigrating; |
|
1549 iMobilityManager->NewCarrierAccepted(); |
|
1550 // restart the pop server |
|
1551 RestartAfterMigrateL(); |
|
1552 } |
|
1553 break; |
|
1554 } |
|
1555 default: |
|
1556 { |
|
1557 __ASSERT_DEBUG(EFalse, Panic(EPopUnexpectedMigrateState)); |
|
1558 migrationHandled = EFalse; |
|
1559 break; |
|
1560 } |
|
1561 } |
|
1562 return migrationHandled; |
|
1563 } |
|
1564 |
|
1565 /** |
|
1566 Utility function to delete the Pop Session |
|
1567 note the Session Manager DeleteSession() request is asynchronous. |
|
1568 */ |
|
1569 void CImppServerMtm::DisconnectForMigrate() |
|
1570 { |
|
1571 // Call the session manager to delete the session |
|
1572 iMigrationState = EDisconnectingForMigrate; |
|
1573 iSessionManager->DeleteSession(*iPopSession, iStatus); |
|
1574 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopQuitting); |
|
1575 iPopSession = NULL; |
|
1576 SetActive(); |
|
1577 } |
|
1578 |
|
1579 /** |
|
1580 Restarts any pre-migration outstanding operations, or set the state machine into the same |
|
1581 state it was pre-migration along with any necessary connections and set ups. |
|
1582 |
|
1583 Note that iCurrentOperation will have returned to EPopConnectedAndIdle if the migration type |
|
1584 was "allow complete" or "stop for migrate" and the operation came to a natural finish. |
|
1585 |
|
1586 If iCurrentOperation is not EPopConnectedAndIdle, it indicates that the operation had not |
|
1587 completed prior to the migration. This is caused with by an "accept immediately" migration, |
|
1588 a CarrierLost() migration, or a "stop operation" migration for which the operation did not |
|
1589 come to a natural completion. In these cases, the operation in progress needs to be resumed. |
|
1590 */ |
|
1591 void CImppServerMtm::RestartAfterMigrateL() |
|
1592 { |
|
1593 if (iSavedValuesForMigration.iValuesSaved) |
|
1594 { |
|
1595 // Ownership of MessageArray is passed to the PopSession here |
|
1596 iPopSession->SetMessageArray(iSavedValuesForMigration.iMessageArray, iSavedValuesForMigration.iNumMessages); |
|
1597 iSavedValuesForMigration.iValuesSaved = EFalse; |
|
1598 } |
|
1599 |
|
1600 // switch on pre-migrate state |
|
1601 switch(iState.iCurrentOperation) |
|
1602 { |
|
1603 case EPopConnecting: // in this state if initial carrier rejected... |
|
1604 case EPopTidying: |
|
1605 { |
|
1606 // Self complete to return to the State Machine |
|
1607 iStatus = KRequestPending; |
|
1608 SetActive(); |
|
1609 TRequestStatus *status = &iStatus; |
|
1610 User::RequestComplete(status,KErrNone); |
|
1611 break; |
|
1612 } |
|
1613 case EPopConnectedAndIdle: |
|
1614 { |
|
1615 if (iState.iRunningOfflineOperations) |
|
1616 { |
|
1617 // can be in this state if the offline operations were stopped before all |
|
1618 // were finished. |
|
1619 RunOfflineOperationL(); |
|
1620 } |
|
1621 else |
|
1622 { |
|
1623 // No operation in progress at time of migration, re-enter idle waiting state |
|
1624 iPopSession->Waiting(iStatus); |
|
1625 SetActive(); |
|
1626 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopConnectedAndIdle); |
|
1627 } |
|
1628 break; |
|
1629 } |
|
1630 // Refresh, Copy, Move, Delete, Populate - these operations need to be |
|
1631 // resumed if they were cancelled or stopped before completing. |
|
1632 // Note that if the operation had actually completed, |
|
1633 // iCurrentOperation would now be EPopConnectedAndIdle. |
|
1634 case EPopRefreshing: |
|
1635 { |
|
1636 // Resume the refresh operation: |
|
1637 iPopRefreshMailbox->ResumeL(iPopSession, iStatus); |
|
1638 SetActive(); |
|
1639 break; |
|
1640 } |
|
1641 case EPopCopying: |
|
1642 case EPopMoving: |
|
1643 case EPopPopulating: |
|
1644 { |
|
1645 // Resume the copy/move operation |
|
1646 iPopCopyMove->ResumeL(iPopSession, iStatus); |
|
1647 iStatus = KRequestPending; |
|
1648 SetActive(); |
|
1649 break; |
|
1650 } |
|
1651 case EPopDeleting: |
|
1652 { |
|
1653 // Resume the delete operation |
|
1654 iPopDelete->ResumeL(iPopSession, iStatus); |
|
1655 SetActive(); |
|
1656 break; |
|
1657 } |
|
1658 case EPopTopPopulating: |
|
1659 { |
|
1660 iPopTopPop->ResumeL(iPopSession, iStatus); |
|
1661 SetActive(); |
|
1662 break; |
|
1663 } |
|
1664 case EPopFindingFirstOfflineOp: |
|
1665 { |
|
1666 // This can be the current operation either during connect or |
|
1667 // disconnect. However, we will not migrate during a disconnect, |
|
1668 // so we can safely assume this is during connect. |
|
1669 // This is an asynchronous operation that builds an array of |
|
1670 // offline requested operations that need to be performed once |
|
1671 // connection has been established. Probably best to rebuild |
|
1672 // the list now. |
|
1673 User::LeaveIfError(iServerEntry->SetEntry(iServiceId)); |
|
1674 FindFirstOfflineOperationL(EFalse); // calls SetActive() |
|
1675 break; |
|
1676 } |
|
1677 case EPopCancellingOfflineOps: |
|
1678 { |
|
1679 // nothing to stop this action when connected, therefore must be able |
|
1680 // to handle it having been cancelled. |
|
1681 iOfflineOpSetter->ResumeCancelOfflineOperationsL(iStatus); |
|
1682 break; |
|
1683 } |
|
1684 case EPopAuthoriseAndConnect: |
|
1685 case EPopQuitting: // we shouldn't ever get a migration when quitting |
|
1686 case EPopAddingOfflineOp: // disconnected operation |
|
1687 case EPopDisconnected: // disconnected operation |
|
1688 default: |
|
1689 { |
|
1690 __ASSERT_ALWAYS(EFalse, Panic(EPopRestartUnexpectedOp)); |
|
1691 break; |
|
1692 } |
|
1693 } |
|
1694 |
|
1695 } |
|
1696 |
|
1697 // |
|
1698 // |
|
1699 // |
|
1700 void CImppServerMtm::DoComplete(TInt aError) |
|
1701 { |
|
1702 CommandComplete( aError ); |
|
1703 } |
|
1704 |
|
1705 // |
|
1706 // Open up POP3 settings store |
|
1707 // |
|
1708 void CImppServerMtm::GetPopDetailsL(const CMsvEntrySelection& aSel) |
|
1709 { |
|
1710 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1711 delete iPopSettings; |
|
1712 iPopSettings=NULL; |
|
1713 iPopSettings=new(ELeave)CImPop3Settings; |
|
1714 delete iIAPPreferences; |
|
1715 iIAPPreferences = NULL; |
|
1716 iIAPPreferences = CImIAPPreferences::NewLC(); |
|
1717 CleanupStack::Pop(); // doesn't need to be on the stack! |
|
1718 // check our entry is the service entry else use IT'S service id |
|
1719 TInt err = iServerEntry->SetEntry(aSel[0]); |
|
1720 |
|
1721 if (iServerEntry->Entry().iType != KUidMsvServiceEntry) |
|
1722 { |
|
1723 User::LeaveIfError(iServerEntry->SetEntry(iServerEntry->Entry().iServiceId)); |
|
1724 iServiceId = iServerEntry->Entry().Id(); |
|
1725 } |
|
1726 |
|
1727 __ASSERT_DEBUG(iServerEntry->Entry().iType==KUidMsvServiceEntry, Panic(EPopCurrentContextIsNotService)); |
|
1728 if(err == KErrNone && iServerEntry->Entry().iType != KUidMsvServiceEntry) |
|
1729 { |
|
1730 User::Leave(KErrNotSupported); |
|
1731 } |
|
1732 |
|
1733 CEmailAccounts* account = CEmailAccounts::NewLC(); |
|
1734 TPopAccount id; |
|
1735 id.iPopAccountId = iServerEntry->Entry().MtmData2(); // iMtmData2 of the service entry contains TPopAccountId |
|
1736 id.iPopAccountName = iServerEntry->Entry().iDetails; |
|
1737 id.iPopService = iServerEntry->Entry().iServiceId; |
|
1738 id.iSmtpService = iServerEntry->Entry().iRelatedId; |
|
1739 |
|
1740 account->LoadPopSettingsL(id, *iPopSettings); |
|
1741 account->LoadPopIapSettingsL(id, *iIAPPreferences); |
|
1742 CleanupStack::PopAndDestroy(account); |
|
1743 __ASSERT_DEBUG(iServiceId==iServerEntry->Entry().Id(), Panic(EPopCurrentContextIsNotService)); |
|
1744 iServiceId = iServerEntry->Entry().Id(); |
|
1745 } |
|
1746 |
|
1747 // |
|
1748 // Async stage for cleaning up |
|
1749 // |
|
1750 void CImppServerMtm::QueueRemoteCleanup() |
|
1751 { |
|
1752 TRequestStatus *pS = &iStatus; |
|
1753 SetActive(); |
|
1754 User::RequestComplete(pS,KErrNone); |
|
1755 } |
|
1756 |
|
1757 // |
|
1758 // DoShowMessagesL(). |
|
1759 // |
|
1760 // Gets all the chld entries for iServiceId.. |
|
1761 // |
|
1762 // |
|
1763 void CImppServerMtm::DoShowMessagesL(TBool aShow) |
|
1764 { |
|
1765 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1766 if ((!iConnectedToPopMbox) && (!aShow)) |
|
1767 { |
|
1768 return; |
|
1769 } |
|
1770 |
|
1771 iConnectedToPopMbox=aShow; |
|
1772 |
|
1773 // Leave messages displayed under the service if we are in disconnected mode. |
|
1774 if (iPopSettings) |
|
1775 { |
|
1776 if ((iPopSettings->DisconnectedUserMode())) |
|
1777 { |
|
1778 aShow = ETrue; |
|
1779 } |
|
1780 } |
|
1781 |
|
1782 if (iDoCallShowMessages==(TInt)aShow) |
|
1783 { |
|
1784 return; |
|
1785 } |
|
1786 User::LeaveIfError(iServerEntry->SetEntry( iServiceId )); |
|
1787 __ASSERT_DEBUG(iServerEntry->Entry().Id()!=KMsvNullIndexEntryId, Panic(EPopCurrentContextIsNullEntry)); |
|
1788 if (iServerEntry->Entry().iType!=KUidMsvServiceEntry || iServerEntry->Entry().Id()==KMsvNullIndexEntryId) |
|
1789 { |
|
1790 return; |
|
1791 } |
|
1792 // Make a new CMsvEntrySelection |
|
1793 CMsvEntrySelection* selection = new (ELeave) CMsvEntrySelection; |
|
1794 CleanupStack::PushL(selection); |
|
1795 TMsvSelectionOrdering order; |
|
1796 order.SetShowInvisibleEntries( ETrue ); |
|
1797 iServerEntry->SetSort( order ); |
|
1798 User::LeaveIfError(iServerEntry->GetChildren(*selection)); |
|
1799 |
|
1800 // Change the visible flag for each TMsvEntry in the child |
|
1801 // collection.. |
|
1802 if (aShow) |
|
1803 { |
|
1804 User::LeaveIfError(iServerEntry->ChangeAttributes(*selection, KMsvVisibilityAttribute,0)); |
|
1805 } |
|
1806 else |
|
1807 { |
|
1808 User::LeaveIfError(iServerEntry->ChangeAttributes(*selection,0,KMsvVisibilityAttribute | KMsvUnreadAttribute)); |
|
1809 } |
|
1810 CleanupStack::PopAndDestroy(); // selection |
|
1811 iDoCallShowMessages=(TInt)aShow; |
|
1812 } |
|
1813 |
|
1814 // |
|
1815 // Abort an MTM command if necessary |
|
1816 // |
|
1817 |
|
1818 void CImppServerMtm::CommandComplete( TInt aErrorCode ) |
|
1819 { |
|
1820 // error code returned in the progress |
|
1821 iPopProgress.iErrorCode = aErrorCode; |
|
1822 |
|
1823 //check iReportStatus for cases where we have already completed the caller |
|
1824 if(iReportStatus) |
|
1825 { |
|
1826 User::RequestComplete(iReportStatus, KErrNone); |
|
1827 iReportStatus = NULL; |
|
1828 } |
|
1829 } |
|
1830 |
|
1831 CMsvEntrySelection* CImppServerMtm::StripInvalidEntriesLC(const CMsvEntrySelection& aSelection, TBool aExcludePartial) const |
|
1832 { |
|
1833 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1834 CMsvEntrySelection* entries=aSelection.CopyLC(); |
|
1835 TMsvEntry* entry; |
|
1836 TInt count=entries->Count(); |
|
1837 while (count--) |
|
1838 { |
|
1839 iServerEntry->GetEntryFromId((*entries)[count], entry); |
|
1840 const TMsvEmailEntry &emailEntry=(*entry); |
|
1841 if(entry->iServiceId != iServiceId || (emailEntry.PartialDownloaded() && aExcludePartial)) |
|
1842 { |
|
1843 entries->Delete(count); |
|
1844 } |
|
1845 } |
|
1846 return entries; |
|
1847 } |
|
1848 |
|
1849 void CImppServerMtm::FindFirstOfflineOperationL(TBool aQuitting) |
|
1850 { |
|
1851 iState.iCurrentOperation=EPopFindingFirstOfflineOp; |
|
1852 iOperationActive=ETrue; |
|
1853 iOfflineOpFinder->FindFirstL(iServiceId, aQuitting, iStatus); |
|
1854 iState.iRunningOfflineOperations = ETrue; |
|
1855 SetActive(); |
|
1856 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopFindingFirstOfflineOp); |
|
1857 } |
|
1858 |
|
1859 void CImppServerMtm::RunOfflineOperationL() |
|
1860 { |
|
1861 if (iOfflineOpFinder->OperationFound()) |
|
1862 { |
|
1863 const CImOffLineOperation& offlineOperation = iOfflineOpFinder->OfflineOperation(); |
|
1864 CMsvEntrySelection* messageSelection; |
|
1865 iState.iCurrentOperation=EPopConnectedAndIdle; |
|
1866 iOperationActive=EFalse; |
|
1867 |
|
1868 switch (offlineOperation.OpType()) |
|
1869 { |
|
1870 case CImOffLineOperation::EOffLineOpNone: |
|
1871 case CImOffLineOperation::EOffLineOpCopyFromLocal: |
|
1872 case CImOffLineOperation::EOffLineOpMoveFromLocal: |
|
1873 case CImOffLineOperation::EOffLineOpMoveWithinService: |
|
1874 case CImOffLineOperation::EOffLineOpChange: |
|
1875 case CImOffLineOperation::EOffLineOpCreate: |
|
1876 case CImOffLineOperation::EOffLineOpMtmSpecific: |
|
1877 User::Leave(KErrNotSupported); |
|
1878 |
|
1879 case CImOffLineOperation::EOffLineOpCopyToLocal: |
|
1880 messageSelection = new (ELeave) CMsvEntrySelection; |
|
1881 CleanupStack::PushL(messageSelection); |
|
1882 messageSelection->AppendL(offlineOperation.MessageId()); |
|
1883 CopyToLocalL(*messageSelection, offlineOperation.TargetMessageId(),*iReportStatus); |
|
1884 CleanupStack::PopAndDestroy(); // messageSelection |
|
1885 break; |
|
1886 |
|
1887 case CImOffLineOperation::EOffLineOpDelete: |
|
1888 messageSelection = new (ELeave) CMsvEntrySelection; |
|
1889 CleanupStack::PushL(messageSelection); |
|
1890 messageSelection->AppendL(offlineOperation.MessageId()); |
|
1891 DeleteAllL(*messageSelection, *iReportStatus); |
|
1892 CleanupStack::PopAndDestroy(); // messageSelection |
|
1893 break; |
|
1894 |
|
1895 case CImOffLineOperation::EOffLineOpCopyWithinService: |
|
1896 messageSelection = new (ELeave) CMsvEntrySelection; |
|
1897 CleanupStack::PushL(messageSelection); |
|
1898 messageSelection->AppendL(offlineOperation.MessageId()); |
|
1899 CopyWithinServiceL(*messageSelection, offlineOperation.TargetMessageId(),*iReportStatus); |
|
1900 CleanupStack::PopAndDestroy(); // messageSelection |
|
1901 break; |
|
1902 |
|
1903 case CImOffLineOperation::EOffLineOpMoveToLocal: |
|
1904 messageSelection = new (ELeave) CMsvEntrySelection; |
|
1905 CleanupStack::PushL(messageSelection); |
|
1906 messageSelection->AppendL(offlineOperation.MessageId()); |
|
1907 MoveToLocalL(*messageSelection, offlineOperation.TargetMessageId(),*iReportStatus); |
|
1908 CleanupStack::PopAndDestroy(); // messageSelection |
|
1909 break; |
|
1910 default: |
|
1911 User::Leave(KErrNotSupported); |
|
1912 break; |
|
1913 } |
|
1914 } |
|
1915 else |
|
1916 { |
|
1917 iState.iRunningOfflineOperations = EFalse; |
|
1918 if (iState.iQuitting) |
|
1919 { |
|
1920 // Run the actual quit operation now. |
|
1921 iState.iCurrentOperation=EPopQuitting; |
|
1922 ResetProgress(); |
|
1923 //iPopSession->Quit(iStatus); |
|
1924 iSessionManager->DeleteSession(*iPopSession, iStatus); |
|
1925 MOBILITY_TEST_MTM_STATE(iServiceId, KMobilityTestMtmStatePopQuitting); |
|
1926 iPopSession=NULL; |
|
1927 iOperationActive=ETrue; |
|
1928 SetActive(); |
|
1929 } |
|
1930 else |
|
1931 { |
|
1932 iState.iCurrentOperation=EPopConnectedAndIdle; |
|
1933 iOperationActive=EFalse; |
|
1934 } |
|
1935 } |
|
1936 } |
|
1937 |
|
1938 |
|
1939 TBool CImppServerMtm::AcceptingOfflineOperationsL(const CMsvEntrySelection& aSelection) |
|
1940 // Returns true if the POPS MTM can accept an offline operation. |
|
1941 { |
|
1942 if (iPopSettings == 0) |
|
1943 { |
|
1944 GetPopDetailsL(aSelection); |
|
1945 } |
|
1946 |
|
1947 return ((iState.iCurrentOperation == EPopDisconnected) && (iPopSettings->DisconnectedUserMode())); |
|
1948 } |
|
1949 |
|
1950 |
|
1951 void CImppServerMtm::AddOfflineOperationL(const CMsvEntrySelection& aSelection, TMsvId aDestination, CImOffLineOperation::TOffLineOpType aOperationType, TRequestStatus& aStatus) |
|
1952 // Asynchronously applies the given operation type to the given selection of |
|
1953 // messages. The destination parameter is ignored for some operations, eg. delete. |
|
1954 { |
|
1955 if (iState.iCurrentOperation == EPopConnectedAndIdle) |
|
1956 { |
|
1957 Cancel(); |
|
1958 } |
|
1959 |
|
1960 iOfflineOpSetter->AddOfflineOperationL(&aSelection, aOperationType, aDestination, iStatus); |
|
1961 iState.iCurrentOperation = EPopAddingOfflineOp; |
|
1962 iReportStatus=&aStatus; |
|
1963 ResetProgress(); |
|
1964 SetActive(); |
|
1965 aStatus = KRequestPending; |
|
1966 iOperationActive = ETrue; |
|
1967 } |
|
1968 |
|
1969 void CImppServerMtm::CancelOfflineOperationsL(const CMsvEntrySelection& aSelection, TRequestStatus& aStatus) |
|
1970 { |
|
1971 Cancel(); |
|
1972 iOfflineOpSetter->CancelOfflineOperationsL(aSelection, iStatus); |
|
1973 iState.iCurrentOperation = EPopCancellingOfflineOps; |
|
1974 iReportStatus=&aStatus; |
|
1975 ResetProgress(); |
|
1976 SetActive(); |
|
1977 aStatus = KRequestPending; |
|
1978 iOperationActive = ETrue; |
|
1979 } |
|
1980 |
|
1981 // |
|
1982 // constructor |
|
1983 // |
|
1984 CImppServerMtm::CImppServerMtm(CRegisteredMtmDll& aPopServerMtmDll, CMsvServerEntry* aEntry) |
|
1985 :CBaseServerMtm(aPopServerMtmDll, aEntry) |
|
1986 { |
|
1987 } |
|
1988 |
|
1989 void CImppServerMtm::ConstructL() |
|
1990 { |
|
1991 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
1992 CActiveScheduler::Add(this); |
|
1993 iConnectedToPopMbox=EFalse; |
|
1994 iOperationActive=EFalse; |
|
1995 iDoCallShowMessages=-1; |
|
1996 ResetProgress(); |
|
1997 iServiceId=iServerEntry->Entry().Id(); |
|
1998 |
|
1999 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
2000 iWaiter = CPopUpsResponseWaiter::NewL(); |
|
2001 iHasCapability = ETrue; |
|
2002 #endif |
|
2003 |
|
2004 iOfflineOpFinder = CImPop3OfflineOperationFinder::NewL(*iServerEntry); |
|
2005 iOfflineOpSetter = CImPop3SetOfflineOps::NewL(*iServerEntry); |
|
2006 iState.iCurrentOperation = EPopDisconnected; |
|
2007 iCancelForBMMigration = EFalse; |
|
2008 iMigrationState = ENotMigrating; |
|
2009 iNotConnectToPopMailBox = ETrue ; |
|
2010 TRAP_IGNORE( iLogMessage=CImLogMessage::NewL( iServerEntry->FileSession() ) ); |
|
2011 } |
|
2012 |
|
2013 CImppServerMtm::~CImppServerMtm() |
|
2014 { |
|
2015 Cancel(); |
|
2016 |
|
2017 if (iServerEntry->Entry().Id()!=KMsvNullIndexEntryId) |
|
2018 { |
|
2019 TRAP_IGNORE( DoShowMessagesL(EFalse) ); |
|
2020 TInt err = iServerEntry->SetEntry(iServiceId); |
|
2021 |
|
2022 if (err == KErrNone) |
|
2023 { |
|
2024 TMsvEntry entry = iServerEntry->Entry(); |
|
2025 if (entry.Connected()) |
|
2026 { |
|
2027 entry.SetConnected( EFalse ); |
|
2028 iServerEntry->ChangeEntry( entry ); // ignore any error |
|
2029 } |
|
2030 } |
|
2031 } |
|
2032 |
|
2033 delete iPopSession; |
|
2034 delete iPopRefreshMailbox; |
|
2035 delete iPopCopyMove; |
|
2036 delete iPopDelete; |
|
2037 delete iPopSettings; |
|
2038 delete iIAPPreferences; |
|
2039 delete iMsvIdArray; |
|
2040 delete iOfflineOpFinder; |
|
2041 delete iOfflineOpSetter; |
|
2042 delete iLogMessage; |
|
2043 delete iMessagesToKeep; |
|
2044 delete iPopTopPop; |
|
2045 #if (defined SYMBIAN_USER_PROMPT_SERVICE) |
|
2046 delete iWaiter; |
|
2047 #endif |
|
2048 |
|
2049 delete iMobilityManager; |
|
2050 delete iSessionManager; |
|
2051 if(iSavedValuesForMigration.iValuesSaved) |
|
2052 { |
|
2053 // We are leaving before ownership of Message Array was passed to PopSession |
|
2054 delete iSavedValuesForMigration.iMessageArray; |
|
2055 } |
|
2056 } |
|
2057 |
|
2058 |
|
2059 TBool CImppServerMtm::PruneMessages(const CMsvEntrySelection& aSelection, TRequestStatus& aStatus) |
|
2060 { |
|
2061 TInt index = aSelection.Count(); |
|
2062 |
|
2063 // See if the parent of the first entry is a message. |
|
2064 // If it is then we need to prune the entries, ie. delete them locally. |
|
2065 if (index == 0) |
|
2066 { |
|
2067 return EFalse; |
|
2068 } |
|
2069 |
|
2070 TInt err = iServerEntry->SetEntry(aSelection[0]); |
|
2071 |
|
2072 if (err == KErrNone) |
|
2073 { |
|
2074 err = iServerEntry->SetEntry(iServerEntry->Entry().Parent()); |
|
2075 if (KUidMsvMessageEntry != iServerEntry->Entry().iType) |
|
2076 { |
|
2077 // The parent of the given entry was not a message, so we don't prune it. |
|
2078 return EFalse; |
|
2079 } |
|
2080 } |
|
2081 |
|
2082 while ((index--) && (err==KErrNone)) |
|
2083 { |
|
2084 // Go to the required entry |
|
2085 err = iServerEntry->SetEntry(aSelection[index]); |
|
2086 |
|
2087 if (KErrNone == err) |
|
2088 { |
|
2089 // Go to the parent entry to see if it is a message entry |
|
2090 iServerEntry->SetEntry(iServerEntry->Entry().Parent()); |
|
2091 TMsvEmailEntry entry = iServerEntry->Entry(); |
|
2092 |
|
2093 // Clear the complete flag because we are about to delete the child parts. |
|
2094 entry.SetComplete(EFalse); |
|
2095 entry.SetBodyTextComplete(EFalse); |
|
2096 err = iServerEntry->ChangeEntry(entry); |
|
2097 |
|
2098 if (KErrNone == err) |
|
2099 { |
|
2100 // Delete the body of the message. |
|
2101 iServerEntry->DeleteEntry(aSelection[index]); |
|
2102 } |
|
2103 } |
|
2104 } |
|
2105 if (err == KErrNone) |
|
2106 { |
|
2107 err = iServerEntry->SetEntry(KMsvNullIndexEntryId); |
|
2108 } |
|
2109 |
|
2110 TRequestStatus* status = &aStatus; |
|
2111 User::RequestComplete(status, err); |
|
2112 |
|
2113 return ETrue; |
|
2114 } |
|
2115 |
|
2116 /** |
|
2117 Notice that a preferred carrier has become available, and migration to that bearer has been |
|
2118 accepted. The Pop Server MTM shall either pause or allow any current operation to complete |
|
2119 according to the action specified in parameter aAction. Once the current operation is paused |
|
2120 or complete, the Pop Server MTM shall close any existing sockets and finally notify the |
|
2121 mobility framework that it is ready to migrate to the new carrier. |
|
2122 |
|
2123 @param aAction - indicates the action that should be taken re: current operations |
|
2124 @param aIsSeamless - indicates if the Bearer is seamless. |
|
2125 */ |
|
2126 void CImppServerMtm::PrepareForNewCarrier(TImMobilityAction aAction, TBool /*aIsSeamless*/) |
|
2127 { |
|
2128 // if the action is to accept immediately, CancelToMigrate can handle any current state... |
|
2129 if (aAction == KAcceptImmediately) |
|
2130 { |
|
2131 if (iPopSession) |
|
2132 { |
|
2133 TRAP_IGNORE(StoreConfigurationToMigrateL()); |
|
2134 } |
|
2135 |
|
2136 // Accept the migration immediately, and delete any current activity |
|
2137 CancelToMigrate(); |
|
2138 iMigrationState = EWaitingForNewCarrier; |
|
2139 iMobilityManager->MigrateToNewCarrier(); |
|
2140 |
|
2141 // do not set waiting if NewCarrierActive has been called synchronously. |
|
2142 if (iMigrationState == EWaitingForNewCarrier) |
|
2143 { |
|
2144 // Now in a waiting state, set self active |
|
2145 iStatus = KRequestPending; |
|
2146 SetActive(); |
|
2147 } |
|
2148 } |
|
2149 else // ...otherwise, we need to handle being called in different migration states |
|
2150 { |
|
2151 switch (iMigrationState) |
|
2152 { |
|
2153 case ENotMigrating: |
|
2154 { |
|
2155 // allow any op in progress to complete, or stop when convenient, |
|
2156 // according to the specified action |
|
2157 if (aAction == KAcceptCompleteCurrent) |
|
2158 { |
|
2159 CompleteCurrentOpForMigration(); |
|
2160 } |
|
2161 else // aAction == KAcceptStopCurrent |
|
2162 { |
|
2163 StopCurrentOpForMigration(); |
|
2164 } |
|
2165 break; |
|
2166 } |
|
2167 case EWaitingForOpToComplete: |
|
2168 { |
|
2169 // override a previous complete action with a stop... |
|
2170 if (aAction == KAcceptStopCurrent) |
|
2171 { |
|
2172 StopCurrentOpForMigration(); |
|
2173 } |
|
2174 break; |
|
2175 } |
|
2176 case EWaitingForOpToStop: |
|
2177 case EDisconnectingForMigrate: |
|
2178 { |
|
2179 // already stopping, do NOT override a stop action with a complete action |
|
2180 break; |
|
2181 } |
|
2182 case EWaitingForNewCarrier: |
|
2183 case EWaitingCarrierRejected: |
|
2184 { |
|
2185 // aleady ready and waiting for a new carrier. Tell the mobility manager, |
|
2186 // but no further action necessary |
|
2187 iMobilityManager->MigrateToNewCarrier(); |
|
2188 break; |
|
2189 } |
|
2190 case EConnectingAfterMigrate: |
|
2191 { |
|
2192 // Cancel the (re)connect operation, and inform the mobility manager |
|
2193 CancelToMigrate(); |
|
2194 iMigrationState = EWaitingForNewCarrier; |
|
2195 iMobilityManager->MigrateToNewCarrier(); |
|
2196 |
|
2197 // do not set waiting if NewCarrierActive has been called synchronously. |
|
2198 if (iMigrationState == EWaitingForNewCarrier) |
|
2199 { |
|
2200 // Now in a waiting state, set self active |
|
2201 iStatus = KRequestPending; |
|
2202 SetActive(); |
|
2203 } |
|
2204 break; |
|
2205 } |
|
2206 default: |
|
2207 { |
|
2208 __ASSERT_ALWAYS(EFalse, Panic(EPopNewCarrierUnknownState)); |
|
2209 break; |
|
2210 } |
|
2211 } // end of switch (iMigrationState) |
|
2212 } // end of else... |
|
2213 } |
|
2214 |
|
2215 /** |
|
2216 Handles the completion of operations in order to migrate. This is called by the |
|
2217 PrepareForNewCarrier() function, when it is called by the mobility manager with |
|
2218 the mobility action CompleteCurrentOpForMigration. |
|
2219 */ |
|
2220 void CImppServerMtm::CompleteCurrentOpForMigration() |
|
2221 { |
|
2222 iMigrationState = EWaitingForOpToComplete; |
|
2223 switch(iState.iCurrentOperation) |
|
2224 { |
|
2225 case EPopRefreshing: |
|
2226 case EPopTidying: |
|
2227 case EPopCopying: |
|
2228 case EPopMoving: |
|
2229 case EPopPopulating: |
|
2230 case EPopTopPopulating: |
|
2231 case EPopDeleting: |
|
2232 case EPopFindingFirstOfflineOp: |
|
2233 case EPopCancellingOfflineOps: |
|
2234 { |
|
2235 // Just allow these operations to complete, handle in DoRunL |
|
2236 break; |
|
2237 } |
|
2238 case EPopConnectedAndIdle: |
|
2239 { |
|
2240 // The POP Server MTM sets itself into a dummy active state when it enters |
|
2241 // the EPopConnectedAndIdle state so we must cancel this active state |
|
2242 CancelToMigrate(); |
|
2243 // Kick off the disconnect immediately. DoRunL is complex enough as it is. |
|
2244 DisconnectForMigrate(); |
|
2245 break; |
|
2246 } |
|
2247 case EPopAuthoriseAndConnect: |
|
2248 case EPopAddingOfflineOp: // offline only |
|
2249 case EPopDisconnected: // offline |
|
2250 case EPopConnecting: // haven't registered for bearer events in this state |
|
2251 case EPopQuitting: // deregistered |
|
2252 default: |
|
2253 { |
|
2254 __ASSERT_ALWAYS(EFalse, Panic(EPopCompleteOpUnexpectedOp)); |
|
2255 break; |
|
2256 } |
|
2257 } |
|
2258 } |
|
2259 |
|
2260 /** |
|
2261 Handles the halting of operations in order to migrate. This is called by the |
|
2262 PrepareForNewCarrier() function, when it is called by the mobility manager with |
|
2263 the mobility action StopCurrentOpForMigration. |
|
2264 */ |
|
2265 void CImppServerMtm::StopCurrentOpForMigration() |
|
2266 { |
|
2267 iMigrationState = EWaitingForOpToStop; |
|
2268 // Signal the current operation handler to stop when convenient... |
|
2269 switch (iState.iCurrentOperation) |
|
2270 { |
|
2271 case EPopTidying: // self completed state - handle in DoMigrateRunL |
|
2272 case EPopFindingFirstOfflineOp: // self completed state - handle in DoMigrateRunL |
|
2273 case EPopCancellingOfflineOps: // allow to finish. |
|
2274 { |
|
2275 break; |
|
2276 } |
|
2277 case EPopCopying: |
|
2278 case EPopMoving: |
|
2279 case EPopPopulating: |
|
2280 { |
|
2281 iPopCopyMove->Pause(); |
|
2282 break; |
|
2283 } |
|
2284 case EPopTopPopulating: |
|
2285 { |
|
2286 iPopTopPop->Pause(); |
|
2287 break; |
|
2288 } |
|
2289 case EPopDeleting: |
|
2290 { |
|
2291 iPopDelete->Pause(); |
|
2292 break; |
|
2293 } |
|
2294 case EPopRefreshing: |
|
2295 { |
|
2296 iPopRefreshMailbox->Pause(); |
|
2297 break; |
|
2298 } |
|
2299 case EPopConnectedAndIdle: |
|
2300 { |
|
2301 // The POP Server MTM sets itself into a dummy active state when it enters |
|
2302 // the EPopConnectedAndIdle state so we must cancel this active state |
|
2303 CancelToMigrate(); |
|
2304 // Kick off the disconnect immediately. DoRunL is complex enough as it is. |
|
2305 DisconnectForMigrate(); |
|
2306 break; |
|
2307 } |
|
2308 case EPopAuthoriseAndConnect: // not yet registered |
|
2309 case EPopConnecting: // not yet registered |
|
2310 case EPopQuitting: // deregistered... |
|
2311 case EPopDisconnected: // offline |
|
2312 case EPopAddingOfflineOp: // offline |
|
2313 default: |
|
2314 { |
|
2315 __ASSERT_ALWAYS(EFalse, Panic(EPopStopOpUnexpectedOp)); |
|
2316 break; |
|
2317 } |
|
2318 } |
|
2319 } |
|
2320 |
|
2321 /** |
|
2322 This function may be called directly by the Mobility Manager in the case |
|
2323 that a downgrade notification has been received from the networking layer. |
|
2324 On return from this function, the server MTM must have cancelled any operations |
|
2325 on the existing pop session with resume enabled. |
|
2326 |
|
2327 It may be called at any time, including when a migration is already in progress. |
|
2328 */ |
|
2329 void CImppServerMtm::CarrierLost() |
|
2330 { |
|
2331 if (iPopSession) |
|
2332 { |
|
2333 TRAP_IGNORE(StoreConfigurationToMigrateL()); |
|
2334 } |
|
2335 |
|
2336 // DoCancel() handles all migration states. |
|
2337 CancelToMigrate(); |
|
2338 |
|
2339 // Calling Cancel() doesnt *always* cause the iPopSession to be deleted, |
|
2340 // for example, if in EPopConnectedAndIdle state. Just make sure: |
|
2341 delete iPopSession; |
|
2342 iPopSession = NULL; |
|
2343 |
|
2344 // Now that the current activity has been stopped, just need to wait for |
|
2345 // a new carrier to come available. Set state and dummy request pending |
|
2346 iMigrationState = EWaitingForNewCarrier; |
|
2347 iStatus = KRequestPending; |
|
2348 SetActive(); |
|
2349 } |
|
2350 |
|
2351 /** |
|
2352 Notice that the New Carrier is now active and the server MTM can make connections on it. |
|
2353 Once this notice is received from the Mobility Manager, the Server MTM can create a new |
|
2354 session on it and restart any awaiting operations on the New Carrier. These could be |
|
2355 operations that were stopped mid-way and need resuming from there or operations(requests) |
|
2356 that were cancelled and need starting from beginning. |
|
2357 @param aNewApp - acces point information. |
|
2358 @param aIsSeamless - Flag to indicate whether the migration is seamless. |
|
2359 */ |
|
2360 void CImppServerMtm::NewCarrierActive(TAccessPointInfo /*aNewAp*/, TBool /*aIsSeamless*/) |
|
2361 { |
|
2362 __ASSERT_DEBUG((iMigrationState == EWaitingForNewCarrier || |
|
2363 iMigrationState == EWaitingCarrierRejected), |
|
2364 Panic(EPopUnexpectedNewCarrierActive)); |
|
2365 |
|
2366 // Complete the request as the New carrier we were waiting on is now active |
|
2367 // This will enable us to get back into the Server MTM state machine, |
|
2368 // initially dealing with the migration states and later with the MTM states if needed. |
|
2369 TRequestStatus* status = &iStatus; |
|
2370 User::RequestComplete(status, KErrNone); |
|
2371 } |
|
2372 |
|
2373 /** |
|
2374 Handles Migration Errors |
|
2375 |
|
2376 Simply deletes everything, marks the server offline and completes any |
|
2377 outstanding user requests. |
|
2378 |
|
2379 @param aError - An error code indicating the type of migration error. |
|
2380 */ |
|
2381 void CImppServerMtm::MobilityError(TUint /*aError*/) |
|
2382 { |
|
2383 __ASSERT_ALWAYS(iServerEntry, Panic(EPopNullPointer)); |
|
2384 |
|
2385 // use special form of Cancel() to make sure we complete while |
|
2386 // reporting the correct error code. Using this means owned operation |
|
2387 // classes must be explicitly deleted here. |
|
2388 CancelToMigrate(); |
|
2389 |
|
2390 // delete the mobility manager |
|
2391 delete iMobilityManager; |
|
2392 iMobilityManager = NULL; |
|
2393 |
|
2394 // delete operation classes |
|
2395 delete iPopRefreshMailbox; |
|
2396 iPopRefreshMailbox = NULL; |
|
2397 delete iPopCopyMove; |
|
2398 iPopCopyMove = NULL; |
|
2399 delete iPopDelete; |
|
2400 iPopDelete = NULL; |
|
2401 delete iPopTopPop; |
|
2402 iPopTopPop = NULL; |
|
2403 |
|
2404 // and the session |
|
2405 delete iPopSession; |
|
2406 iPopSession = NULL; |
|
2407 |
|
2408 // and the session manager - error might be a result of the RConnection |
|
2409 delete iSessionManager; |
|
2410 iSessionManager = NULL; |
|
2411 |
|
2412 // tidyup |
|
2413 iState.iQuitting = EFalse; |
|
2414 TRAP_IGNORE( DoShowMessagesL(EFalse) ); |
|
2415 |
|
2416 TInt err = iServerEntry->SetEntry( iServiceId ); |
|
2417 if(err == KErrNone) |
|
2418 { |
|
2419 TMsvEntry entry = iServerEntry->Entry(); |
|
2420 entry.SetConnected( EFalse ); |
|
2421 iServerEntry->ChangeEntry( entry ); // ignore any error |
|
2422 } |
|
2423 |
|
2424 // If their is an outstanding command, then complete it with the error |
|
2425 CommandComplete( KErrDisconnected ); |
|
2426 |
|
2427 // final tidyup |
|
2428 iServerEntry->SetEntry(KMsvNullIndexEntryId); |
|
2429 iState.iCurrentOperation = EPopDisconnected; |
|
2430 } |
|
2431 |
|
2432 /** |
|
2433 Returns Progress info for Migration purposes |
|
2434 */ |
|
2435 const TDesC8& CImppServerMtm::MobilityProgress() |
|
2436 { |
|
2437 return Progress(); |
|
2438 } |
|
2439 |
|
2440 /** |
|
2441 Gets MTM information that is not related to the current operation |
|
2442 |
|
2443 @param aMtmDataType Type of data to fetch |
|
2444 @param aMtmDataBuffer On return this points to a descriptor holding the data |
|
2445 |
|
2446 @return KErrNone if successful, or a system wide error code |
|
2447 */ |
|
2448 TInt CImppServerMtm::GetNonOperationMtmData(TNonOperationMtmDataType aMtmDataType, TPtrC8& aMtmDataBuffer) |
|
2449 { |
|
2450 if (aMtmDataType == EMtmDataAccessPointId) |
|
2451 { |
|
2452 if (iSessionManager) |
|
2453 { |
|
2454 TNonOperationMtmDataAccessPointId mtmDataAccessPointId; |
|
2455 |
|
2456 TInt err = iSessionManager->GetAccessPointIdForConnection(mtmDataAccessPointId.iAccessPointId); |
|
2457 |
|
2458 if (err == KErrNone) |
|
2459 { |
|
2460 iMtmDataAccessPointIdBuffer = TNonOperationMtmDataAccessPointIdBuffer(mtmDataAccessPointId); |
|
2461 aMtmDataBuffer.Set(iMtmDataAccessPointIdBuffer); |
|
2462 return KErrNone; |
|
2463 } |
|
2464 } |
|
2465 |
|
2466 return KErrNotFound; |
|
2467 } |
|
2468 return KErrNotSupported; |
|
2469 } |
|
2470 |
|
2471 /** |
|
2472 Creates the mobility manager and registers the RConnection for notification of |
|
2473 bearer migration events, if the necessary conditions are met. |
|
2474 |
|
2475 Returns ETrue if mobility enabled and the initial carrier has been rejected. |
|
2476 |
|
2477 @param aError completion code of the session connect async operation |
|
2478 @return ETrue if the initial carrier has been rejected (DoRunL should return) |
|
2479 EFalse otherwise, DoRunL processing should continue |
|
2480 */ |
|
2481 TBool CImppServerMtm::StartBearerMobilityL(TInt aError) |
|
2482 { |
|
2483 // Connection operation complete. If the account supports bearer mobility |
|
2484 // register now for bearer event notifications. |
|
2485 if (iPopSettings->BearerMobility() && iIAPPreferences->SNAPDefined()) |
|
2486 { |
|
2487 // only create iMobilityManager once per connection request - we can be at this |
|
2488 // point due an initial carrier rejected followed by successful migration... |
|
2489 // also, check that the session manager has an RConnection. If not, bomb out. |
|
2490 if (!iMobilityManager && iSessionManager->HasConnection()) |
|
2491 { |
|
2492 iMobilityManager = CImMobilityManager::NewL(KUidPop3ServerMtm, iServiceId, *this); |
|
2493 iMobilityManager->SetConnection(iSessionManager->GetConnection()); |
|
2494 |
|
2495 // if there has been a problem connecting the session, reject the current carrier |
|
2496 // via the migration manager, and wait for a new bearer available notification. |
|
2497 if (aError != KErrNone) |
|
2498 { |
|
2499 iMigrationState = EWaitingCarrierRejected; |
|
2500 iMobilityManager->NewCarrierRejected(); |
|
2501 |
|
2502 // do not set waiting if NewCarrierActive has been called synchronously. |
|
2503 if (iMigrationState == EWaitingCarrierRejected) |
|
2504 { |
|
2505 // Now in a waiting state, set self active |
|
2506 iStatus = KRequestPending; |
|
2507 SetActive(); |
|
2508 } |
|
2509 return ETrue; |
|
2510 } // end if (eCode != KErrNone) |
|
2511 } // end if (!iMobilityManager && iSessionManager->HasConnection()) |
|
2512 } // end if (iPopSettings->BearerMobility() && iIAPPreferences->SNAPDefined()) |
|
2513 return EFalse; |
|
2514 } |