diff -r d189ee25cf9d -r 3533d4323edc 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 +#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& 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* newEntries( + static_cast< RArray* >( aParam1 ) ); + + TInt count = newEntries->Count(); + for ( TInt i = 0; ioperator []( 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 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 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 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 +