25
|
1 |
/*
|
|
2 |
* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
|
|
3 |
* All rights reserved.
|
|
4 |
* This component and the accompanying materials are made available
|
|
5 |
* under the terms of "Eclipse Public License v1.0"
|
|
6 |
* which accompanies this distribution, and is available
|
|
7 |
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
|
8 |
*
|
|
9 |
* Initial Contributors:
|
|
10 |
* Nokia Corporation - initial contribution.
|
|
11 |
*
|
|
12 |
* Contributors:
|
|
13 |
*
|
|
14 |
* Description: This file implements class CFSNotificationHandlerBase.
|
|
15 |
*
|
|
16 |
*/
|
|
17 |
|
|
18 |
#include <centralrepository.h>
|
|
19 |
#include "emailtrace.h"
|
|
20 |
#include "cfsmailclient.h"
|
|
21 |
|
|
22 |
#include "fsnotificationhandlermgr.h"
|
|
23 |
#include "fsnotificationhandlerbase.h"
|
|
24 |
#include "cmailhandlerpluginpanic.h"
|
|
25 |
#include "commonemailcrkeys.h"
|
|
26 |
#include "freestyleemailcenrepkeys.h"
|
|
27 |
#include "FreestyleEmailUiConstants.h"
|
|
28 |
|
|
29 |
|
|
30 |
const TInt KTimerDelay = 20;
|
|
31 |
|
|
32 |
// ======== MEMBER FUNCTIONS ========
|
|
33 |
|
|
34 |
CFSNotificationHandlerBase::CFSNotificationHandlerBase(
|
|
35 |
MFSNotificationHandlerMgr& aOwner ) :
|
|
36 |
iOwner( aOwner ),
|
|
37 |
iObserving( EFalse )
|
|
38 |
{
|
|
39 |
FUNC_LOG;
|
|
40 |
}
|
|
41 |
|
|
42 |
void CFSNotificationHandlerBase::ConstructL()
|
|
43 |
{
|
|
44 |
FUNC_LOG;
|
|
45 |
|
|
46 |
iTimer = CNewMailNotificationTimer::NewL( *this );
|
|
47 |
}
|
|
48 |
|
|
49 |
CFSNotificationHandlerBase::~CFSNotificationHandlerBase()
|
|
50 |
{
|
|
51 |
FUNC_LOG;
|
|
52 |
REComSession::DestroyedImplementation( iDestructorKey );
|
|
53 |
|
|
54 |
delete iTimer;
|
|
55 |
iNewInboxEntries.Reset();
|
|
56 |
}
|
|
57 |
|
|
58 |
CFSMailClient& CFSNotificationHandlerBase::MailClient() const
|
|
59 |
{
|
|
60 |
FUNC_LOG;
|
|
61 |
return iOwner.MailClient();
|
|
62 |
}
|
|
63 |
void CFSNotificationHandlerBase::EventL( TFSMailEvent aEvent, TFSMailMsgId aMailbox,
|
|
64 |
TAny* aParam1, TAny* aParam2, TAny* aParam3 )
|
|
65 |
{
|
|
66 |
FUNC_LOG;
|
|
67 |
if ( !iObserving )
|
|
68 |
{
|
|
69 |
return;
|
|
70 |
}
|
|
71 |
|
|
72 |
HandleEventL( aEvent, aMailbox, aParam1, aParam2, aParam3 );
|
|
73 |
}
|
|
74 |
|
|
75 |
|
|
76 |
|
|
77 |
void CFSNotificationHandlerBase::SetObserving( TBool aNewValue )
|
|
78 |
{
|
|
79 |
FUNC_LOG;
|
|
80 |
iObserving = aNewValue;
|
|
81 |
}
|
|
82 |
|
|
83 |
TBool CFSNotificationHandlerBase::MsgIsUnread( CFSMailMessage& aMessage ) const
|
|
84 |
{
|
|
85 |
FUNC_LOG;
|
|
86 |
TBool read( aMessage.IsFlagSet( EFSMsgFlag_Read ) );
|
|
87 |
TBool read_locally( aMessage.IsFlagSet( EFSMsgFlag_Read_Locally ) );
|
|
88 |
|
|
89 |
if ( !read && !read_locally )
|
|
90 |
{
|
|
91 |
return ETrue;
|
|
92 |
}
|
|
93 |
else
|
|
94 |
{
|
|
95 |
return EFalse;
|
|
96 |
}
|
|
97 |
}
|
|
98 |
|
|
99 |
TBool CFSNotificationHandlerBase::MessagesCauseNotificationL( TFSMailMsgId aMailboxId,
|
|
100 |
TFSMailMsgId aParentFolderId,
|
|
101 |
const RArray<TFSMailMsgId>& aMsgIdList )
|
|
102 |
{
|
|
103 |
FUNC_LOG;
|
|
104 |
|
|
105 |
CFSMailFolder* parentFolder(
|
|
106 |
MailClient().GetFolderByUidL( aMailboxId, aParentFolderId ) );
|
|
107 |
User::LeaveIfNull( parentFolder );
|
|
108 |
CleanupStack::PushL( parentFolder );
|
|
109 |
|
|
110 |
CFSMailMessage* newestMsg( NULL );
|
|
111 |
TRAPD( notFoundError,
|
|
112 |
newestMsg =
|
|
113 |
NewestMsgInFolderL( *parentFolder ) );
|
|
114 |
if ( notFoundError == KErrNotFound )
|
|
115 |
{
|
|
116 |
// For some odd reason we are not able to get the newest
|
|
117 |
// message from the folder. This should not be possible
|
|
118 |
// as we just received notification of a new message.
|
|
119 |
// Possibly something has moved/deleted the message?
|
|
120 |
return EFalse;
|
|
121 |
}
|
|
122 |
User::LeaveIfError( notFoundError );
|
|
123 |
|
|
124 |
TTime dateOfNewest( newestMsg->GetDate() );
|
|
125 |
|
|
126 |
delete newestMsg;
|
|
127 |
newestMsg = NULL;
|
|
128 |
|
|
129 |
CleanupStack::PopAndDestroy( parentFolder );
|
|
130 |
|
|
131 |
const TInt entriesCount( aMsgIdList.Count() );
|
|
132 |
TInt index( entriesCount-1 );
|
|
133 |
// go from back of list, as messages are coming from earliest to latest..
|
|
134 |
while ( index >= 0 )
|
|
135 |
{
|
|
136 |
// Let's get the message. We need to check from it that
|
|
137 |
// it is really unread. This info is stored in the
|
|
138 |
// flags. Also check that the message is newest.
|
|
139 |
// EFSMsgDataEnvelope is used as TFSMailDetails
|
|
140 |
// so that we get enough data.
|
|
141 |
CFSMailMessage*
|
|
142 |
currentMessage( MailClient().GetMessageByUidL(
|
|
143 |
aMailboxId,
|
|
144 |
aParentFolderId,
|
|
145 |
aMsgIdList[index],
|
|
146 |
EFSMsgDataEnvelope ) );
|
|
147 |
User::LeaveIfNull( currentMessage );
|
|
148 |
const TTime dateOfCurrentMsg( currentMessage->GetDate() );
|
|
149 |
|
|
150 |
|
|
151 |
const TBool msgIsUnread( MsgIsUnread( *currentMessage ) );
|
|
152 |
delete currentMessage;
|
|
153 |
currentMessage = NULL;
|
|
154 |
|
|
155 |
if ( msgIsUnread &&
|
|
156 |
( dateOfCurrentMsg >= dateOfNewest ) )
|
|
157 |
{
|
|
158 |
// At least one of the messages is unread and newest.
|
|
159 |
return ETrue;
|
|
160 |
}
|
|
161 |
|
|
162 |
--index;
|
|
163 |
}
|
|
164 |
|
|
165 |
return EFalse;
|
|
166 |
}
|
|
167 |
|
|
168 |
TBool CFSNotificationHandlerBase::Observing() const
|
|
169 |
{
|
|
170 |
FUNC_LOG;
|
|
171 |
return iObserving;
|
|
172 |
}
|
|
173 |
|
|
174 |
TBool CFSNotificationHandlerBase::CapabilitiesToContinueL(
|
|
175 |
TFSMailEvent aEvent,
|
|
176 |
TFSMailMsgId aMailbox,
|
|
177 |
TAny* /*aParam1*/,
|
|
178 |
TAny* /*aParam2*/,
|
|
179 |
TAny* /*aParam3*/ ) const
|
|
180 |
{
|
|
181 |
FUNC_LOG;
|
|
182 |
if ( aEvent != TFSEventMailboxDeleted )
|
|
183 |
{
|
|
184 |
CFSMailBox* mailBox( MailClient().GetMailBoxByUidL( aMailbox ) );
|
|
185 |
if ( mailBox == NULL )
|
|
186 |
{
|
|
187 |
User::Leave( KErrArgument );
|
|
188 |
}
|
|
189 |
|
|
190 |
if ( mailBox->HasCapability( EFSMBoxCapaNewEmailNotifications ) )
|
|
191 |
{
|
|
192 |
delete mailBox;
|
|
193 |
return EFalse;
|
|
194 |
}
|
|
195 |
else
|
|
196 |
{
|
|
197 |
delete mailBox;
|
|
198 |
return ETrue;
|
|
199 |
}
|
|
200 |
}
|
|
201 |
else
|
|
202 |
{
|
|
203 |
return ETrue;
|
|
204 |
}
|
|
205 |
}
|
|
206 |
|
|
207 |
void CFSNotificationHandlerBase::HandleEventL(
|
|
208 |
TFSMailEvent aEvent,
|
|
209 |
TFSMailMsgId aMailbox,
|
|
210 |
TAny* aParam1,
|
|
211 |
TAny* aParam2,
|
|
212 |
TAny* /*aParam3*/ )
|
|
213 |
{
|
|
214 |
FUNC_LOG;
|
|
215 |
// Only event TFSEventNewMail means that the mail is completely new.
|
|
216 |
if ( aEvent == TFSEventNewMail )
|
|
217 |
{
|
|
218 |
// In case of TFSEventNewMail we have parent folder id
|
|
219 |
// in aParam2
|
|
220 |
TFSMailMsgId* parentFolderId( NULL );
|
|
221 |
parentFolderId = static_cast< TFSMailMsgId* >( aParam2 );
|
|
222 |
if ( parentFolderId == NULL )
|
|
223 |
{
|
|
224 |
User::Leave( KErrArgument );
|
|
225 |
}
|
|
226 |
|
|
227 |
// Set the notification on only in cases that the new mail is
|
|
228 |
// in folder of type EFSInbox
|
|
229 |
if ( iOwner.GetFolderTypeL( aMailbox, parentFolderId ) == EFSInbox )
|
|
230 |
{
|
|
231 |
RArray<TFSMailMsgId>* newEntries(
|
|
232 |
static_cast< RArray<TFSMailMsgId>* >( aParam1 ) );
|
|
233 |
|
|
234 |
TInt count = newEntries->Count();
|
|
235 |
for ( TInt i = 0; i<count;i++ )
|
|
236 |
{
|
|
237 |
TFSMailMsgId msgId = newEntries->operator []( i );
|
|
238 |
TNewMailInfo info( msgId, aMailbox, *parentFolderId );
|
|
239 |
iNewInboxEntries.AppendL( info );
|
|
240 |
}
|
|
241 |
|
|
242 |
if (iTimer->IsActive() )
|
|
243 |
{
|
|
244 |
iTimer->Cancel();
|
|
245 |
}
|
|
246 |
iTimer->After( KTimerDelay );
|
|
247 |
}
|
|
248 |
else
|
|
249 |
{
|
|
250 |
// If messages are in some other folder than in inbox
|
|
251 |
// they have no effect on the notification
|
|
252 |
}
|
|
253 |
}
|
|
254 |
else
|
|
255 |
{
|
|
256 |
// No other events than new mail are handled. For example
|
|
257 |
// moving of messages and changing message status has no
|
|
258 |
// effect on the notification.
|
|
259 |
}
|
|
260 |
}
|
|
261 |
|
|
262 |
void CFSNotificationHandlerBase::TimerExpiredL()
|
|
263 |
{
|
|
264 |
// process collected insert requests
|
|
265 |
RArray<TFSMailMsgId> msgIds;
|
|
266 |
TFSMailMsgId mailBoxId;
|
|
267 |
TFSMailMsgId parentFolderId;
|
|
268 |
for ( TInt i = 0; i< iNewInboxEntries.Count(); i++ )
|
|
269 |
{
|
|
270 |
TNewMailInfo& info = iNewInboxEntries[ i ];
|
|
271 |
if ( mailBoxId.IsNullId() && parentFolderId.IsNullId() )
|
|
272 |
{
|
|
273 |
// starting new group is starting to collect
|
|
274 |
mailBoxId = info.iMailBox;
|
|
275 |
parentFolderId = info.iParentFolderId;
|
|
276 |
}
|
|
277 |
if ( mailBoxId == info.iMailBox && parentFolderId == info.iParentFolderId )
|
|
278 |
{
|
|
279 |
// collect message ids for the same mailbox and parent folder
|
|
280 |
msgIds.Append( info.iMsgId );
|
|
281 |
}
|
|
282 |
else
|
|
283 |
{
|
|
284 |
// process collected message ids for the same mailbox and parent folder
|
|
285 |
if ( msgIds.Count()&& MessagesCauseNotificationL( mailBoxId, parentFolderId, msgIds ) )
|
|
286 |
{
|
|
287 |
TurnNotificationOn();
|
|
288 |
}
|
|
289 |
// clear data and start collecting again
|
|
290 |
msgIds.Reset();
|
|
291 |
mailBoxId = TFSMailMsgId();
|
|
292 |
parentFolderId = TFSMailMsgId();
|
|
293 |
}
|
|
294 |
}
|
|
295 |
// process collected message ids for the same mailbox and parent folder
|
|
296 |
if ( msgIds.Count() && MessagesCauseNotificationL( mailBoxId, parentFolderId, msgIds ) )
|
|
297 |
{
|
|
298 |
TurnNotificationOn();
|
|
299 |
}
|
|
300 |
// clear processed entries
|
|
301 |
msgIds.Reset();
|
|
302 |
iNewInboxEntries.Reset();
|
|
303 |
}
|
|
304 |
|
|
305 |
CFSMailMessage* CFSNotificationHandlerBase::NewestMsgInFolderL(
|
|
306 |
CFSMailFolder& aFolder ) const
|
|
307 |
{
|
|
308 |
FUNC_LOG;
|
|
309 |
// Load info only necessary for sorting by date into the messages.
|
|
310 |
TFSMailDetails details( EFSMsgDataDate );
|
|
311 |
|
|
312 |
// Want to sort mails so that the newest is in the beginning
|
|
313 |
TFSMailSortCriteria criteriaDate;
|
|
314 |
criteriaDate.iField = EFSMailSortByDate;
|
|
315 |
criteriaDate.iOrder = EFSMailDescending;
|
|
316 |
|
|
317 |
RArray<TFSMailSortCriteria> sorting;
|
|
318 |
CleanupClosePushL( sorting );
|
|
319 |
// First criteria appended would be the primary criteria
|
|
320 |
// but here we don't have any other criteria
|
|
321 |
sorting.Append( criteriaDate );
|
|
322 |
MFSMailIterator* iterator = aFolder.ListMessagesL( details, sorting );
|
|
323 |
|
|
324 |
// Resetting array of sort criteria already here because
|
|
325 |
// the iterator does not need it anymore.
|
|
326 |
CleanupStack::PopAndDestroy(); // sorting
|
|
327 |
|
|
328 |
// CleanupStack::PushL doesn't work for M-class
|
|
329 |
CleanupDeletePushL( iterator );
|
|
330 |
|
|
331 |
RPointerArray<CFSMailMessage> messages;
|
|
332 |
CleanupClosePushL( messages );
|
|
333 |
// Let's get only the first and therefore the newest message.
|
|
334 |
TInt amount( 1 );
|
|
335 |
iterator->NextL( TFSMailMsgId(), amount, messages );
|
|
336 |
if ( messages.Count() < 1 )
|
|
337 |
{
|
|
338 |
messages.ResetAndDestroy();
|
|
339 |
User::Leave( KErrNotFound );
|
|
340 |
}
|
|
341 |
|
|
342 |
CFSMailMessage* outcome = messages[0];
|
|
343 |
messages.Remove( 0 ); // remove from array to prevent destruction of element
|
|
344 |
messages.ResetAndDestroy();
|
|
345 |
CleanupStack::PopAndDestroy(); // messages
|
|
346 |
CleanupStack::PopAndDestroy( iterator );
|
|
347 |
return outcome;
|
|
348 |
}
|
|
349 |
|
|
350 |
CNewMailNotificationTimer::CNewMailNotificationTimer( MFSTimerObserver& aObserver ) :
|
|
351 |
CTimer( EPriorityIdle ), iObserver( aObserver )
|
|
352 |
{
|
|
353 |
FUNC_LOG;
|
|
354 |
}
|
|
355 |
|
|
356 |
void CNewMailNotificationTimer::ConstructL()
|
|
357 |
{
|
|
358 |
FUNC_LOG;
|
|
359 |
CTimer::ConstructL();
|
|
360 |
CActiveScheduler::Add( this );
|
|
361 |
}
|
|
362 |
|
|
363 |
CNewMailNotificationTimer* CNewMailNotificationTimer::NewL(
|
|
364 |
MFSTimerObserver& aObserver )
|
|
365 |
{
|
|
366 |
FUNC_LOG;
|
|
367 |
CNewMailNotificationTimer* self =
|
|
368 |
new( ELeave ) CNewMailNotificationTimer( aObserver );
|
|
369 |
CleanupStack::PushL( self );
|
|
370 |
self->ConstructL();
|
|
371 |
CleanupStack::Pop( self );
|
|
372 |
return self;
|
|
373 |
}
|
|
374 |
|
|
375 |
|
|
376 |
CNewMailNotificationTimer::~CNewMailNotificationTimer()
|
|
377 |
{
|
|
378 |
FUNC_LOG;
|
|
379 |
Cancel();
|
|
380 |
}
|
|
381 |
|
|
382 |
void CNewMailNotificationTimer::DoCancel()
|
|
383 |
{
|
|
384 |
FUNC_LOG;
|
|
385 |
// Cancel Base class
|
|
386 |
CTimer::DoCancel();
|
|
387 |
}
|
|
388 |
|
|
389 |
void CNewMailNotificationTimer::RunL()
|
|
390 |
{
|
|
391 |
FUNC_LOG;
|
|
392 |
iObserver.TimerExpiredL();
|
|
393 |
}
|
|
394 |
|
|
395 |
|
|
396 |
void Panic( TCmailhandlerPanic aPanic )
|
|
397 |
{
|
|
398 |
_LIT( KPanicText, "emailhandlerplugin" );
|
|
399 |
User::Panic( KPanicText, aPanic );
|
|
400 |
}
|
|
401 |
|
|
402 |
// End of file
|
|
403 |
|