emailservices/emailserver/cmailhandlerplugin/src/fsnotificationhandlerbaseimpl.cpp
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailserver/cmailhandlerplugin/src/fsnotificationhandlerbaseimpl.cpp Wed Sep 01 12:28:57 2010 +0100
@@ -0,0 +1,403 @@
+/*
+* Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: This file implements class CFSNotificationHandlerBase.
+*
+*/
+
+#include <centralrepository.h>
+#include "emailtrace.h"
+#include "cfsmailclient.h"
+
+#include "fsnotificationhandlermgr.h"
+#include "fsnotificationhandlerbase.h"
+#include "cmailhandlerpluginpanic.h"
+#include "commonemailcrkeys.h"
+#include "freestyleemailcenrepkeys.h"
+#include "FreestyleEmailUiConstants.h"
+
+
+const TInt KTimerDelay = 20;
+
+// ======== MEMBER FUNCTIONS ========
+
+CFSNotificationHandlerBase::CFSNotificationHandlerBase(
+ MFSNotificationHandlerMgr& aOwner ) :
+ iOwner( aOwner ),
+ iObserving( EFalse )
+ {
+ FUNC_LOG;
+ }
+
+void CFSNotificationHandlerBase::ConstructL()
+ {
+ FUNC_LOG;
+
+ iTimer = CNewMailNotificationTimer::NewL( *this );
+ }
+
+CFSNotificationHandlerBase::~CFSNotificationHandlerBase()
+ {
+ FUNC_LOG;
+ REComSession::DestroyedImplementation( iDestructorKey );
+
+ delete iTimer;
+ iNewInboxEntries.Reset();
+ }
+
+CFSMailClient& CFSNotificationHandlerBase::MailClient() const
+ {
+ FUNC_LOG;
+ return iOwner.MailClient();
+ }
+void CFSNotificationHandlerBase::EventL( TFSMailEvent aEvent, TFSMailMsgId aMailbox,
+ TAny* aParam1, TAny* aParam2, TAny* aParam3 )
+ {
+ FUNC_LOG;
+ if ( !iObserving )
+ {
+ return;
+ }
+
+ HandleEventL( aEvent, aMailbox, aParam1, aParam2, aParam3 );
+ }
+
+
+
+void CFSNotificationHandlerBase::SetObserving( TBool aNewValue )
+ {
+ FUNC_LOG;
+ iObserving = aNewValue;
+ }
+
+TBool CFSNotificationHandlerBase::MsgIsUnread( CFSMailMessage& aMessage ) const
+ {
+ FUNC_LOG;
+ TBool read( aMessage.IsFlagSet( EFSMsgFlag_Read ) );
+ TBool read_locally( aMessage.IsFlagSet( EFSMsgFlag_Read_Locally ) );
+
+ if ( !read && !read_locally )
+ {
+ return ETrue;
+ }
+ else
+ {
+ return EFalse;
+ }
+ }
+
+TBool CFSNotificationHandlerBase::MessagesCauseNotificationL( TFSMailMsgId aMailboxId,
+ TFSMailMsgId aParentFolderId,
+ const RArray<TFSMailMsgId>& aMsgIdList )
+ {
+ FUNC_LOG;
+
+ CFSMailFolder* parentFolder(
+ MailClient().GetFolderByUidL( aMailboxId, aParentFolderId ) );
+ User::LeaveIfNull( parentFolder );
+ CleanupStack::PushL( parentFolder );
+
+ CFSMailMessage* newestMsg( NULL );
+ TRAPD( notFoundError,
+ newestMsg =
+ NewestMsgInFolderL( *parentFolder ) );
+ if ( notFoundError == KErrNotFound )
+ {
+ // For some odd reason we are not able to get the newest
+ // message from the folder. This should not be possible
+ // as we just received notification of a new message.
+ // Possibly something has moved/deleted the message?
+ return EFalse;
+ }
+ User::LeaveIfError( notFoundError );
+
+ TTime dateOfNewest( newestMsg->GetDate() );
+
+ delete newestMsg;
+ newestMsg = NULL;
+
+ CleanupStack::PopAndDestroy( parentFolder );
+
+ const TInt entriesCount( aMsgIdList.Count() );
+ TInt index( entriesCount-1 );
+ // go from back of list, as messages are coming from earliest to latest..
+ while ( index >= 0 )
+ {
+ // Let's get the message. We need to check from it that
+ // it is really unread. This info is stored in the
+ // flags. Also check that the message is newest.
+ // EFSMsgDataEnvelope is used as TFSMailDetails
+ // so that we get enough data.
+ CFSMailMessage*
+ currentMessage( MailClient().GetMessageByUidL(
+ aMailboxId,
+ aParentFolderId,
+ aMsgIdList[index],
+ EFSMsgDataEnvelope ) );
+ User::LeaveIfNull( currentMessage );
+ const TTime dateOfCurrentMsg( currentMessage->GetDate() );
+
+
+ const TBool msgIsUnread( MsgIsUnread( *currentMessage ) );
+ delete currentMessage;
+ currentMessage = NULL;
+
+ if ( msgIsUnread &&
+ ( dateOfCurrentMsg >= dateOfNewest ) )
+ {
+ // At least one of the messages is unread and newest.
+ return ETrue;
+ }
+
+ --index;
+ }
+
+ return EFalse;
+ }
+
+TBool CFSNotificationHandlerBase::Observing() const
+ {
+ FUNC_LOG;
+ return iObserving;
+ }
+
+TBool CFSNotificationHandlerBase::CapabilitiesToContinueL(
+ TFSMailEvent aEvent,
+ TFSMailMsgId aMailbox,
+ TAny* /*aParam1*/,
+ TAny* /*aParam2*/,
+ TAny* /*aParam3*/ ) const
+ {
+ FUNC_LOG;
+ if ( aEvent != TFSEventMailboxDeleted )
+ {
+ CFSMailBox* mailBox( MailClient().GetMailBoxByUidL( aMailbox ) );
+ if ( mailBox == NULL )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ if ( mailBox->HasCapability( EFSMBoxCapaNewEmailNotifications ) )
+ {
+ delete mailBox;
+ return EFalse;
+ }
+ else
+ {
+ delete mailBox;
+ return ETrue;
+ }
+ }
+ else
+ {
+ return ETrue;
+ }
+ }
+
+void CFSNotificationHandlerBase::HandleEventL(
+ TFSMailEvent aEvent,
+ TFSMailMsgId aMailbox,
+ TAny* aParam1,
+ TAny* aParam2,
+ TAny* /*aParam3*/ )
+ {
+ FUNC_LOG;
+ // Only event TFSEventNewMail means that the mail is completely new.
+ if ( aEvent == TFSEventNewMail )
+ {
+ // In case of TFSEventNewMail we have parent folder id
+ // in aParam2
+ TFSMailMsgId* parentFolderId( NULL );
+ parentFolderId = static_cast< TFSMailMsgId* >( aParam2 );
+ if ( parentFolderId == NULL )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // Set the notification on only in cases that the new mail is
+ // in folder of type EFSInbox
+ if ( iOwner.GetFolderTypeL( aMailbox, parentFolderId ) == EFSInbox )
+ {
+ RArray<TFSMailMsgId>* newEntries(
+ static_cast< RArray<TFSMailMsgId>* >( aParam1 ) );
+
+ TInt count = newEntries->Count();
+ for ( TInt i = 0; i<count;i++ )
+ {
+ TFSMailMsgId msgId = newEntries->operator []( i );
+ TNewMailInfo info( msgId, aMailbox, *parentFolderId );
+ iNewInboxEntries.AppendL( info );
+ }
+
+ if (iTimer->IsActive() )
+ {
+ iTimer->Cancel();
+ }
+ iTimer->After( KTimerDelay );
+ }
+ else
+ {
+ // If messages are in some other folder than in inbox
+ // they have no effect on the notification
+ }
+ }
+ else
+ {
+ // No other events than new mail are handled. For example
+ // moving of messages and changing message status has no
+ // effect on the notification.
+ }
+ }
+
+void CFSNotificationHandlerBase::TimerExpiredL()
+ {
+ // process collected insert requests
+ RArray<TFSMailMsgId> msgIds;
+ TFSMailMsgId mailBoxId;
+ TFSMailMsgId parentFolderId;
+ for ( TInt i = 0; i< iNewInboxEntries.Count(); i++ )
+ {
+ TNewMailInfo& info = iNewInboxEntries[ i ];
+ if ( mailBoxId.IsNullId() && parentFolderId.IsNullId() )
+ {
+ // starting new group is starting to collect
+ mailBoxId = info.iMailBox;
+ parentFolderId = info.iParentFolderId;
+ }
+ if ( mailBoxId == info.iMailBox && parentFolderId == info.iParentFolderId )
+ {
+ // collect message ids for the same mailbox and parent folder
+ msgIds.Append( info.iMsgId );
+ }
+ else
+ {
+ // process collected message ids for the same mailbox and parent folder
+ if ( msgIds.Count()&& MessagesCauseNotificationL( mailBoxId, parentFolderId, msgIds ) )
+ {
+ TurnNotificationOn();
+ }
+ // clear data and start collecting again
+ msgIds.Reset();
+ mailBoxId = TFSMailMsgId();
+ parentFolderId = TFSMailMsgId();
+ }
+ }
+ // process collected message ids for the same mailbox and parent folder
+ if ( msgIds.Count() && MessagesCauseNotificationL( mailBoxId, parentFolderId, msgIds ) )
+ {
+ TurnNotificationOn();
+ }
+ // clear processed entries
+ msgIds.Reset();
+ iNewInboxEntries.Reset();
+ }
+
+CFSMailMessage* CFSNotificationHandlerBase::NewestMsgInFolderL(
+ CFSMailFolder& aFolder ) const
+ {
+ FUNC_LOG;
+ // Load info only necessary for sorting by date into the messages.
+ TFSMailDetails details( EFSMsgDataDate );
+
+ // Want to sort mails so that the newest is in the beginning
+ TFSMailSortCriteria criteriaDate;
+ criteriaDate.iField = EFSMailSortByDate;
+ criteriaDate.iOrder = EFSMailDescending;
+
+ RArray<TFSMailSortCriteria> sorting;
+ CleanupClosePushL( sorting );
+ // First criteria appended would be the primary criteria
+ // but here we don't have any other criteria
+ sorting.Append( criteriaDate );
+ MFSMailIterator* iterator = aFolder.ListMessagesL( details, sorting );
+
+ // Resetting array of sort criteria already here because
+ // the iterator does not need it anymore.
+ CleanupStack::PopAndDestroy(); // sorting
+
+ // CleanupStack::PushL doesn't work for M-class
+ CleanupDeletePushL( iterator );
+
+ RPointerArray<CFSMailMessage> messages;
+ CleanupClosePushL( messages );
+ // Let's get only the first and therefore the newest message.
+ TInt amount( 1 );
+ iterator->NextL( TFSMailMsgId(), amount, messages );
+ if ( messages.Count() < 1 )
+ {
+ messages.ResetAndDestroy();
+ User::Leave( KErrNotFound );
+ }
+
+ CFSMailMessage* outcome = messages[0];
+ messages.Remove( 0 ); // remove from array to prevent destruction of element
+ messages.ResetAndDestroy();
+ CleanupStack::PopAndDestroy(); // messages
+ CleanupStack::PopAndDestroy( iterator );
+ return outcome;
+ }
+
+CNewMailNotificationTimer::CNewMailNotificationTimer( MFSTimerObserver& aObserver ) :
+ CTimer( EPriorityIdle ), iObserver( aObserver )
+ {
+ FUNC_LOG;
+ }
+
+void CNewMailNotificationTimer::ConstructL()
+ {
+ FUNC_LOG;
+ CTimer::ConstructL();
+ CActiveScheduler::Add( this );
+ }
+
+CNewMailNotificationTimer* CNewMailNotificationTimer::NewL(
+ MFSTimerObserver& aObserver )
+ {
+ FUNC_LOG;
+ CNewMailNotificationTimer* self =
+ new( ELeave ) CNewMailNotificationTimer( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+
+CNewMailNotificationTimer::~CNewMailNotificationTimer()
+ {
+ FUNC_LOG;
+ Cancel();
+ }
+
+void CNewMailNotificationTimer::DoCancel()
+ {
+ FUNC_LOG;
+ // Cancel Base class
+ CTimer::DoCancel();
+ }
+
+void CNewMailNotificationTimer::RunL()
+ {
+ FUNC_LOG;
+ iObserver.TimerExpiredL();
+ }
+
+
+void Panic( TCmailhandlerPanic aPanic )
+ {
+ _LIT( KPanicText, "emailhandlerplugin" );
+ User::Panic( KPanicText, aPanic );
+ }
+
+// End of file
+