emailservices/emailstore/base_plugin/src/basepluginnotifications.cpp
changeset 0 8466d47a6819
child 8 e1b6206813b4
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/emailservices/emailstore/base_plugin/src/basepluginnotifications.cpp	Thu Dec 17 08:39:21 2009 +0200
@@ -0,0 +1,680 @@
+/*
+* Copyright (c) 2006 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:   Email interface notification systems implementation.
+*
+*/
+
+
+
+//<cmail>
+#include "MsgStore.h"
+#include "MsgStoreFolder.h"
+//</cmail>
+
+#include "BasePlugin.h"
+#include "baseplugincommonutils.h"
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::SubscribeMailboxEventsL(
+    const TFSMailMsgId& aMailboxId,
+    MFSMailEventObserver& aObserver )
+
+	{
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailboxId.Id() );
+
+    if ( KErrNotFound == mailBox.iObservers.Find( &aObserver ) )
+        {
+        mailBox.iObservers.AppendL( &aObserver );
+        }
+	}
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::UnsubscribeMailboxEvents(
+    const TFSMailMsgId& aMailboxId,
+    MFSMailEventObserver& aObserver )
+
+	{
+	TRAP_IGNORE( UnsubscribeMailboxEventsL( aMailboxId, aObserver ) );
+	}
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::AddObserverL(
+    MFSMailEventObserver& aObserver )
+    {
+    
+    if ( KErrNotFound == iObservers.Find( &aObserver ) )
+        {
+        iObservers.AppendL( &aObserver );
+        }
+
+    if ( iObservers.Count() == 1 )
+        {
+        iMsgStore->AddObserverL( this );
+        }
+    }
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::RemoveObserver(
+    MFSMailEventObserver& aObserver )
+    {
+
+    TInt idx = iObservers.Find( &aObserver );
+    
+    if ( KErrNotFound != idx )
+        {
+        iObservers.Remove( idx );
+        }
+        
+    if ( iObservers.Count() == 0 )
+        {
+        TRAP_IGNORE( iMsgStore->RemoveObserverL( this ) );
+        }
+    }
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::UnregisterRequestObserver(
+    TInt /*aRequestId*/ )
+    {
+    
+    }
+
+
+#pragma mark -
+#pragma mark --- MSGSTORE OBSERVERS ---
+
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::SystemEventNotify( TMsgStoreSystemEvent aEvent )
+	{
+	TRAP_IGNORE( SystemEventNotifyL( aEvent ) );
+	}
+
+
+/**
+ *
+ */
+void CBasePlugin::SystemEventNotifyL( TMsgStoreSystemEvent aEvent )
+    
+    {
+    switch ( aEvent )
+        {
+        // A backup or restore is in progress.  The message store is unavailable.
+        case EMsgStoreBackupOrRestoreInProgress:
+        // The message store has been wiped, including the password.
+        case EMsgStoreDatabaseWiped:
+        // The message store has transitioned from an authenticated state to an unauthenticated state.
+        case EMsgStoreNotAuthenticated:
+            {
+            NotifyGlobalEventL( TFSMailboxUnavailable );
+            }
+        break;
+
+        // The backup or restore completed.  The message store is available again.   
+        case EMsgStoreBackupOrRestoreCompleted:
+        // The message store has transitioned from an unauthenticated state to an authenticated state.
+        case EMsgStoreAuthenticated:
+            {
+            NotifyGlobalEventL( TFSMailboxAvailable );
+            }
+        break;
+
+        // The observer event queue has overflowed and has been reset, so events have been lost.  This
+        // shouldn't happen unless the client thread has been starved for an extended period of time, during
+        // which many message store operations have occurred.
+        case EObserverEventQueueOverflow:
+        //don't see anything meaningful to do here.
+        break;
+        };
+    }
+
+
+/**
+ *
+ */   
+EXPORT_C void CBasePlugin::AccountEventNotify(
+    TMsgStoreAccountEvent aEvent,
+	TInt32 aOwnerId,
+	const TDesC& aName,
+	const TDesC& aNewName,
+	TMsgStoreId aMailboxId )
+	
+	{
+	if ( GetPluginId() == aOwnerId )
+	    {
+	    TRAP_IGNORE( AccountEventNotifyL( aEvent, aOwnerId, aName, aNewName, aMailboxId ) );
+	    }
+	}
+
+
+/**
+ *
+ */   
+void CBasePlugin::AccountEventNotifyL(
+    TMsgStoreAccountEvent aEvent,
+	TInt32 /*aOwnerId*/,
+	const TDesC& /*aName*/,
+	const TDesC& /*aNewName*/,
+	TMsgStoreId aMailboxId )
+
+    {
+    switch ( aEvent )
+        {
+        case EMsgStoreAccountCreated:
+            {
+            TFSMailMsgId mailBox( GetPluginId(), aMailboxId );
+            NotifyGlobalEventL( TFSEventNewMailbox, mailBox );
+            }
+        break;
+
+        case EMsgStoreAccountDeleted:
+            {
+            //remove from the cache.
+            if ( KErrNotFound != iMailboxes.Find( aMailboxId ) )
+                {
+                iMailboxes.RemoveL( aMailboxId );
+                }
+
+            TFSMailMsgId mailBox( GetPluginId(), aMailboxId );
+            
+            HandleMailboxDeleteL( mailBox );
+            
+            NotifyGlobalEventL( TFSEventMailboxDeleted, mailBox );
+            }
+        break;
+
+        case EMsgStoreAccountRenamed:
+            {
+            }
+        break;
+        };   
+    }
+
+
+EXPORT_C void CBasePlugin::HandleMailboxDeleteL( const TFSMailMsgId& /*aMailboxId*/ )
+    {
+    //nothing to do
+    }
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::ModificationNotify(
+    TMsgStoreId aMailBoxId,
+    TMsgStoreOperation aOperation,
+    TMsgStoreContainerType aType,
+    TUint32 aFlags,
+    TMsgStoreId aId,
+    TMsgStoreId aParentId,
+    TMsgStoreId aOtherId )
+
+    {
+    TRAP_IGNORE( ModificationNotifyL( aMailBoxId, aOperation, aType, aFlags, aId, aParentId, aOtherId ) );
+    }
+
+
+/**
+ *
+ */
+void CBasePlugin::ModificationNotifyL(
+    TMsgStoreId aMailBoxId,
+    TMsgStoreOperation aOperation,
+    TMsgStoreContainerType aType,
+    TUint32 /*aFlags*/,
+    TMsgStoreId aId,
+    TMsgStoreId aParentId,
+    TMsgStoreId aOtherId )
+
+    {
+    __LOG_ENTER( "ModificationNotifyL" );
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId );
+    
+    __LOG_WRITE_FORMAT1_INFO( "aMailBoxId = 0x%X.", aMailBoxId );
+    __LOG_WRITE_FORMAT1_INFO( "aId = 0x%X.", aId );
+    __LOG_WRITE_FORMAT1_INFO( "aParentId = 0x%X.", aParentId );
+    
+    InvalidateCacheIfNecessary( aId, aParentId, aOtherId );
+    
+    if ( mailBox.iObservers.Count() > 0 )
+        {
+        switch ( aOperation )
+            {
+            
+            case EMsgStoreAdd:
+                {
+                __LOG_WRITE_INFO( "EMsgStoreAdd." );
+                if ( EMsgStoreMessageContainer == aType )
+                    {
+                    NotifyEventL( aMailBoxId, aId, aParentId, TFSEventNewMail );
+                    }
+                else if ( EMsgStoreFolderContainer == aType )
+                    {
+                    NotifyEventL( aMailBoxId, aId, aParentId, TFSEventNewFolder );
+                    }
+                }
+            break;
+
+            case EMsgStoreDelete:
+                {
+                __LOG_WRITE_INFO( "EMsgStoreDelete." );
+                if ( EMsgStoreMessageContainer == aType )
+                    {
+                    NotifyEventL( aMailBoxId, aId, aParentId, TFSEventMailDeleted );
+                    }
+                else if ( EMsgStoreFolderContainer == aType )
+                    {
+                    TRAPD( err, CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId ) );
+                    
+                    if ( KErrNone == err )
+                    	{
+                    	for ( TInt i = EFSInbox; i <= EFSDeleted; i++ )
+                    		{
+                    		if ( mailBox.iRootFolders.iFolders[i] == aId )
+                    			{
+                    			TMsgStoreId newId = 0;
+                    			
+                    			/**@ this behavior is forced by the UI for some reason and should be revisited
+                    			 * in the future as it allows more than one inbox folder which is not recommended. */
+                    			
+                    			//loop over all of the root folders looking for a replacement.
+								RPointerArray<CMsgStoreFolder> folders;
+								CleanupResetAndDestroyClosePushL( folders );
+
+								mailBox().FoldersL( aMailBoxId, folders );
+
+								for ( int j = 0; j < folders.Count(); j++ )
+									{
+									CMsgStoreFolder* folder = folders[j];
+
+									TUint index = 0;
+									if ( folder->FindProperty( KMsgStorePropertyFolderType, index ) )
+										{
+	                                    TUint32 type = folder->PropertyValueUint32L( index );
+
+	                                    if ( type == i )	//i is a value in the folder type enum.
+											{
+											newId = folder->Id();
+											break;
+											}
+	                                    }
+									}
+								
+								CleanupStack::PopAndDestroy( &folders );
+                                
+                    			//set the new root folder info.
+                    			mailBox.iRootFolders.iFolders[i] = newId;
+                    			break;
+                    			}                    		
+                    		}
+						}
+                
+                    NotifyEventL( aMailBoxId, aId, aParentId, TFSEventFoldersDeleted );
+                    }
+                }
+            break;
+            
+            case EMsgStoreMove:
+                {
+                __LOG_WRITE_INFO( "EMsgStoreMove." );
+                NotifyEventL( aMailBoxId, aId, aOtherId, TFSEventMailMoved, aParentId );
+                break;
+                }
+
+            case EMsgStoreUpdateProperties:
+                {
+                __LOG_WRITE_INFO( "EMsgStoreUpdateProperties." );
+                if ( EMsgStoreMessageContainer == aType )
+                    {
+                    NotifyEventL( aMailBoxId, aId, aParentId, TFSEventMailChanged );
+                    }
+                else if ( EMsgStoreFolderContainer == aType )
+                    {
+                    NotifyEventL( aMailBoxId, aId, aParentId, TFSEventFolderChanged );
+                    }
+                else if ( EMsgStoreMailboxContainer == aType )
+                    {
+                    TBool mailBoxNameHasChanged( EFalse );
+                    TRAP_IGNORE( RefreshCachedMailBoxDisplayNameL( mailBoxNameHasChanged, aMailBoxId ) );
+                    
+                    if ( mailBoxNameHasChanged )
+                        {
+                        NotifyEventL( aMailBoxId, aId, aParentId, TFSEventMailboxRenamed );
+                        }
+                    }
+                }
+            break;
+
+            case EMsgStoreRemoveContent:
+                break;
+
+            default:
+                break;
+            }
+        }
+        /* Reporting request status moved from above if-statement here. Now, request status is reported even there is no
+         * mailbox observers.
+         */ 
+        switch ( aOperation )
+            {
+            case EMsgStoreUpdateProperties:
+                {
+                if ( EMsgStorePartContainer == aType )
+                    {
+                    ReportRequestStatusL( aMailBoxId, aOtherId, aParentId, aId );
+                    }
+                }
+                break;
+            /**@ check whether the ui removes the observer - then the observer must be kept
+            until there are pending reqs ?*/
+            //attachment download request handling.
+            case EMsgStoreUpdateContent:
+                {
+                __LOG_WRITE_INFO( "EMsgStoreUpdateContent." );
+                ReportRequestStatusL( aMailBoxId, aOtherId, aParentId, aId, ETrue );
+                }
+                break;
+                
+            default:
+                break;
+        }
+    
+        
+        __LOG_EXIT;
+    } //ModificationNotifyL.
+
+
+/**
+ *
+ */
+void CBasePlugin::NotifyEventL(
+    TMsgStoreId aMailBoxId,
+    TMsgStoreId aId,
+    TMsgStoreId aParentId,
+    TFSMailEvent aFsEvent,
+    TMsgStoreId aOtherId /*=KMsgStoreInvalidId*/ )
+
+    {
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBoxId );
+    
+    TFSMailMsgId mailBoxId( GetPluginId(), aMailBoxId );
+    TFSMailMsgId parent( GetPluginId(), aParentId );
+    TFSMailMsgId other( GetPluginId(), aOtherId );
+
+    TFSMailMsgId* param3 = NULL;
+    if ( KMsgStoreInvalidId != aOtherId )
+    	{
+    	param3 = &other;
+    	}
+
+    RArray<TFSMailMsgId> entries;
+    CleanupClosePushL( entries );
+
+    TFSMailMsgId entry( GetPluginId(), aId );
+    entries.AppendL( entry );
+
+    TInt count = mailBox.iObservers.Count();
+    for ( TInt i = 0; i < count; i++ )
+        {
+        mailBox.iObservers[i]->EventL( aFsEvent, mailBoxId, &entries, &parent, param3 );
+        }
+
+    CleanupStack::PopAndDestroy( &entries );
+    }
+
+
+/**
+ *
+ */
+void CBasePlugin::NotifyGlobalEventL(
+    TFSMailEvent aEvent,
+    TFSMailMsgId aMailBox /*=TFSMailMsgId()*/,   //defaults to a null id.
+    TAny* aParam1 /*=NULL*/,
+    TAny* aParam2 /*=NULL*/,
+    TAny* aParam3 /*=NULL*/ )
+    
+    {
+    TInt count = iObservers.Count();
+    
+    for ( TInt i = 0; i < count; i++ )
+        {
+        iObservers[i]->EventL( aEvent, aMailBox, aParam1, aParam2, aParam3 );
+        }
+    }
+
+/**
+ *
+ */
+EXPORT_C void CBasePlugin::NotifyMailboxEventL(
+        TFSMailEvent aEvent,
+        TFSMailMsgId aMailBox,
+        TAny* aParam1 /*=NULL*/,
+        TAny* aParam2 /*=NULL*/,
+        TAny* aParam3 /*=NULL*/ )
+    {
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailBox.Id() );
+    
+    for ( TInt i = 0; i < mailBox.iObservers.Count(); i++ )
+        {
+        mailBox.iObservers[i]->EventL( aEvent, aMailBox, aParam1, aParam2, aParam3 );
+        }
+    }
+
+
+/**
+ *
+ */
+EXPORT_C /*protected virtual*/ void CBasePlugin::ReportRequestStatusL(
+    TMsgStoreId aMailBox,
+    TMsgStoreId aOtherId,
+    TMsgStoreId aMsgId,
+    TMsgStoreId aPartId,
+    TBool aCanReportCompletion /*=EFalse*/ )
+
+    {
+    __LOG_ENTER( "ReportRequestStatusL" );
+
+    __LOG_WRITE_FORMAT1_INFO( "aMailBox : 0x%X.", aMailBox );
+    __LOG_WRITE_FORMAT1_INFO( "aMsgId : 0x%X.", aMsgId );
+    __LOG_WRITE_FORMAT1_INFO( "aPartId : 0x%X.", aPartId );
+
+    TOngoingFetchInfo fetchInfo;
+    if ( FindFetchRequestL( aMailBox, aOtherId, aMsgId, aPartId, fetchInfo ) )
+        {
+        __LOG_WRITE_INFO( "Request match found." );
+
+        CMailboxInfo& mailBox = GetMailboxInfoL( aMailBox );
+
+        //get the fetched and the server sizes.                    
+        CMsgStoreMessage* msg = mailBox().FetchMessageL(
+        	fetchInfo.iMessageId, KMsgStoreInvalidId );
+        CleanupStack::PushL( msg );
+        CMsgStoreMessagePart* part = msg->ChildPartL( aPartId, ETrue );
+        CleanupStack::PushL( part );
+
+        TUint32 size = 0;
+        TUint idx = 0;
+        if ( part->FindProperty( KMsgStorePropertySize, idx ) )
+            {
+            size = part->PropertyValueUint32L( idx );
+            }
+        
+        TUint32 fetchedSize = 0;
+        idx = 0;
+        if ( part->FindProperty( KMsgStorePropertyRetrievedSize, idx ) )
+            {
+            fetchedSize = part->PropertyValueUint32L( idx );
+            }
+        
+        CleanupStack::PopAndDestroy( part );
+        CleanupStack::PopAndDestroy( msg );
+
+        TFSProgress progress;
+        progress.iError = KErrNone;
+        progress.iMaxCount = size;
+        progress.iCounter = fetchedSize;
+        
+        __LOG_WRITE_FORMAT2_INFO(
+            "Size: %d, fetched size: %d.", size, fetchedSize );
+            
+        if ( fetchedSize < size )
+            {
+            __LOG_WRITE_INFO( "Download in progress, about to notify the UI." );
+
+            progress.iProgressStatus = TFSProgress::EFSStatus_Status;
+            fetchInfo.iRequest->iObserver.RequestResponseL(
+            	progress, fetchInfo.iRequest->iRequestId );
+            }
+        else if ( aCanReportCompletion )
+            {
+            if ( DeleteFetchRequestForPart( fetchInfo ) )
+            	{
+            	//no more parts left for downloading thus completed.
+                progress.iProgressStatus
+					= TFSProgress::EFSStatus_RequestComplete;                        
+                __LOG_WRITE_INFO( "Download completed for all parts." );
+
+                fetchInfo.iRequest->iObserver.RequestResponseL(
+                	progress, fetchInfo.iRequest->iRequestId );
+                DeleteFetchRequest( fetchInfo );
+            	}
+            else
+            	{
+                progress.iProgressStatus
+					= TFSProgress::EFSStatus_Status;
+                __LOG_WRITE_INFO( "A part download completed, more is left." );
+
+                fetchInfo.iRequest->iObserver.RequestResponseL(
+                	progress, fetchInfo.iRequest->iRequestId );
+            	}
+            }
+        }
+        
+    __LOG_EXIT;
+    }
+
+
+/**
+ * @return ETrue in case there are no more parts left for downloading.
+ */
+EXPORT_C /*protected*/ TBool CBasePlugin::DeleteFetchRequestForPart(
+	TOngoingFetchInfo& aFetchInfo )
+	{
+    //remove the downloaded part from the request object.                        
+	aFetchInfo.iRequest->iParts.Remove( aFetchInfo.iPartIndex );
+
+	return 0 == aFetchInfo.iRequest->iParts.Count();
+	}
+
+
+/**
+ * 
+ */
+EXPORT_C /*protected*/ void CBasePlugin::DeleteFetchRequest(
+	TOngoingFetchInfo& aFetchInfo )
+	{
+	iReqs.Remove( aFetchInfo.iRequestIndex );
+	delete aFetchInfo.iRequest;
+	}
+
+
+/**
+ * 
+ */
+EXPORT_C TBool CBasePlugin::FindFetchRequestL(
+	TMsgStoreId aMailBox,
+	TMsgStoreId aOtherId,
+	TMsgStoreId aMsgId,
+	TMsgStoreId aPartId,
+	CBasePlugin::TOngoingFetchInfo& aOngoingFetchInfo )
+	{
+	
+	for ( TInt count = iReqs.Count(); aOngoingFetchInfo.iRequestIndex < count;
+		aOngoingFetchInfo.iRequestIndex++ )
+		{
+		TFSMailMsgId fsId( GetPluginId(), aPartId );
+		CFetchRequester* request = iReqs[aOngoingFetchInfo.iRequestIndex];
+		
+		//a request might specify more than one part for download, find the
+		//index of the currently processed part.
+		TInt partsCount = request->iParts.Count();
+		for ( TInt i = 0; i < partsCount; i++ )
+			{
+			if ( fsId == request->iParts[i] )
+				{
+				aOngoingFetchInfo.iPartIndex = i;
+				break;
+				}
+			}
+	
+		//there are MsgStore notification that receive the message id in the
+		//"other" id, determine for sure the id of the message this part belongs
+		//to. 
+		if ( aMsgId == request->iMessageId.Id() )
+			{
+			aOngoingFetchInfo.iMessageId = aMsgId;
+			}
+		else if ( aOtherId 
+			== request->iMessageId.Id() )
+			{
+			aOngoingFetchInfo.iMessageId = aOtherId;
+			}
+	
+		//final check before choosing the download request object that
+		//identifies this part download request.
+		if ( aMailBox == request->iMailBoxId.Id()
+			&& KMsgStoreInvalidId != aOngoingFetchInfo.iMessageId 
+			&& KErrNotFound != aOngoingFetchInfo.iPartIndex )
+			{
+			aOngoingFetchInfo.iRequest = request;
+			break;
+			}
+		}
+	
+	return NULL != aOngoingFetchInfo.iRequest;
+	} //FindRequestL.
+
+
+/**
+ *
+ */
+void CBasePlugin::UnsubscribeMailboxEventsL(
+    const TFSMailMsgId& aMailboxId,
+    MFSMailEventObserver& aObserver )
+
+	{
+    CMailboxInfo& mailBox = GetMailboxInfoL( aMailboxId.Id() );
+
+    TInt idx = mailBox.iObservers.Find( &aObserver );
+    
+    if ( KErrNotFound != idx )
+        {
+        mailBox.iObservers.Remove( idx );
+        }
+	}