diff -r 000000000000 -r 8466d47a6819 emailservices/emailstore/base_plugin/src/basepluginnotifications.cpp
--- /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.
+*
+*/
+
+
+
+//
+#include "MsgStore.h"
+#include "MsgStoreFolder.h"
+//
+
+#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 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 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 );
+ }
+ }