diff -r 000000000000 -r 72b543305e3a mmsengine/clientmtm/src/mmsnotificationclient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mmsengine/clientmtm/src/mmsnotificationclient.cpp Thu Dec 17 08:44:11 2009 +0200 @@ -0,0 +1,1056 @@ +/* +* Copyright (c) 2002-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: +* A Client MTM to access MMS notifications in a manual fetch mode. +* All this is needed to support new mtm type for Symbian OS messaging +* UI components. +* +*/ + + + +// INCLUDE FILES +#include +#include "mmsheaders.h" +#include "mmsnotificationclient.h" +#include "mmscmds.h" +#include "mmsmessageoperation.h" +#include "mmsmmboxviewheaders.h" +#include "mmssettings.h" + +// EXTERNAL DATA STRUCTURES + +// EXTERNAL FUNCTION PROTOTYPES + +// CONSTANTS + +// MACROS + +// LOCAL CONSTANTS AND MACROS +const TInt KMmsAttributeArrayGranularity = 8; + +// MODULE DATA STRUCTURES + +// LOCAL FUNCTION PROTOTYPES + +// ==================== LOCAL FUNCTIONS ==================== + + +// ================= MEMBER FUNCTIONS ======================= + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::NewL +// --------------------------------------------------------- +// +EXPORT_C CMmsNotificationClientMtm* CMmsNotificationClientMtm::NewL( + CRegisteredMtmDll& aRegisteredMtmDll, + CMsvSession& aSession ) + { + CMmsNotificationClientMtm* self = new ( ELeave ) CMmsNotificationClientMtm( + aRegisteredMtmDll, aSession ); + + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + + return self; + } + + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::CMmsNotificationClientMtm +// --------------------------------------------------------- +// +CMmsNotificationClientMtm::CMmsNotificationClientMtm( + CRegisteredMtmDll& aRegisteredMtmDll, + CMsvSession& aSession ) + : CMmsClientMtm( aRegisteredMtmDll, aSession ) + { + __ASSERT_DEBUG( Type() == KUidMsgMMSNotification, gPanic( EMmsBadMtmTypeUid ) ); + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::~CMmsNotificationClientMtm +// --------------------------------------------------------- +// +CMmsNotificationClientMtm::~CMmsNotificationClientMtm() + { + + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::ConstructL +// +// --------------------------------------------------------- +// +void CMmsNotificationClientMtm::ConstructL() + { + // First loading settings + iMmsSettings = CMmsSettings::NewL(); + iMmsSettings->LoadSettingsL(); + // Get the base values to detect changes + iHomeMode = iMmsSettings->ReceivingModeHome(); + iRoamingMode = iMmsSettings->ReceivingModeForeign(); + iAccessPointCount = iMmsSettings->AccessPointCount(); + + iMessageDrive = EDriveC; + TInt error = KErrNone; + + TRAP ( error, { iMessageDrive = Session().CurrentDriveL(); } ); + + if ( error != KErrNone ) + { + // if cannot ask, use default + iMessageDrive = EDriveC; + } + + // Notification client mtm does not create new service + iServiceId = iMmsSettings->Service(); + + iMmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); + + iAttributes = new( ELeave ) CDesCArrayFlat( KMmsAttributeArrayGranularity ); + + // Set the original context to the service entry + SwitchCurrentEntryL( iServiceId ); + } + +// --------------------------------------------------------- +// CMmsClientMtm::QueryCapability +// --------------------------------------------------------- +// +TInt CMmsNotificationClientMtm::QueryCapability( + TUid /*aCapability*/, + TInt& /*aResponse*/ ) + { + // Nothing Supported at the moment + return KErrNotSupported; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::ForwardL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::ForwardL( + TMsvId aDestination, + TMsvPartList /*aPartList*/, + TRequestStatus& aCompletionStatus ) + { + // + // Actual creation is done synchronously below + // + TMsvId id = CreateForwardEntryL( aDestination ); + + // + // This method has to be asynchronous.. + // + TPckgC < TMsvId > progress = id; + return CMsvCompletedOperation::NewL( Session(), Type(), progress, + KMsvLocalServiceIndexEntryId, aCompletionStatus ); + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::CreateForwardEntryL +// --------------------------------------------------------- +// +TMsvId CMmsNotificationClientMtm::CreateForwardEntryL( TMsvId aDestination ) + { + // + // Check that current context is valid + // + if( iMsvEntry->Entry().iType != KUidMsvMessageEntry + || iMsvEntry->Entry().iMtm != KUidMsgMMSNotification ) + { + User::Leave( KErrUnknown ); + } + + // It is assumed that a created forward entry can not be saved to drafts. + // I.e. the application calling this, is responsible to take care that + // the entry is either SENT or DESTROYED. + + // + // Load entry to local cache if necessary + // + if( iMmsHeaders->ContentLocation() == TPtrC8() ) + { + LoadMessageL(); + } + + // + // Create new Mms message object into aDestination folder + // + TMsvId forwardId = CMmsMessageOperation::CreateForwardWithoutRetrievalL( + Session(), + *iMmsHeaders, + iMsvEntry->EntryId(), + aDestination, + iServiceId ); + + return forwardId; + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::SendL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::SendL( + TRequestStatus& aCompletionStatus, + const TTime aSendingTime ) + { + // + // Is it possible to proceed with the operation... + // If yes, the notification is marked as "further-operations-not-allowed" + // + TMsvId relatedNotificationId = iMmsHeaders->RelatedEntry(); + TInt retval = ReserveNotificationOperationL( relatedNotificationId, KMmsOperationForward ); + if( retval != KErrNone ) + { + TPckgC < TMsvId > progress = relatedNotificationId; + return CMsvCompletedOperation::NewL( + Session(), + KUidMsgMMSNotification, + progress, // progress contains the related entry id + iServiceId, + aCompletionStatus, + KErrInUse); + } + + // + // Create the selection to be sent + // + CMsvEntrySelection* selection = new( ELeave ) CMsvEntrySelection; + CleanupStack::PushL( selection ); // *** + selection->AppendL( iMsvEntry->Entry().Id() ); + + // + // Make sure the message is in OUTBOX + // + TMsvId currentParent = iMsvEntry->Entry().Parent(); + if ( currentParent != KMsvGlobalOutBoxIndexEntryId ) + { + CMsvEntry* cEntry = NULL; + cEntry = Session().GetEntryL( currentParent ); + CleanupStack::PushL( cEntry ); + cEntry->MoveL( iMsvEntry->Entry().Id(), KMsvGlobalOutBoxIndexEntryId ); + CleanupStack::PopAndDestroy( cEntry ); + } + + // + // Create parameters structure + // + TCommandParameters parameters; + TTime now; + now.UniversalTime(); + if ( aSendingTime > now ) + { + aSendingTime.SecondsFrom( now, parameters.iInitialDelay ); + } + TCommandParametersBuf paramPack( parameters ); + + // + // Call Server MTM + // + CMsvOperation* op = InvokeAsyncFunctionL( + EMmsScheduledForward, + *selection, + paramPack, + aCompletionStatus ); + + // + // Cleanup and return + // + CleanupStack::PopAndDestroy( selection ); + return op; + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::SendL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::SendL( + CMsvEntrySelection& /*aSelection*/, + TRequestStatus& /*aCompletionStatus*/, + TTime /*aSendingTime*/ ) + { + User::Leave( KErrNotSupported ); + return NULL; // makes the compiler happy + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::ReserveNotificationOperationL +// --------------------------------------------------------- +// +TInt CMmsNotificationClientMtm::ReserveNotificationOperationL( + TMsvId aNotifId, + const TUint32 aOperation ) + { + // + // Get hands on index entry based on entryId + // + CMsvEntry* cEntry = NULL; + cEntry = Session().GetEntryL( aNotifId ); + CleanupStack::PushL( cEntry ); // *** + TMsvEntry tEntry = cEntry->Entry(); + + // + // Check that entry is a notification + // + if( cEntry->Entry().iType != KUidMsvMessageEntry + || cEntry->Entry().iMtm != KUidMsgMMSNotification ) + { + CleanupStack::PopAndDestroy( cEntry ); + return KErrNotSupported; + } + + // + // Make some checks concerning the current status of notification and + // return with error if reservation is not possible + // + // if operation is forbidden OR + // if ( (the aOperation is fetch or forward) and notification is deleted successfully from mmbox) + if( tEntry.iMtmData2 & KMmsNewOperationForbidden || + ( ( aOperation == KMmsOperationFetch || aOperation == KMmsOperationForward ) && + tEntry.iMtmData2 & KMmsOperationFinished && + ! ( tEntry.iMtmData2 & KMmsOperationResult ) && + ! ( tEntry.iMtmData2 & KMmsStoredInMMBox ) && + tEntry.iMtmData2 & KMmsOperationDelete ) ) + { + CleanupStack::PopAndDestroy( cEntry ); + return KErrInUse; + } + + // + // Set the flags + // + // reserve the operation + MarkNotificationOperationReserved( tEntry, aOperation ); + tEntry.SetReadOnly( EFalse ); + + // + // Save the entry + // + cEntry->ChangeL( tEntry ); + CleanupStack::PopAndDestroy( cEntry ); + return KErrNone; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::MarkFreeNotificationsReservedL +// --------------------------------------------------------- +// +void CMmsNotificationClientMtm::MarkFreeNotificationsReservedL( + CMsvEntrySelection& aNotifications, const TUint32 aOperation ) + { + TInt count = aNotifications.Count(); + if ( count == 0 ) + { + return; + } + CMsvEntry* clientEntry = Session().GetEntryL( aNotifications.At( 0 )); + CleanupStack::PushL( clientEntry ); + + for ( TInt i = aNotifications.Count() - 1 ; i >= 0 ; i-- ) + { + TBool drop = EFalse; + TBool alreadyMarked = EFalse; + + clientEntry->SetEntryL( aNotifications.At( i ) ); + TMsvEntry entry = clientEntry->Entry(); + TMsvId duplicate = KMsvNullIndexEntryId; + if ( FreeNotification( entry, aOperation ) ) + { + // Check possible duplicate, if mmbox folder even exists + TMsvId mmboxFolder = iMmsSettings->MMBoxFolder(); + if ( mmboxFolder != KMsvNullIndexEntryId ) + { + TMsvId parent = entry.Parent(); + + CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); + CleanupStack::PushL( mmsHeaders ); + CMsvStore* store = clientEntry->ReadStoreL(); + CleanupStack::PushL( store ); + mmsHeaders->RestoreL( *store ); + CleanupStack::PopAndDestroy( store ); + store = NULL; + + if ( parent == KMsvGlobalInBoxIndexEntryId ) + { + + FindDuplicateNotificationL( mmboxFolder, + *mmsHeaders, duplicate ); + } + else if ( parent == mmboxFolder ) + { + FindDuplicateNotificationL( KMsvGlobalInBoxIndexEntryId, + *mmsHeaders, duplicate ); + } + else + { + // keep LINT happy + } + if ( duplicate != KMsvNullIndexEntryId ) + { + // check if duplicate is free for a operation + clientEntry->SetEntryL( duplicate ); + TMsvEntry dupEntry = clientEntry->Entry(); + if ( FreeNotification( dupEntry, aOperation )) + { + // if original notification is in mmbox folder + // mark the duplicate reserved too. + if ( parent == mmboxFolder ) + { + MarkNotificationOperationReserved( dupEntry, aOperation ); + clientEntry->ChangeL( dupEntry ); + + clientEntry->SetEntryL( aNotifications.At( i ) ); + entry = clientEntry->Entry(); + MarkNotificationOperationReserved( entry, aOperation ); + entry.SetReadOnly( EFalse ); + clientEntry->ChangeL( entry ); + alreadyMarked = ETrue; + + store = clientEntry->EditStoreL(); + CleanupStack::PushL( store ); + mmsHeaders->RestoreL( *store ); + mmsHeaders->SetRelatedEntry( duplicate ); + mmsHeaders->StoreL( *store ); + store->CommitL(); + CleanupStack::PopAndDestroy( store ); + store = NULL; + } + clientEntry->SetEntryL( aNotifications.At( i ) ); + + } + else // duplicate is not free-> original notification has to be dropped + { + drop = ETrue; + } + + } + CleanupStack::PopAndDestroy( mmsHeaders ); + } + + } + else // original notification is not free + { + drop = ETrue; + } + + if ( drop ) + { + // Remove the entry from selection + aNotifications.Delete( i ); + } + else // mark original notification reserved, unless it is already marked + { + if ( !alreadyMarked) + { + clientEntry->SetEntryL( aNotifications.At( i ) ); + entry = clientEntry->Entry(); + MarkNotificationOperationReserved( entry, aOperation ); + entry.SetReadOnly( EFalse ); + clientEntry->ChangeL( entry ); + } + } + } + aNotifications.Compress(); + + CleanupStack::PopAndDestroy( clientEntry ); + + } + + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::FreeNotification +// --------------------------------------------------------- +// +TBool CMmsNotificationClientMtm::FreeNotification( TMsvEntry& aEntry, const TUint32 aOperation ) + { + if ( aEntry.iMtm != KUidMsgMMSNotification) + { + return EFalse; + } + if ( aEntry.iMtmData2 & KMmsNewOperationForbidden || + ( aEntry.iMtmData2 & KMmsOperationFinished && + !( aEntry.iMtmData2 & KMmsOperationResult ) && + !( aEntry.iMtmData2 & KMmsStoredInMMBox ) && + ( aOperation == KMmsOperationFetch || aOperation == KMmsOperationForward ))) + { + return EFalse; + } + + return ETrue; + + } + + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::MarkNotificationOperationReserved +// --------------------------------------------------------- +// +void CMmsNotificationClientMtm::MarkNotificationOperationReserved( TMsvEntry& aEntry, + const TUint32 aOperation ) + { + aEntry.iMtmData2 &= ~KMmsOperationIdentifier; // clear possible old operation + aEntry.iMtmData2 |= KMmsNewOperationForbidden; // forbidden + aEntry.iMtmData2 |= KMmsOperationOngoing; // operation is active + aEntry.iMtmData2 |= aOperation; // operation + aEntry.iMtmData2 &= ~KMmsOperationFinished; // not finished + aEntry.iMtmData2 &= ~KMmsOperationResult; // not failed + } +// --------------------------------------------------------- +// CMmsNotificationClientMtm::FindDuplicateNotificationL +// --------------------------------------------------------- +// +void CMmsNotificationClientMtm::FindDuplicateNotificationL( TMsvId aParent, + CMmsHeaders& aHeaders, + TMsvId& aDuplicate ) + { + + aDuplicate = KMsvNullIndexEntryId; + if ( aParent == KMsvNullIndexEntryId ) + { + return; + } + + CMsvEntry* cEntry = Session().GetEntryL( aParent ); + CleanupStack::PushL( cEntry ); + + CMsvEntrySelection* selection = cEntry->ChildrenWithMtmL( KUidMsgMMSNotification ); + CleanupStack::PushL( selection ); + + TInt count = selection->Count(); + if ( count == 0 ) + { + CleanupStack::PopAndDestroy( selection ); + CleanupStack::PopAndDestroy( cEntry ); + return; + } + + CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); + CleanupStack::PushL( mmsHeaders ); + + for ( TInt i = count; i > 0 && ( aDuplicate == KMsvNullIndexEntryId ); i-- ) + { + cEntry->SetEntryL( selection->At( i - 1 ) ); + + CMsvStore* store = cEntry->ReadStoreL(); + CleanupStack::PushL( store ); + mmsHeaders->RestoreL( *store ); + CleanupStack::PopAndDestroy( store ); + + // content location must match + if ( mmsHeaders->ContentLocation().Compare( aHeaders.ContentLocation() ) == 0 ) + { + aDuplicate = selection->At( i - 1 ); + } + } + + CleanupStack::PopAndDestroy( mmsHeaders ); + CleanupStack::PopAndDestroy( selection ); + CleanupStack::PopAndDestroy( cEntry ); + } + +// --------------------------------------------------------- +// CMmsClientNotificationMtm::GetExtendedText +// --------------------------------------------------------- +// +const TPtrC CMmsNotificationClientMtm::GetExtendedText() const + { + return iMmsHeaders->ExtendedNotification(); + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::FetchMessagesL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::FetchMessagesL( + const CMsvEntrySelection& aSelection, + TRequestStatus& aCompletionStatus ) + { + if ( aSelection.Count() == 0 ) + { + User::Leave( KErrNotFound ); + } + + CMsvEntrySelection* notifications = aSelection.CopyLC(); + + // mark free notifications reserved. Others are dropped out. + MarkFreeNotificationsReservedL( *notifications, KMmsOperationFetch ); + + // check if none of the entries are allowed to start fetch + if ( notifications->Count() == 0 ) + { + // leave will destroy reserved items from cleanupstack + User::Leave( KErrNotSupported ); + } + + TCommandParameters parameters; // initialized to zero + TCommandParametersBuf paramPack( parameters ); + + // Fetch messages + CMsvOperation* op = InvokeAsyncFunctionL( + EMmsScheduledReceiveForced, + *notifications, + paramPack, + aCompletionStatus ); + + CleanupStack::PopAndDestroy( notifications ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::FetchMessageL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::FetchMessageL( + TMsvId aUid, + TRequestStatus& aCompletionStatus ) + { + CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection; + CleanupStack::PushL( selection ); + selection->AppendL( aUid ); + + // Mark the notification reserved for fetching is possible + MarkFreeNotificationsReservedL( *selection, KMmsOperationFetch ); + + // if notification is not allowed to be fetched, + // the notification is dropped from selection. + if ( selection->Count() == 0 ) + { + CleanupStack::PopAndDestroy( selection ); + return NULL; + } + + TCommandParameters parameters; // initialized to zero + TCommandParametersBuf paramPack( parameters ); + + // Fetch the message + CMsvOperation* op = InvokeAsyncFunctionL( + EMmsScheduledReceiveForced, + *selection, + paramPack, + aCompletionStatus ); + + CleanupStack::PopAndDestroy( selection ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::FetchAllL +// --------------------------------------------------------- +// + +CMsvOperation* CMmsNotificationClientMtm::FetchAllL( TRequestStatus& aCompletionStatus, + TBool aForced ) + { + // List notifications that have no active operation + CMsvEntrySelection* notifications = ListNotificationsL(); + if ( notifications->Count() == 0 ) + { + delete notifications; + notifications = NULL; + User::Leave( KErrNotFound ); + } + CleanupStack::PushL( notifications ); + + // Loop through the notifications and reserve them for the operation + TInt retval = KErrNone; + TInt count = notifications->Count(); + for ( TInt i = count; i > 0; i-- ) + { + retval = ReserveNotificationOperationL( notifications->At( i - 1 ), KMmsOperationFetch ); + if( retval != KErrNone ) + { + // Remove the entry from selection + notifications->Delete( i - 1 ); + } + } + + TCommandParameters parameters; // initialized to zero + TCommandParametersBuf paramPack( parameters ); + + // Fetch the message + CMsvOperation* op = NULL; + if ( aForced ) + { + op = InvokeAsyncFunctionL( + EMmsScheduledReceiveForced, + *notifications, + paramPack, + aCompletionStatus ); + } + else + { + op = InvokeAsyncFunctionL( + EMmsScheduledReceive, + *notifications, + paramPack, + aCompletionStatus ); + } + + CleanupStack::PopAndDestroy( notifications ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::NotificationCount +// --------------------------------------------------------- +// +TInt CMmsNotificationClientMtm::NotificationCount() + { + TInt numberOfNotifications = -1; + + TInt error = KErrNone; + CMsvEntrySelection* notifications = NULL; + + TRAP( error, + { notifications = ListNotificationsL(); + }); + + if ( error == KErrNone ) + { + numberOfNotifications = notifications->Count(); + } + + delete notifications; + notifications = NULL; + + return numberOfNotifications; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::ListNotificationsL +// --------------------------------------------------------- +// +CMsvEntrySelection* CMmsNotificationClientMtm::ListNotificationsL() + { + return CMmsClientMtm::ListNotificationsInInboxL(); + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::DeleteNotificationL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::DeleteNotificationL( + const CMsvEntrySelection& aSelection, + TMmsDeleteOperationType aDeleteType, + TRequestStatus& aCompletionStatus ) + { + + if ( aSelection.Count() == 0 ) + { + // if nothing to delete, operation is complete + TPckgC < TMsvId > progress = 0; + return CMsvCompletedOperation::NewL( Session(), Type(), progress, + KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNone ); + } + + // + // aDeleteType has to be delivered to server side. + // Using TCommandParameters.iError for it on purpose. + // + TCommandParameters parameters; + parameters.iError = aDeleteType; + TCommandParametersBuf paramPack( parameters ); + + // + // Modifying indexentries + // + CMsvEntry* cEntry = NULL; + cEntry = Session().GetEntryL( aSelection.At( 0 ) ); + CleanupStack::PushL( cEntry ); // *** + for ( TInt i = 0; i < aSelection.Count(); i++ ) + { + cEntry->SetEntryL( aSelection.At( i ) ); + TMsvEntry tEntry = cEntry->Entry(); + tEntry.SetReadOnly( EFalse ); + cEntry->ChangeL( tEntry ); + } + CleanupStack::PopAndDestroy( cEntry ); + + // + // NOTE: Notification delete operations perform majority of the work in + // the server side. This includes also notification reservation for the operation. + // + + // + // Calling server side + // + CMsvOperation* op = InvokeAsyncFunctionL( + EMmsScheduledNotificationDelete, + aSelection, + paramPack, + aCompletionStatus ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::UnscheduledDeleteNotificationL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::UnscheduledDeleteNotificationL( + const CMsvEntrySelection& aSelection, + TMmsDeleteOperationType aDeleteType, + TRequestStatus& aCompletionStatus ) + { + + if ( aSelection.Count() == 0 ) + { + // if nothing to delete, operation is complete + TPckgC < TMsvId > progress = 0; + return CMsvCompletedOperation::NewL( Session(), Type(), progress, + KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNone ); + } + + // + // aDeleteType has to be delivered to server side. + // Using TCommandParameters.iError for it on purpose. + // + TCommandParameters parameters; + parameters.iError = aDeleteType; + TCommandParametersBuf paramPack( parameters ); + + // + // NOTE: Notification delete operations perform majority of the work in + // the server side. This includes also notification reservation for the operation. + // + + // + // Calling server side + // + CMsvOperation* op = InvokeAsyncFunctionL( + EMmsNotificationDelete, + aSelection, + paramPack, + aCompletionStatus ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::DeleteAllNotificationsL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::DeleteAllNotificationsL( + TMmsDeleteOperationType aDeleteType, + TRequestStatus& aCompletionStatus ) + { + // + // Get selection of all the notifications in Inbox + // (operations that do not have ongoing operations) + // + CMsvEntrySelection* selection = ListNotificationsL(); + + if ( selection->Count() == 0 ) + { + delete selection; + selection = NULL; + // if nothing to delete, operation is complete + TPckgC < TMsvId > progress = 0; + return CMsvCompletedOperation::NewL( Session(), Type(), progress, + KMsvLocalServiceIndexEntryId, aCompletionStatus, KErrNone ); + } + + CleanupStack::PushL( selection ); + + // + // Call DeleteNotificationL with the selection just created + // + CMsvOperation* op = DeleteNotificationL( + *selection, + aDeleteType, + aCompletionStatus ); + CleanupStack::PopAndDestroy( selection ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::DeleteForwardEntryL +// --------------------------------------------------------- +// +void CMmsNotificationClientMtm::DeleteForwardEntryL( const CMsvEntrySelection& aSelection ) + { + // + // Loop through the selection of forward entries + // + TInt count = aSelection.Count(); + for( TInt index = 0; index < count; index++ ) + { + iMsvEntry->SetEntryL( aSelection.At( index ) ); + TMsvEntry tEntry = iMsvEntry->Entry(); + // Test entry type + if( tEntry.iType != KUidMsvMessageEntry || + tEntry.iMtm != KUidMsgMMSNotification || + !( tEntry.iMtmData1 & KMmsMessageForwardReq ) ) + { + continue; + } + // Test entry location + TMsvId parentId = tEntry.Parent(); + if( ( parentId != KMsvGlobalOutBoxIndexEntryId ) && + ( parentId != KMsvSentEntryId ) ) + { + continue; + } + // Test that entry is not in a middle of some other action + if( tEntry.SendingState() == KMsvSendStateSending ) + { + // Too late to delete + continue; + } + else + { + // Quickly "reserve" the entry for deletion + tEntry.SetSendingState( KMsvSendStateSuspended ); + iMsvEntry->ChangeL( tEntry ); + } + // + // Entry will do; it will be deleted. + // + + // But first clearing possible related notification + CMsvStore* store = iMsvEntry->ReadStoreL(); + CleanupStack::PushL( store ); // *** + CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); + CleanupStack::PushL( mmsHeaders ); + mmsHeaders->RestoreL( *store ); + TMsvId relatedId = mmsHeaders->RelatedEntry(); + CleanupStack::PopAndDestroy( mmsHeaders ); + CleanupStack::PopAndDestroy( store ); + + // If forward entry has a "related id" (i.e. id of the notification), + // context is changed to it and it will be cleared. + if( relatedId != KMsvNullIndexEntryId ) + { + // Change to related notification + iMsvEntry->SetEntryL( relatedId ); + tEntry = iMsvEntry->Entry(); + // "Clear" the flags + tEntry.iMtmData2 &= ~KMmsOperationIdentifier; // clear possible old operations + tEntry.iMtmData2 &= ~KMmsNewOperationForbidden; // not forbidden + tEntry.iMtmData2 &= ~KMmsOperationOngoing; // not ongoing + tEntry.iMtmData2 &= ~KMmsOperationFinished; // not finished (this is notification's initial state) + tEntry.iMtmData2 &= ~KMmsOperationResult; // clear also the result flag ("assuming OK") + tEntry.SetReadOnly( ETrue ); + iMsvEntry->ChangeL( tEntry ); + } + + // Activating parent entry of the forward entry + iMsvEntry->SetEntryL( parentId ); + // Delete forward entry + iMsvEntry->DeleteL( aSelection.At( index ) ); + } // for loop + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::MmboxInfoL +// --------------------------------------------------------- +// +TBool CMmsNotificationClientMtm::MmboxInfoL( TMmboxInfo& aMmboxInfo ) + { + // check first, if quota information is available. + TMsvId mmboxFolder = iMmsSettings->MMBoxFolder(); + CMsvEntry* cEntry = Session().GetEntryL( KMsvLocalServiceIndexEntryId ); + CleanupStack::PushL( cEntry ); + TInt pushedToStack = 1; + + cEntry->SetEntryL( mmboxFolder ); + // Show invisible entries + cEntry->SetSortTypeL( TMsvSelectionOrdering( KMsvNoGrouping, EMsvSortByIdReverse, ETrue ) ); + CMsvEntrySelection* selection = cEntry->ChildrenWithMtmL( KUidMsgTypeMultimedia ); + CleanupStack::PushL( selection ); + pushedToStack++; + + TBool quotaInfoAvailable = EFalse; + + if ( selection->Count() > 0 ) + { + cEntry->SetEntryL( selection->At( 0 )); + CMsvStore* store = cEntry->ReadStoreL(); + CleanupStack::PushL( store ); + pushedToStack++; + CMmsHeaders* mmsHeaders = CMmsHeaders::NewL( iMmsSettings->MmsVersion() ); + CleanupStack::PushL( mmsHeaders ); + pushedToStack++; + mmsHeaders->RestoreL( *store ); + + // Get quota info + CMmsMMBoxViewHeaders& viewHeaders = mmsHeaders->MMBoxViewHeadersL(); + + aMmboxInfo.mmboxTotalInBytes = viewHeaders.MMBoxTotalSize(); + aMmboxInfo.mmboxTotalInMessageCount = viewHeaders.MMBoxTotalNumber(); + aMmboxInfo.mmboxQuotaInBytes = viewHeaders.MMBoxQuotaSize(); + aMmboxInfo.mmboxQuotaInMessageCount = viewHeaders.MMBoxQuotaNumber(); + + // get Date info + TMsvEntry tEntry = cEntry->Entry(); + aMmboxInfo.date = tEntry.iDate; + + // error + aMmboxInfo.error = tEntry.iError; + + quotaInfoAvailable = ETrue; + } + + CleanupStack::PopAndDestroy( pushedToStack ); + return quotaInfoAvailable; + } +// --------------------------------------------------------- +// CMmsNotificationClientMtm::UpdateMmBoxListL +// --------------------------------------------------------- +// +CMsvOperation* CMmsNotificationClientMtm::UpdateMmBoxListL( + TRequestStatus& aCompletionStatus ) + { + TCommandParameters parameters; // initialized to zero + TCommandParametersBuf paramPack( parameters ); + + CMsvEntrySelection* selection = new ( ELeave ) CMsvEntrySelection; + CleanupStack::PushL( selection ); + selection->AppendL( iServiceId ); + + // Update mmbox list + CMsvOperation* op = InvokeAsyncFunctionL( + EMmsUpdateMmboxList, + *selection, + paramPack, + aCompletionStatus ); + + CleanupStack::PopAndDestroy( selection ); + return op; + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm::GetMmboxFolderL +// --------------------------------------------------------- +// +TMsvId CMmsNotificationClientMtm::GetMmboxFolderL() + { + return iMmsSettings->MMBoxFolder(); + } + +// --------------------------------------------------------- +// CMmsNotificationClientMtm +// --------------------------------------------------------- +// +const TPtrC CMmsNotificationClientMtm::GetApplicationId() const + { + return iMmsHeaders->ApplicId(); + } + +// ================= OTHER EXPORTED FUNCTIONS ============== + +// End of File + +