|
1 // Copyright (c) 1998-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 <miutset.h> |
|
17 #include <mtclreg.h> |
|
18 #include <msvids.h> |
|
19 #include <miutset.h> |
|
20 #include <commdb.h> |
|
21 #include <mtclbase.h> |
|
22 #include "IMAPSET.H" |
|
23 #include "IMAPCMDS.H" |
|
24 #include "CONSYNC.H" |
|
25 #include "MIUT_ERR.H" |
|
26 #include "ImapConnectionObserver.H" // MMsvImapConnectionObserver |
|
27 #include <cemailaccounts.h> |
|
28 |
|
29 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS |
|
30 #include "msvconsts.h" |
|
31 #include "miut_errconsts.h" |
|
32 #endif |
|
33 |
|
34 const TInt KImapIdleProgressRate =300000000; // 5 minutes |
|
35 const TInt KImapDefaultProgressRate =0xF0000; // approx 1sex |
|
36 |
|
37 // static |
|
38 CImapConnectAndSyncOp* CImapConnectAndSyncOp::NewL( CMsvSession& aSession, const CMsvEntrySelection& aSelection, |
|
39 CBaseMtm& aBaseMtm, TInt aPriority, |
|
40 TRequestStatus& aStatus, |
|
41 TImapConnectionCompletionState aCompletionState, |
|
42 MMsvImapConnectionObserver* aConnectionObserver) |
|
43 // |
|
44 // |
|
45 // |
|
46 { |
|
47 CImapConnectAndSyncOp* self=new(ELeave) CImapConnectAndSyncOp(aSession, aSelection, aBaseMtm, aPriority, aStatus, aCompletionState, aConnectionObserver); |
|
48 CleanupStack::PushL(self); |
|
49 self->ConstructL(aSelection); |
|
50 CleanupStack::Pop(); // self |
|
51 return self; |
|
52 } |
|
53 |
|
54 CImapConnectAndSyncOp::CImapConnectAndSyncOp(CMsvSession& aSession, const CMsvEntrySelection& aSelection, |
|
55 CBaseMtm& aBaseMtm, TInt aPriority, |
|
56 TRequestStatus& aStatus, |
|
57 TImapConnectionCompletionState aCompletionState, |
|
58 MMsvImapConnectionObserver* aConnectionObserver) |
|
59 : CMsvOperation(aSession, aPriority, aStatus), |
|
60 iBaseMtm(aBaseMtm), |
|
61 iConnectionObserver(aConnectionObserver), |
|
62 iCompletionState(aCompletionState) |
|
63 // |
|
64 // |
|
65 // |
|
66 { |
|
67 iService=aSelection.At(0); |
|
68 iMtm=KUidMsgTypeIMAP4; |
|
69 } |
|
70 |
|
71 void CImapConnectAndSyncOp::ConstructL(const CMsvEntrySelection& aSelection) |
|
72 // |
|
73 // |
|
74 // |
|
75 { |
|
76 iServiceEntry = CMsvEntry::NewL(iMsvSession, iService, TMsvSelectionOrdering()); |
|
77 iServiceEntry->SetEntryL(iService); |
|
78 iServiceEntry->AddObserverL(*this); |
|
79 CActiveScheduler::Add(this); |
|
80 |
|
81 iProgressTimer = CProgressTimer::NewL(*this); |
|
82 iRefreshTimer = CRefreshTimer::NewL(*this); |
|
83 |
|
84 // Need to restore the imap settings to get the refresh rate. This rate will |
|
85 // persist for the life time of this connect and sync op. |
|
86 CImImap4Settings* settings = new (ELeave) CImImap4Settings(); |
|
87 CleanupStack::PushL(settings); |
|
88 |
|
89 CEmailAccounts* account = CEmailAccounts::NewLC(); |
|
90 TImapAccount id; |
|
91 account->GetImapAccountL(iServiceEntry->Entry().Id(), id); |
|
92 account->LoadImapSettingsL(id, *settings); |
|
93 |
|
94 iRefreshRate = settings->SyncRate(); |
|
95 CleanupStack::PopAndDestroy(2, settings); // account, settings |
|
96 |
|
97 // Start the connection operation |
|
98 iSelection = aSelection.CopyL(); |
|
99 TBuf8<4> buf; |
|
100 iOperation = iBaseMtm.InvokeAsyncFunctionL(KIMAP4MTMConnectAndSynchronise, *iSelection, buf, iStatus); |
|
101 SetActive(); |
|
102 iState = EConnecting; |
|
103 iObserverRequestStatus=KRequestPending; |
|
104 iProgress().iSyncProgress.iState=TImap4SyncProgress::EConnecting; |
|
105 } |
|
106 |
|
107 CImapConnectAndSyncOp::~CImapConnectAndSyncOp() |
|
108 // |
|
109 // |
|
110 // |
|
111 { |
|
112 if (!IsActive() && iState!=ENotStarted && iState!=ECompleted) |
|
113 Completed(KErrCancel); |
|
114 Cancel(); |
|
115 delete iServiceEntry; |
|
116 delete iOperation; |
|
117 delete iSelection; |
|
118 delete iRefreshTimer;//.Close(); |
|
119 delete iProgressTimer; |
|
120 }; |
|
121 |
|
122 |
|
123 // |
|
124 // |
|
125 // |
|
126 void CImapConnectAndSyncOp::DoRefreshInboxL() |
|
127 { |
|
128 // If this operation is not already doing something, |
|
129 // make it check the local inbox for new mail. |
|
130 // |
|
131 if( !iOperation && iState==EWaiting ) |
|
132 { |
|
133 // check that we can do a forced sync |
|
134 if( iMsvSession.ServiceActive(iService) ) |
|
135 { |
|
136 // The server MTM is active and therefore the forced sync cannot be |
|
137 // done - set off the refresh timer again. |
|
138 ResetRefreshTimer(); |
|
139 } |
|
140 else |
|
141 { |
|
142 // start a forced sync of inbox |
|
143 TBuf8<4> buf; |
|
144 TRAPD(err,iOperation=iBaseMtm.InvokeAsyncFunctionL(KIMAP4MTMInboxNewSync, *iSelection, buf, iStatus)); |
|
145 if( err ) |
|
146 { |
|
147 // Couldn't start operation, but we are active and pending - |
|
148 // take the connection down. |
|
149 Cancel(); |
|
150 return; |
|
151 } |
|
152 iState = EForcedSyncing; |
|
153 } |
|
154 } |
|
155 } |
|
156 |
|
157 |
|
158 const TDesC8& CImapConnectAndSyncOp::ProgressL() |
|
159 // |
|
160 // |
|
161 // |
|
162 { |
|
163 // Deal with states where we don't need to do anything particularly special |
|
164 switch(iState) |
|
165 { |
|
166 case ENotStarted: |
|
167 case ECompleted: |
|
168 case EDisconnectingOnTimeout: |
|
169 return iProgress; |
|
170 default: // Keep GCC happy |
|
171 break; |
|
172 }; |
|
173 |
|
174 TInt serviceErr=GetServiceProgress(); |
|
175 if(serviceErr || (iProgress().iGenericProgress.iState==TImap4GenericProgress::EDisconnected && |
|
176 iProgress().iGenericProgress.iOperation!=TImap4GenericProgress::EDisconnect)) |
|
177 { |
|
178 // Check to see if the error is due to this operation. |
|
179 if( iState == EWaiting && iMsvSession.ServiceActive(iService) ) |
|
180 { |
|
181 // Ok there's an operation in the service which is not for this |
|
182 // service (as in Waiting state) - therefore error was for them |
|
183 // and not this operation. |
|
184 iProgress().iGenericProgress.iErrorCode = KErrNone; |
|
185 } |
|
186 |
|
187 // Need to'cancel' ourselves here - this will NOT complete the observer |
|
188 // do that later. |
|
189 iForcedCancel = ETrue; |
|
190 Cancel(); |
|
191 iStatus = serviceErr; |
|
192 Completed(serviceErr); |
|
193 } |
|
194 |
|
195 TInt syncProgressState=iProgress().iSyncProgress.iState; |
|
196 |
|
197 switch(iState) |
|
198 { |
|
199 case EConnecting: |
|
200 case EForcedSyncing: |
|
201 // active - return the operation's progress |
|
202 return iOperation->ProgressL(); |
|
203 |
|
204 // to provide sufficient information to our observer (if we have |
|
205 // one), the first sync is broken into three stages. |
|
206 |
|
207 case EFirstSyncingUpdatingInbox: |
|
208 // syncProgressState ought to be ESyncInbox at this point |
|
209 if(syncProgressState==TImap4SyncProgress::ESyncInbox) |
|
210 { |
|
211 // as expected - just reset progress timer and return |
|
212 ResetProgressTimer(); |
|
213 break; |
|
214 } |
|
215 |
|
216 // We're not syncing the inbox...perhaps we're updating the folder list |
|
217 iState=EFirstSyncingUpdatingFolderList; |
|
218 UpdateObserver(); // We've changed state - let our observer know. |
|
219 // Fall through... |
|
220 |
|
221 case EFirstSyncingUpdatingFolderList: |
|
222 // progressState ought to be EFolderTreeSync at this point |
|
223 if(syncProgressState==TImap4SyncProgress::ESyncFolderTree) |
|
224 { |
|
225 // as expected - just reset progress timer and return |
|
226 ResetProgressTimer(); |
|
227 break; |
|
228 } |
|
229 |
|
230 // We're not updating the folder list...perhaps we're updating the folders |
|
231 iState=EFirstSyncingUpdatingFolders; |
|
232 UpdateObserver(); // We've changed state - let our observer know. |
|
233 // Fall through... |
|
234 |
|
235 case EFirstSyncingUpdatingFolders: |
|
236 ResetProgressTimer(); |
|
237 if(syncProgressState==TImap4SyncProgress::EIdle) |
|
238 { |
|
239 // Transition between end of background sync and |
|
240 // periodic inbox checking state |
|
241 if(iCompletionState==EAfterFullSync) |
|
242 { |
|
243 iState=ECompletingSelf; |
|
244 TRequestStatus* status=&iStatus; |
|
245 iStatus=KRequestPending; |
|
246 User::RequestComplete(status,KErrNone); |
|
247 |
|
248 // NOTE - the active object is already active and so no need |
|
249 // to call SetActive() again. |
|
250 __ASSERT_DEBUG( IsActive(), User::Invariant() ); |
|
251 } |
|
252 else |
|
253 { |
|
254 ResetRefreshTimer(); |
|
255 iState=EWaiting; |
|
256 UpdateObserver(); // notify observer as state has changed |
|
257 } |
|
258 }; |
|
259 break; |
|
260 case EWaiting: |
|
261 { |
|
262 // check for idle timeout |
|
263 if(!iTimeout || iProgress().iGenericProgress.iState!=TImap4GenericProgress::EIdle) |
|
264 { |
|
265 // Either... |
|
266 // !iTimeout, in which case the timeout needs to be set for the first time |
|
267 // or.. Server is doing something, so reset the timer |
|
268 if( iIdleTimeout.Int()<=0 ) |
|
269 { |
|
270 // As idle timeout is less zero or -ve, don't timeout at all! |
|
271 iTimeout=EFalse; |
|
272 } |
|
273 else |
|
274 { |
|
275 iTimeout=ETrue; |
|
276 iTimeoutAt.UniversalTime(); |
|
277 iTimeoutAt=iTimeoutAt+iIdleTimeout; |
|
278 } |
|
279 } |
|
280 TTime currentTime; |
|
281 currentTime.UniversalTime(); |
|
282 if(currentTime>iTimeoutAt && iTimeout) |
|
283 { |
|
284 // Timed out - try to perform a disconnection. |
|
285 // |
|
286 TBuf8<1> buf; |
|
287 TRAPD(err,iOperation=iBaseMtm.InvokeAsyncFunctionL(KIMAP4MTMDisconnect, *iSelection, buf, iStatus)); |
|
288 if(err) |
|
289 Cancel(); |
|
290 else |
|
291 { |
|
292 iState=EDisconnectingOnTimeout; |
|
293 // NB no need to SetActive - this operation is ALREADY active. |
|
294 UpdateObserver(); |
|
295 } |
|
296 } |
|
297 else |
|
298 { |
|
299 if(iTimeout != EFalse) |
|
300 { |
|
301 // reset the progress timer |
|
302 iProgressTimer->Cancel(); |
|
303 iProgressTimer->After(KImapDefaultProgressRate); |
|
304 } |
|
305 else |
|
306 { |
|
307 iProgressTimer->Cancel(); |
|
308 iProgressTimer->After(KImapIdleProgressRate); |
|
309 } |
|
310 } |
|
311 }; |
|
312 break; |
|
313 default: |
|
314 break; |
|
315 } |
|
316 |
|
317 iSyncProgress()=iProgress().iSyncProgress; |
|
318 return iSyncProgress; |
|
319 } |
|
320 |
|
321 void CImapConnectAndSyncOp::ResetProgressTimer() |
|
322 { |
|
323 // reset the progress timer |
|
324 iProgressTimer->Cancel(); |
|
325 iProgressTimer->After(KImapDefaultProgressRate); |
|
326 } |
|
327 |
|
328 void CImapConnectAndSyncOp::UpdateObserver() const |
|
329 // |
|
330 // |
|
331 // |
|
332 { |
|
333 if(iConnectionObserver) |
|
334 { |
|
335 // We have an observer - signal them regarding our current state |
|
336 TImapConnectionEvent event; |
|
337 event=EConnectingToServer; // Assume connecting |
|
338 |
|
339 // Translate our new internal state into an event for the observer |
|
340 // |
|
341 switch(iState) |
|
342 { |
|
343 case ENotStarted: |
|
344 case EConnecting: |
|
345 // iState is already EConnectingToServer |
|
346 break; |
|
347 |
|
348 case EDisconnectingOnTimeout: |
|
349 event=EDisconnecting; |
|
350 break; |
|
351 |
|
352 case ECompleted: |
|
353 event=EConnectionCompleted; |
|
354 break; |
|
355 |
|
356 case EForcedSyncing: |
|
357 case EFirstSyncingUpdatingInbox: |
|
358 event=ESynchronisingInbox; |
|
359 break; |
|
360 |
|
361 case EFirstSyncingUpdatingFolderList: |
|
362 event=ESynchronisingFolderList; |
|
363 break; |
|
364 |
|
365 case EFirstSyncingUpdatingFolders: |
|
366 event=ESynchronisingFolders; |
|
367 break; |
|
368 |
|
369 case EWaiting: |
|
370 event=ESynchronisationComplete; |
|
371 break; |
|
372 |
|
373 default: |
|
374 // Should never get here |
|
375 gPanic(ESmtcMTMOperationNULL); //DS EImcmBadStateInConnectionOp |
|
376 break; |
|
377 } |
|
378 |
|
379 iConnectionObserver->HandleImapConnectionEvent(event); |
|
380 } |
|
381 } |
|
382 |
|
383 TInt CImapConnectAndSyncOp::GetServiceProgress() |
|
384 { |
|
385 TInt error = iMsvSession.ServiceProgress(iService, iProgress); |
|
386 if(error == KErrNone) |
|
387 error=iProgress().iGenericProgress.iErrorCode; |
|
388 if(error == KErrNone) |
|
389 error=iProgress().iSyncProgress.iErrorCode; |
|
390 |
|
391 if (error!= KErrNone) |
|
392 { |
|
393 switch (iState) |
|
394 { |
|
395 case EWaiting: |
|
396 case ECompleted: |
|
397 case ENotStarted: |
|
398 // CImapConnectAndSyncOp not really doing anything, so this error |
|
399 // comes from some other IMPS command and so should not be handled |
|
400 // by this operation. |
|
401 |
|
402 // Possible KErrIMAPNO response from server - warning, not error. |
|
403 if (error==KErrNotSupported) |
|
404 error=KErrNone; |
|
405 break; |
|
406 default: |
|
407 // Genuine error in CImapConnectAndSyncOp as it is currently doing |
|
408 // something useful... |
|
409 break; |
|
410 } |
|
411 } |
|
412 |
|
413 return error; |
|
414 } |
|
415 |
|
416 |
|
417 void CImapConnectAndSyncOp::Completed(TInt aError) |
|
418 { |
|
419 if(iState==ECompleted) |
|
420 return; |
|
421 |
|
422 TRequestStatus* observer=&iObserverRequestStatus; |
|
423 User::RequestComplete(observer, aError); |
|
424 iState=ECompleted; |
|
425 UpdateObserver(); |
|
426 } |
|
427 |
|
428 |
|
429 void CImapConnectAndSyncOp::DoCancel() |
|
430 { |
|
431 switch (iState) |
|
432 { |
|
433 case EConnecting: |
|
434 case EForcedSyncing: |
|
435 __ASSERT_DEBUG(iOperation, gPanic(ESmtcMTMOperationNULL)); //DS EImcmNullOperation |
|
436 iOperation->Cancel(); |
|
437 // Stop the service, because it's possible that iOperation has completed and so we have |
|
438 // no handle on the server MTM behaviour which may be performing background sync |
|
439 iMsvSession.StopService(iService); |
|
440 break; |
|
441 case EFirstSyncingUpdatingInbox: |
|
442 case EFirstSyncingUpdatingFolderList: |
|
443 case EFirstSyncingUpdatingFolders: |
|
444 case EWaiting: |
|
445 { |
|
446 if( !iForcedCancel ) |
|
447 iMsvSession.StopService(iService); |
|
448 |
|
449 // Complete ourselves (no one else will) |
|
450 TRequestStatus* myStatus=&iStatus; |
|
451 iStatus=KRequestPending; |
|
452 User::RequestComplete(myStatus,KErrCancel); |
|
453 }; |
|
454 break; |
|
455 default: |
|
456 break; |
|
457 } |
|
458 if (!iForcedCancel) |
|
459 Completed(KErrCancel); |
|
460 |
|
461 iProgressTimer->Cancel(); |
|
462 iRefreshTimer->Cancel(); |
|
463 } |
|
464 |
|
465 |
|
466 void CImapConnectAndSyncOp::RunL() |
|
467 // |
|
468 // |
|
469 // |
|
470 { |
|
471 if (iOperation) |
|
472 { |
|
473 iProgress.Copy(iOperation->ProgressL()); |
|
474 delete iOperation; |
|
475 iOperation=NULL; |
|
476 |
|
477 TInt error = iStatus.Int(); |
|
478 if (error==KErrNone) |
|
479 error=iProgress().iSyncProgress.iErrorCode; |
|
480 if (error==KErrNone) |
|
481 error=iProgress().iGenericProgress.iErrorCode; |
|
482 if (error!=KErrNone) |
|
483 { |
|
484 iProgress().iSyncProgress.iErrorCode=error; |
|
485 User::Leave(error); |
|
486 } |
|
487 } |
|
488 |
|
489 switch (iState) |
|
490 { |
|
491 case EConnecting: |
|
492 { |
|
493 if(iCompletionState==EAfterConnect) |
|
494 Completed(KErrNone); |
|
495 else |
|
496 { |
|
497 iMtm = KUidMsgTypeIMAP4; |
|
498 iState = EFirstSyncingUpdatingInbox; // IMAP server may or may not still be synchronising - assume that it is. |
|
499 UpdateObserver(); |
|
500 iStatus = KRequestPending; // so we still look pending to the OpWatcher |
|
501 ResetProgressTimer(); // Kick off the progress timer... |
|
502 SetActive(); // At next change of state, MUST NOT SetActive again. |
|
503 } |
|
504 |
|
505 // The socket timeout value was stored in iMtmData1 from Imps. |
|
506 iBaseMtm.Entry().SetEntryL(iService); |
|
507 TMsvEntry entry = iBaseMtm.Entry().Entry(); |
|
508 TInt32 socketTimeout = entry.MtmData1(); |
|
509 |
|
510 // Adjust the timeout to make sure that we disconnect the IMAP layer |
|
511 // *before* the socket underneath us times out. |
|
512 const TUint KTimeOutPercentage = 80; // Arbitrarily choose 80% - should be enough |
|
513 iIdleTimeout = (socketTimeout * KTimeOutPercentage)/100; |
|
514 break; |
|
515 } |
|
516 case EForcedSyncing: |
|
517 // move back to waiting |
|
518 iState = EWaiting; |
|
519 UpdateObserver(); |
|
520 iStatus = KRequestPending; |
|
521 SetActive(); // At next change of state, MUST NOT SetActive again. |
|
522 ResetRefreshTimer(); |
|
523 ResetProgressTimer(); |
|
524 break; |
|
525 case EDisconnectingOnTimeout: |
|
526 iProgress().iSyncProgress.iErrorCode=KErrTimedOut; |
|
527 Completed(KErrNone); |
|
528 break; |
|
529 case EFirstSyncingUpdatingInbox: |
|
530 case EFirstSyncingUpdatingFolderList: |
|
531 case EFirstSyncingUpdatingFolders: |
|
532 case EWaiting: |
|
533 iProgress().iSyncProgress.iErrorCode=KErrCancel; |
|
534 Completed(KErrCancel); |
|
535 break; |
|
536 case ECompletingSelf: |
|
537 Completed(KErrNone); |
|
538 break; |
|
539 default: // i.e. ECompleted: |
|
540 __ASSERT_DEBUG(EFalse, gPanic(ESmtcMTMOperationNULL)); //DS EImcmBadStateInConnectionOp |
|
541 break; |
|
542 } |
|
543 } |
|
544 |
|
545 TInt CImapConnectAndSyncOp::RunError(TInt aError) |
|
546 { |
|
547 Completed(aError); |
|
548 return KErrNone; |
|
549 } |
|
550 |
|
551 void CImapConnectAndSyncOp::HandleEntryEventL(TMsvEntryEvent aEvent, TAny* /*aArg1*/, TAny* /*aArg2*/, TAny* /*aArg3*/) |
|
552 { |
|
553 if(aEvent == MMsvEntryObserver::EMsvEntryChanged) |
|
554 { |
|
555 ProgressL(); |
|
556 } |
|
557 } |
|
558 |
|
559 void CImapConnectAndSyncOp::ResetRefreshTimer() |
|
560 { |
|
561 // Only start the timer if the rate is greater than zero. A value of zero |
|
562 // (or less) indicates that the inbox should not be refreshed. |
|
563 if( iRefreshRate.Int() > 0 ) |
|
564 { |
|
565 TTime refreshTime; |
|
566 refreshTime.UniversalTime(); |
|
567 refreshTime += iRefreshRate; |
|
568 |
|
569 iRefreshTimer->Cancel(); |
|
570 iRefreshTimer->AtUTC(refreshTime); |
|
571 } |
|
572 } |
|
573 |
|
574 /* |
|
575 * CProgressTimer |
|
576 */ |
|
577 |
|
578 CProgressTimer::CProgressTimer(CImapConnectAndSyncOp& aOperation) |
|
579 : CTimer(EPriorityLow), iOperation(aOperation) |
|
580 {} |
|
581 |
|
582 void CProgressTimer::RunL() |
|
583 { |
|
584 // we ignore error, as this is just used ensure that progress is called |
|
585 iOperation.ProgressL(); |
|
586 } |
|
587 |
|
588 TInt CProgressTimer::RunError(TInt /*aError*/) |
|
589 { |
|
590 // Do nothing... |
|
591 return KErrNone; |
|
592 } |
|
593 |
|
594 CProgressTimer* CProgressTimer::NewL(CImapConnectAndSyncOp& aOperation) |
|
595 { |
|
596 CProgressTimer* self = new(ELeave) CProgressTimer(aOperation); |
|
597 CleanupStack::PushL(self); |
|
598 self->ConstructL(); // CTimer |
|
599 CActiveScheduler::Add(self); |
|
600 CleanupStack::Pop(); |
|
601 return self; |
|
602 } |
|
603 |
|
604 /* |
|
605 * CRefreshTimer |
|
606 */ |
|
607 |
|
608 CRefreshTimer::CRefreshTimer(CImapConnectAndSyncOp& aOperation) |
|
609 : CTimer(EPriorityLow), iOperation(aOperation) |
|
610 {} |
|
611 |
|
612 void CRefreshTimer::RunL() |
|
613 { |
|
614 // we ignore error, as this is just used ensure that progress is called |
|
615 iOperation.DoRefreshInboxL(); |
|
616 } |
|
617 |
|
618 TInt CRefreshTimer::RunError(TInt /*aError*/) |
|
619 { |
|
620 // Do nothing... |
|
621 return KErrNone; |
|
622 } |
|
623 |
|
624 CRefreshTimer* CRefreshTimer::NewL(CImapConnectAndSyncOp& aOperation) |
|
625 { |
|
626 CRefreshTimer* self = new(ELeave) CRefreshTimer(aOperation); |
|
627 CleanupStack::PushL(self); |
|
628 self->ConstructL(); // CTimer |
|
629 CActiveScheduler::Add(self); |
|
630 CleanupStack::Pop(); |
|
631 return self; |
|
632 } |
|
633 |