diff -r 4697dfb2d7ad -r 238255e8b033 messagingapp/msgappfw/plugin/src/ccsmsghandler.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/messagingapp/msgappfw/plugin/src/ccsmsghandler.cpp Fri Apr 16 14:56:15 2010 +0300 @@ -0,0 +1,842 @@ +/* +* 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: CS Message Handler, This class caches the conversation server + * with the message data and also sends run-time updates to the + * server with the message data + * +*/ + + +// USER INCLUDES +#include "ccsmsghandler.h" +#include "msgbiouids.h" + +// SYSTEM INCLUDES +#include +#include +#include +#include +#include +#include +#include +#include +#include // For services messages + +// NOTE:- DRAFTS AND OUTBOX ENTRIES ARE NOT HANDLED IN THE PLUGIN + +// ============================== MEMBER FUNCTIONS ============================ +// ---------------------------------------------------------------------------- +// CCsMsgHandler::NewL +// Two Phase Construction +// ---------------------------------------------------------------------------- +// +CCsMsgHandler* CCsMsgHandler::NewL(MCsMsgObserver *aMsgObserver) + { + PRINT ( _L("Enter CCsMsgHandler::NewL") ); + + CCsMsgHandler* self = new ( ELeave ) CCsMsgHandler(); + CleanupStack::PushL( self ); + self->ConstructL(aMsgObserver); + CleanupStack::Pop( self ); + + PRINT ( _L("End CCsMsgHandler::NewL") ); + + return self; + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::~CCsMsgHandler +// Destructor +// ---------------------------------------------------------------------------- +// +CCsMsgHandler::~CCsMsgHandler() + { + PRINT ( _L("Enter CCsMsgHandler::~CCsMsgHandler") ); + + if(iMsgPluginUtility) + { + delete iMsgPluginUtility; + iMsgPluginUtility = NULL; + } + + if(iConverstationEntryList) + { + iConverstationEntryList->ResetAndDestroy(); + iConverstationEntryList->Close(); + delete iConverstationEntryList; + iConverstationEntryList = NULL; + } + + if(iSmsMtm) + { + delete iSmsMtm; + iSmsMtm = NULL; + } + + if(iMmsMtm) + { + delete iMmsMtm; + iMmsMtm = NULL; + } + + if(iMtmRegistry) + { + delete iMtmRegistry; + iMtmRegistry = NULL; + } + + if(iSession) + { + delete iSession; + iSession = NULL; + } + + if ( iRootEntry ) + { + delete iRootEntry; + iRootEntry = NULL; + } + + if ( iMessages ) + { + iMessages->Reset(); + delete iMessages; + iMessages = NULL; + } + + PRINT ( _L("End CCsMsgHandler::~CCsMsgHandler") ); + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::ConstructL +// Two Phase Construction +// ---------------------------------------------------------------------------- +// +void CCsMsgHandler::ConstructL(MCsMsgObserver *aMsgObserver) + { + PRINT ( _L("Enter CCsMsgHandler::ConstructL") ); + + iMsgObserver = aMsgObserver; + + iSession = CMsvSession::OpenSyncL(*this); + + iMsgPluginUtility = CCsMsgPluginUtility::NewL(); + + iConverstationEntryList = new(ELeave)RPointerArray(); + + iMtmRegistry = CClientMtmRegistry::NewL( *iSession ); + + iSmsMtm = static_cast( iMtmRegistry-> + NewMtmL( KSenduiMtmSmsUid ) ); + + iMmsMtm = static_cast( iMtmRegistry-> + NewMtmL( KSenduiMtmMmsUid ) ); + + iState = EReadInbox; + + iMessageCount = 0; + + PRINT ( _L("End CCsMsgHandler::ConstructL") ); + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::CCsMsgHandler +// Two Phase Construction +// ---------------------------------------------------------------------------- +// +CCsMsgHandler::CCsMsgHandler() + { + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::ProcessResultsL() +// ProcessResultsL fetches results for the searchsort query and +// updates the CCsServer with the fetched data +// ----------------------------------------------------------------------------- +// +void CCsMsgHandler::ProcessResultsL(TMsvEntry entry) + { + PRINT ( _L("Enter CCsMsgHandler::ProcessResultsL")); + + // Cleanup the conversationEntry List initially. + // So that the previous entries not cleaned up in + // the event of Leave have been clean up. + iConverstationEntryList->ResetAndDestroy(); + + RPointerArray addressList; + + // Ignore hidden items during upload + if ( entry.Visible() == EFalse ) + { + return; + } + + if ( entry.Parent() == KMsvGlobalInBoxIndexEntryIdValue || + entry.Parent() == KMsvSentEntryIdValue || + entry.Parent() == KMsvGlobalOutBoxIndexEntryIdValue ) + { + iMsgPluginUtility->CreateContactL(iSession, entry, addressList); + + //process entry + ExtractAddressesL(entry, ERead, addressList); + + addressList.ResetAndDestroy(); + } + + PRINT ( _L("Exit CCsMsgHandler::ProcessResultsL") ); + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::HandleSessionEventL +// Implemented for MMsvSessionObserver +// ---------------------------------------------------------------------------- +// +void CCsMsgHandler::HandleSessionEventL( TMsvSessionEvent aEvent, + TAny* aArg1, + TAny* aArg2, + TAny* /*aArg3*/) + { + PRINT1 ( _L("Enter CCsMsgHandler::HandleSessionEventL aEvent=%d"),aEvent ); + + CMsvEntrySelection* selection=NULL; + TMsvId parent; + + //args + if(aArg1 == NULL || aArg2 == NULL) + { + PRINT ( _L("Enter CCsMsgHandler::HandleSessionEventL arguments invalid")); + return; + } + + //start, processing the event + selection= (CMsvEntrySelection*)aArg1; + parent = *(TMsvId*)aArg2; + + // Cleanup the conversationEntry List initially. + iConverstationEntryList->ResetAndDestroy(); + + switch( aEvent ) + { + case EMsvEntriesChanged: + case EMsvEntriesMoved: + { + HandleEventL(selection,parent); + } + break; + + case EMsvEntriesDeleted: + { + if ( parent == KMsvGlobalInBoxIndexEntryIdValue || + parent == KMsvSentEntryIdValue || + parent == KMsvGlobalOutBoxIndexEntryIdValue) + { + for( TInt i=0 ; i < selection->Count() ; i++ ) + { + TMsvId id = selection->At( i ); + + //use utility to create conversation entry + CCsConversationEntry *conversationEntry = + iMsgPluginUtility->CreateConversationEntryL( + NULL, + id, + 0, + parent, + NULL, + ECsSendStateUnknown, + ECsAttributeNone, + 0); + CleanupStack::PushL(conversationEntry); + iConverstationEntryList->AppendL( conversationEntry ); + CleanupStack::Pop(conversationEntry); + + // call observer interface for each entry + iMsgObserver->HandleDeleteCompleteL(iConverstationEntryList); + + //cleanup before next iteration + iConverstationEntryList->ResetAndDestroy(); + } + } + } + break; + + case EMsvMediaChanged: + iMsgObserver->HandleRefreshCompleteL(); + break; + } + + // Cleanup the conversationEntry List before function exits. + iConverstationEntryList->ResetAndDestroy(); + PRINT ( _L("Exit CCsMsgHandler::HandleSessionEventL") ); + } + +// --------------------------------------------------------------------- +// CCsMsgHandler::HandleEvent +// Handle events +// --------------------------------------------------------------------- +// +void CCsMsgHandler::HandleEventL(CMsvEntrySelection* aSelection, TMsvId aParent) + { + PRINT ( _L("Enter CCsMsgHandler::HandleEvent") ); + TMsvEntry entry; + TMsvId service; + TInt error= KErrNone; + RPointerArray addressList; + + for( TInt i=0 ; i < aSelection->Count() ; i++ ) + { + error = iSession->GetEntry(aSelection->At(i),service,entry); + + if ( entry.Visible() == EFalse ) + { + // Do a delete if entry becomes invisible. + // e.g) My Nokia registration messages. + RPointerArray* hiddenEntries = + new (ELeave) RPointerArray(); + + CCsConversationEntry *conversationEntry = + iMsgPluginUtility->CreateConversationEntryL ( + NULL, + entry.Id(), + 0, + aParent, + NULL, + ECsSendStateUnknown, + ECsAttributeNone, + 0 ); + CleanupStack::PushL(conversationEntry); + hiddenEntries->AppendL( conversationEntry ); + CleanupStack::Pop(conversationEntry); + + // Delete at server + iMsgObserver->HandleDeleteCompleteL(hiddenEntries); + hiddenEntries->ResetAndDestroy(); + hiddenEntries->Close(); + delete hiddenEntries; + + break; + } + + if ( (KErrNone == error) && (IsMtmSupported(entry.iMtm.iUid) ) ) + { + // sent/inbox/Outbox entry + if ( aParent == KMsvSentEntryIdValue || + aParent == KMsvGlobalInBoxIndexEntryIdValue ) + { + // currently server needs number, so getting it from header + iMsgPluginUtility->CreateContactL(iSession, entry, + addressList); + + //process entry + // entry created in sent already exists, hence an update + ExtractAddressesL(entry, EUpdate, addressList); + + addressList.ResetAndDestroy(); + } + + //for drafts and outbox, the entry changes multiple times, + // so making a check if entry has changed + else if(aParent == KMsvGlobalOutBoxIndexEntryIdValue) + { + //outbox + if(!(iMsgPluginUtility->CompareEntry(iPrevEntry,entry,aParent))) + { + TUint sendState = entry.SendingState(); + + // if the entry state is sent, we dont need to process it + // as it is going to appear in sent items + if( ECsSendStateSent != iMsgPluginUtility->GetSendState(entry) ) + { + // currently server needs number, so getting it from header + iMsgPluginUtility->CreateContactL(iSession, entry, + addressList); + + //process entry + // entry created in sent already exists, hence an update + ExtractAddressesL(entry, EUpdate, addressList); + + iPrevEntry = entry; + + addressList.ResetAndDestroy(); + } + }//end check changed entry + } + } + }//end for loop + + PRINT ( _L("Exit CCsMsgHandler::HandleEvent") ); + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::CreateAndAddEntryL +// Creates CCsConversationEntry and adds to the list +// ---------------------------------------------------------------------------- +// +void CCsMsgHandler::CreateAndAddEntryL(const TDesC& aContact, + const TDesC& aDescription, + const TMsvEntry& aEntry) + { + PRINT ( _L("Enter CCsMsgHandler::CreateAndAddEntryL") ); + + HBufC* contact = NULL; + HBufC* sDescription = NULL; + + if (aContact.Length()>0) + { + contact = aContact.AllocL(); + CleanupStack::PushL(contact); + } + if (aDescription.Length()>0) + { + sDescription = aDescription.AllocL(); + CleanupStack::PushL(sDescription); + } + + //use utility to create conversation entry + CCsConversationEntry *conversationEntry = iMsgPluginUtility->CreateConversationEntryL( + contact, + aEntry.Id(), + aEntry.iDate.Int64(), + aEntry.Parent(), + sDescription, + iMsgPluginUtility->GetSendState(aEntry), + iMsgPluginUtility->GetMsgAttributes(aEntry), + ExtractCsType(aEntry)); + CleanupStack::PushL(conversationEntry); + + //add to the list + iConverstationEntryList->AppendL( conversationEntry ); + CleanupStack::Pop(conversationEntry); + + // cleanup + if (sDescription) + { + CleanupStack::PopAndDestroy(sDescription); + } + if (contact) + { + CleanupStack::PopAndDestroy(contact); + } + + PRINT ( _L("Exit CCsMsgHandler::CreateAndAddEntryL") ); + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::ProcessEntryL +// Creates CCsConversationEntry and adds to the list +// ---------------------------------------------------------------------------- +// +void CCsMsgHandler::ProcessEntryL( TEventType aEvent, const TDesC& aContact, + const TDesC& aDescription, const TMsvEntry& aEntry) + { + PRINT ( _L("Enter CCsMsgHandler::ProcessEntryL") ); + + // create and add entry to the list + CreateAndAddEntryL(aContact,aDescription,aEntry); + + // call cs observer interface for each entry + switch(aEvent) + { + case ERead: + { + iMsgObserver->HandleReadCompleteL(iConverstationEntryList); + } + break; + case EUpdate: + { + iMsgObserver->HandleUpdateCompleteL(iConverstationEntryList); + } + break; + } + + // Cleanup the conversationEntry List, as we are just sending one entry at a time + iConverstationEntryList->ResetAndDestroy(); + + PRINT ( _L("Exit CCsMsgHandler::ProcessEntryL") ); + } + +// ---------------------------------------------------------------------------- +// CCsMsgHandler::ExtractAddressL +// Extracts the addresses in the to field and updates them to server +// ---------------------------------------------------------------------------- +// +void CCsMsgHandler::ExtractAddressesL( + TMsvEntry aEntry, + TEventType aEvent, + RPointerArray& addressList ) + { + PRINT ( _L("Enter CCsMsgHandler::ExtractAddressesL") ); + + // For SMS read the whole body. + // For bio type SMS read the iDescription + // For other message types read the iDescription + // Note: After the LoadMessageL() the iDescription is getting + // deleted so need to make a copy before that. + TPtrC description; + HBufC* tmpBuffer = NULL; + + if ( (aEntry.iBioType && + aEntry.iBioType != KUidMsgSubTypeMmsAudioMsg.iUid ) || + aEntry.iMtm == KSenduiMtmBtUid ) + { + tmpBuffer = aEntry.iDescription.AllocL(); + description.Set( tmpBuffer->Des() ); + } + else if ( aEntry.iMtm == KSenduiMtmSmsUid ) + { + iSmsMtm->SwitchCurrentEntryL( aEntry.Id() ); + iSmsMtm->LoadMessageL(); + + CRichText& body = iSmsMtm->Body(); + TInt smsLength = body.DocumentLength(); + tmpBuffer = HBufC::NewL(smsLength); + TPtr ptr(tmpBuffer->Des()); + body.Extract(ptr, 0); + description.Set( tmpBuffer->Des() ); + } + else if ( aEntry.iMtm == KSenduiMtmMmsUid || + aEntry.iMtm == KSenduiMMSNotificationUid) + { + tmpBuffer = aEntry.iDescription.AllocL(); + description.Set( tmpBuffer->Des() ); + + iMmsMtm->SwitchCurrentEntryL( aEntry.Id() ); + iMmsMtm->LoadMessageL(); + + // Handle addresses + if ( aEntry.Parent() == KMsvGlobalInBoxIndexEntryIdValue ) + { + HBufC* address = iMmsMtm->Sender().AllocL(); + addressList.Append(address); + } + else if ( aEntry.Parent() == KMsvSentEntryIdValue || + aEntry.Parent() == KMsvGlobalOutBoxIndexEntryIdValue ) + { + const CMsvRecipientList& addresses = iMmsMtm->AddresseeList(); + TInt count = addresses.Count(); + + for( TInt i = 0; i < count; i++) + { + HBufC* address = addresses[i].AllocL(); + TPtrC pureAddress = iMsgPluginUtility->PureAddress(*address); + HBufC* address1 = pureAddress.AllocL(); + addressList.Append(address1); + delete address; + } + } + } + else + { + return; + } + + if ( addressList.Count() > 0 ) + { + for ( int i = 0; i < addressList.Count(); i++ ) + { + HBufC* address = addressList[i]; + ProcessEntryL(aEvent, *address, description, aEntry); + } + } + else + { + // Unknown + ProcessEntryL(aEvent, KNullDesC, description, aEntry); + } + + if ( tmpBuffer ) + { + delete tmpBuffer; + } + + PRINT ( _L("Exit CCsMsgHandler::ExtractAddressesL") ); + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::UploadMsgL() +// State machine to upload all messages +// ----------------------------------------------------------------------------- +// +TInt CCsMsgHandler::UploadMsgL() + { + switch ( iState ) + { + case EReadInbox: + { + iRootEntry = iSession->GetEntryL(KMsvGlobalInBoxIndexEntryId); + + // Set sort order + TMsvSelectionOrdering order; + order.SetSorting(EMsvSortById); + iRootEntry->SetSortTypeL(order); + + iMessages = iRootEntry->ChildrenL(); + iMessageCount = iRootEntry->Count(); + + if ( iMessageCount ) + iState = EProcessInbox; + else + { + iState = EReadSent; + CleanupL(); + } + + return 1; + } + + case EProcessInbox: + { + iMessageCount = iMessageCount - 1; + TMsvEntry entry = iRootEntry->ChildDataL(iMessages->At(iMessageCount)); + if(IsMtmSupported(entry.iMtm.iUid)) + { + ProcessResultsL(entry); + } + + if ( iMessageCount ) + iState = EProcessInbox; + else + { + iState = EReadSent; + CleanupL(); + } + + return 1; + } + + case EReadSent: + { + iRootEntry = iSession->GetEntryL(KMsvSentEntryId); + + // Set sort order + TMsvSelectionOrdering order; + order.SetSorting(EMsvSortById); + iRootEntry->SetSortTypeL(order); + + iMessages = iRootEntry->ChildrenL(); + iMessageCount = iRootEntry->Count(); + + if ( iMessageCount ) + iState = EProcessSent; + else + { + iState = EReadOutbox; + CleanupL(); + } + + return 1; + } + + case EProcessSent: + { + iMessageCount = iMessageCount - 1; + TMsvEntry entry = iRootEntry->ChildDataL(iMessages->At(iMessageCount)); + if(IsMtmSupported(entry.iMtm.iUid)) + { + ProcessResultsL(entry); + } + + if ( iMessageCount ) + iState = EProcessSent; + else + { + iState = EReadOutbox; + CleanupL(); + } + + return 1; + } + + case EReadOutbox: + { + iRootEntry = iSession->GetEntryL(KMsvGlobalOutBoxIndexEntryId); + + // Set sort order + TMsvSelectionOrdering order; + order.SetSorting(EMsvSortById); + iRootEntry->SetSortTypeL(order); + + iMessages = iRootEntry->ChildrenL(); + iMessageCount = iRootEntry->Count(); + + if ( iMessageCount ) + iState = EProcessOutbox; + else + { + iState = EComplete; + iMsgObserver->HandleCachingCompleted(); + CleanupL(); + return 0; // DONE + } + + return 1; + } + + case EProcessOutbox: + { + iMessageCount = iMessageCount - 1; + TMsvEntry entry = iRootEntry->ChildDataL(iMessages->At(iMessageCount)); + if(IsMtmSupported(entry.iMtm.iUid)) + { + ProcessResultsL(entry); + } + + if ( iMessageCount ) + iState = EProcessOutbox; + else + { + iState = EComplete; + iMsgObserver->HandleCachingCompleted(); + CleanupL(); + return 0; // DONE + } + + return 1; + } + } + + return 0; + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::UploadMsg() +// CIdle callback +// ----------------------------------------------------------------------------- +// +TInt CCsMsgHandler::UploadMsg(TAny* aArg) + { + CCsMsgHandler* handler = (CCsMsgHandler*) aArg; + TInt ok = 0; + TRAPD(err, ok = handler->UploadMsgL()); + return ((err == KErrNone) && ok); + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::StartL() +// This function starts the state machine to fetch sms data from msvserver +// ----------------------------------------------------------------------------- +// +void CCsMsgHandler::StartL() + { + PRINT ( _L("Enter CCsMsgHandler::Start") ); + + iState = EReadInbox; + TCallBack callback = TCallBack(UploadMsg, (TAny*) this); + iIdle = CIdle::NewL(CActive::EPriorityLow); + iIdle->Start(callback); + + PRINT ( _L("End CCsMsgHandler::Start") ); + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::CleanupL() +// Helper function for state machine cleanup +// ----------------------------------------------------------------------------- +// +void CCsMsgHandler::CleanupL() + { + if ( iRootEntry ) + { + delete iRootEntry; + iRootEntry = NULL; + } + + if ( iMessages ) + { + iMessages->Reset(); + delete iMessages; + iMessages = NULL; + } + + iMessageCount = 0; + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::IsMtmSupported() +// +// ----------------------------------------------------------------------------- +// +TBool CCsMsgHandler::IsMtmSupported(long uid) + { + if ( KSenduiMtmSmsUidValue == uid || \ + KSenduiMtmBtUidValue == uid || \ + KSenduiMtmMmsUidValue == uid || \ + KSenduiMtmBioUidValue == uid || \ + KSenduiMMSNotificationUidValue == uid || \ + KUidMtmWapPush == TUid::Uid(uid) ) + { + return ETrue; + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CCsMsgHandler::ExtractCsType() +// Extracts the Message type based on the MTM Uid +// ----------------------------------------------------------------------------- +// +TCsType CCsMsgHandler::ExtractCsType( const TMsvEntry& aEntry) + { + TCsType type = ECsUnknown; + switch(aEntry.iMtm.iUid) + { + case KSenduiMtmSmsUidValue: + type = ECsSMS; + break; + case KSenduiMtmBtUidValue: + type = ECsBlueTooth; + break; + case KSenduiMtmMmsUidValue: + if(aEntry.iBioType == KUidMsgSubTypeMmsAudioMsg.iUid) + { + type = ECsAudio; + } + else + { + type = ECsMMS; + } + break; + case KSenduiMMSNotificationUidValue: + type = ECsMmsNotification; + break; + case KSenduiMtmBioUidValue: + { + type = ECsBioMsg; + + // based on the biotype uid set message type + if(aEntry.iBioType == KMsgBioUidRingingTone.iUid) + { + type = ECsRingingTone; + } + else if(aEntry.iBioType == KMsgBioProvisioningMessage.iUid) + { + type = ECsProvisioning; + } + else if (aEntry.iBioType == KMsgBioUidVCard.iUid) + { + type = ECsBioMsg_VCard; + } + else if (aEntry.iBioType == KMsgBioUidVCalendar.iUid) + { + type = ECsBioMsg_VCal; + } + } + break; + default: + type = ECsUnknown; + break; + } + return (type); + } +// End of file +