emailservices/emailserver/cmailhandlerplugin/src/fsnotificationhandlerbaseimpl.cpp
branchRCL_3
changeset 64 3533d4323edc
child 80 726fba06891a
equal deleted inserted replaced
63:d189ee25cf9d 64:3533d4323edc
       
     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