messagingfw/sendas/server/src/csendassender.cpp
changeset 0 8e480a14352b
child 22 d2c4c66342f3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/messagingfw/sendas/server/src/csendassender.cpp	Mon Jan 18 20:36:02 2010 +0200
@@ -0,0 +1,413 @@
+// Copyright (c) 2004-2009 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:
+// csendassender.cpp
+//
+
+#include "csendassender.h"
+
+#include <msvids.h>
+#include <mtclbase.h>
+#include <tmsvpackednotifierrequest.h>
+#include <s32mem.h>
+
+#include "msendassenderobserver.h"
+#include "tsendasserverpanic.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS  
+#include "msvconsts.h"
+#endif
+
+// Buffer for IPC messages to notifier
+const TInt KNotifierBufferLength 	= 60;
+const TInt KNotifierBufferIncrement = 20;
+
+CSendAsSender* CSendAsSender::NewL(MSendAsSenderObserver& aObserver)
+	{
+	CSendAsSender* self = new (ELeave) CSendAsSender(aObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CSendAsSender::~CSendAsSender()
+	{
+	// do not notify observer during deletion.
+	iObserver = NULL;
+	Cancel();
+
+	iNotifier.Close();
+	delete iClientMtm;
+	delete iOperation;
+	delete iBuffer;
+	delete iSelection;
+	// Close UPS session
+#if (defined SYMBIAN_USER_PROMPT_SERVICE)	
+    iUpsSubsession.Close();
+	iUpsSession.Close();
+#endif	
+	}
+
+CSendAsSender::CSendAsSender(MSendAsSenderObserver& aObserver)
+: CActive(CActive::EPriorityStandard), iObserver(&aObserver)
+	{
+	CActiveScheduler::Add(this);
+	}
+	
+void CSendAsSender::ConstructL()
+	{
+	iBuffer = HBufC8::NewL(KNotifierBufferLength);
+	User::LeaveIfError(iNotifier.Connect());		
+	iSelection = new (ELeave) CMsvEntrySelection();
+	}
+	
+/**
+Sets the client MTM to use for move and send operations.
+ 
+@param	aClientMtm
+The client MTM.
+*/
+void CSendAsSender::SetClientMtm(CBaseMtm& aClientMtm)
+	{
+	__ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() );
+	__ASSERT_ALWAYS( iClientMtm == NULL, User::Invariant() );
+	__ASSERT_ALWAYS( iSelection != NULL, User::Invariant() );
+	
+	iClientMtm = &aClientMtm;
+	}
+
+/**
+Populates the entry selection from the client MTM's entry.
+*/
+void CSendAsSender::SetEntrySelectionL()
+	{
+	iSelection->Reset();
+	iSelection->AppendL(iClientMtm->Entry().EntryId());
+	}
+
+/**
+Initiates an confirmed / unconfirmed message send operation.
+*/
+#if (defined SYMBIAN_USER_PROMPT_SERVICE)
+void CSendAsSender::SendMessageL(const RMessage2 aMessage, TBool aHasCapability)
+	{
+	__ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() );
+	__ASSERT_ALWAYS( iClientMtm != NULL, User::Invariant() );
+	
+	iState = ESenderAuthoriseSend;
+	// Serialise the recipient list
+	const CMsvRecipientList& rcptList = iClientMtm->AddresseeList();
+	const MDesC16Array& recipient = rcptList.RecipientList();
+	
+	TInt rcptCount = recipient.MdcaCount();
+	TInt size = 0;
+	for(TInt i=0;i<rcptCount; ++i)
+		{
+		size += recipient.MdcaPoint(i).Length();
+		}		
+	
+ 	_LIT16(KComma, ",");
+ 		
+ 	RBuf16 buffer;
+ 	buffer.Create(size+ rcptCount);
+ 	CleanupClosePushL(buffer);
+ 	if(rcptCount > 0)
+ 		{
+ 		buffer.Append(recipient.MdcaPoint(0));	
+ 		}
+ 		
+ 	for(TInt i=1;i<rcptCount; ++i)
+ 		{
+ 		buffer.Append(KComma);
+ 		buffer.Append(recipient.MdcaPoint(i));
+ 		}
+   	
+   	RThread clientThread;
+   	aMessage.Client(clientThread);
+   	
+   	// Connect to UPS service.....
+   	User::LeaveIfError(iUpsSession.Connect());
+ 	
+ 	User::LeaveIfError(iUpsSubsession.Initialise(iUpsSession, clientThread));
+   	
+   	iDecision = EUpsDecNo;
+ 	iUpsSubsession.Authorise(aHasCapability, KUidSendAs2Service, buffer, iDecision, iStatus);
+   	SetActive();
+ 	CleanupStack::PopAndDestroy(&buffer);
+	}
+#endif	
+
+/**
+Initiates an unconfirmed message send operation.
+*/
+void CSendAsSender::SendMessage()
+	{
+	__ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() );
+	__ASSERT_ALWAYS( iClientMtm != NULL, User::Invariant() );
+	
+	// update state and auto-complete - send process started by RunL()
+	iState = ESenderStartingUnconfirmedSend;
+	TRequestStatus* status=&iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+	
+/**
+Initiates a confirmed message send operation.
+ 
+@param	aSecurityInfo
+The security info associated with the message.
+
+@param  aNotifierUid
+The UID of the notifier plugin.
+*/
+void CSendAsSender::SendMessage(const TSecurityInfo& aSecurityInfo, const TUid& aNotifierUid)
+	{
+	__ASSERT_ALWAYS( iState == ESenderIdle, User::Invariant() );
+	__ASSERT_ALWAYS( iClientMtm != NULL, User::Invariant() );
+	
+	// confirmed send - use notifier to prompt the user for confirmation.
+	iSecurityInfo = aSecurityInfo;
+	iNotifierUid  = aNotifierUid;
+
+	// update state and auto-complete
+	iState = ESenderStartingConfirmedSend;
+	TRequestStatus* status=&iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+	
+/**
+Provides progress information for the send operation.
+ 
+@param	aProgress
+The operation progerss object.
+*/
+void CSendAsSender::ProgressL(TMsvSendOperationProgress& aProgress)
+	{
+	switch( iState )
+		{
+	case ESenderStartingUnconfirmedSend:
+	case ESenderStartingConfirmedSend:
+	case ESenderIdle:
+	case ESenderConfirming:
+	case ESenderMoving:
+	case ESenderAuthoriseSend:
+		{
+		aProgress().iState = CMsvSendOperation::ESendStateWaitingToSend;
+		} break;
+	case ESenderSending:
+		{
+		// when sending, operation returns a CMsvSendOperation which returns the
+		// correct progress.
+		const TDesC8& opProgress = iOperation->ProgressL();
+		__ASSERT_ALWAYS(opProgress.Size() == sizeof(CMsvSendOperation::TSendOperationProgress), 
+						TSendAsServerPanic::Panic(TSendAsServerPanic::ESendAsBadDescriptor));
+		TMsvSendOperationProgress& progress = (TMsvSendOperationProgress&) opProgress;
+		aProgress = progress;
+		} break;
+	case ESenderDone:
+		{
+		FinalProgress(aProgress);
+		} break;
+	default:
+		User::Invariant();
+		break;
+		}
+	}
+	
+void CSendAsSender::FinalProgress(TMsvSendOperationProgress& aProgress)
+	{
+	__ASSERT_ALWAYS( iState == ESenderDone, User::Invariant() );
+	
+	aProgress = iFinalProgress;
+	}
+
+/**
+Deletes the current operation
+*/
+void CSendAsSender::DeleteOperation()
+	{
+	delete iOperation;
+	iOperation = NULL;
+	}
+
+/**
+Invokes an asynchronous move operation.
+Moves the message from current location (drafts folder) to the outbox.
+*/
+void CSendAsSender::InvokeMoveOperationL()
+	{
+	iEntry = iClientMtm->Entry().Entry();
+	iClientMtm->Entry().SetEntryL(iEntry.Parent());
+
+	DeleteOperation();
+	iOperation = iClientMtm->Entry().MoveL(iEntry.Id(), KMsvGlobalOutBoxIndexEntryId, iStatus);
+	SetActive();
+
+	iState = ESenderMoving;
+	}
+
+/**
+Invokes an asychronous send operation.
+*/
+void CSendAsSender::InvokeSendOperationL()
+	{
+	// Buffer required for call to InvokeAsyncFunction, unused.
+	TBuf8<1> buf;
+	iClientMtm->Entry().SetEntryL(iEntry.Id());
+	DeleteOperation();
+	// Note: This operation must be a CMsvSendOperation as TMsvSendOperationProgress is needed
+	iOperation = iClientMtm->InvokeAsyncFunctionL(KMTMStandardFunctionsSendMessage, *iSelection, buf, iStatus);
+	SetActive();
+	
+	iState = ESenderSending;	
+	}
+
+/**
+Invokes an asynchronous notification request.
+*/
+void CSendAsSender::InvokeConfirmOperationL()
+	{
+	// Use plugin notifier to get the send confirmation.
+	TMsvPackedNotifierRequest packedInfo(iBuffer);
+	while(packedInfo.Pack(*iSelection, iSecurityInfo) != KErrNone)
+		{
+		// increase the size of the buffer and try again
+		iBuffer->Des().Zero(); // to avoid copying contents
+		iBuffer = iBuffer->ReAllocL(iBuffer->Des().MaxSize() + KNotifierBufferIncrement);
+		}
+
+	iNotifier.StartNotifierAndGetResponse(iStatus, iNotifierUid, *iBuffer, iNotifierResult);
+	SetActive();
+	
+	iState = ESenderConfirming;
+	}
+
+/**
+Notifies the observer that the operation has completed.
+@param  aError 	The error code.
+*/
+void CSendAsSender::Complete(TInt aError)
+	{
+	iState = ESenderDone; // This must be set before notifying observer
+	if( iObserver != NULL )
+		{
+		// notify observer that the send has completed.
+		iObserver->SenderComplete(aError);
+		}
+	}
+	
+/**
+Methods from CActive
+Handles a request completion event.
+Implements the CSendAsSender state machine.
+
+@see CActive::RunL()
+*/
+void CSendAsSender::RunL()
+	{
+	User::LeaveIfError(iStatus.Int());
+	
+	switch( iState )
+		{
+	case ESenderStartingConfirmedSend:
+		{
+		SetEntrySelectionL();
+		InvokeConfirmOperationL();
+		}break;
+	case ESenderStartingUnconfirmedSend:
+		{
+		SetEntrySelectionL();
+		} // fall through
+	case ESenderConfirming:
+		{
+		InvokeMoveOperationL();			
+		} break;
+#if (defined SYMBIAN_USER_PROMPT_SERVICE)		
+	case ESenderAuthoriseSend:
+		{
+		if(iDecision != EUpsDecYes)
+			{
+			Complete(KErrPermissionDenied);
+			}
+		else
+			{
+			SetEntrySelectionL();
+			InvokeMoveOperationL();	
+			}	
+						
+		}break;
+#endif		
+	case ESenderMoving:
+		{
+		InvokeSendOperationL();			
+		} break;
+	case ESenderSending:
+		{
+		TMsvSendOperationProgress& progress = (TMsvSendOperationProgress&)iOperation->FinalProgress();
+		iFinalProgress = progress;
+		Complete(KErrNone);
+		} break;
+	case ESenderIdle:
+	case ESenderDone:
+	default:
+		User::Invariant();
+		}
+	}
+	
+/** 
+Implements cancellation of an outstanding request.
+@see CActive::DoCancel()
+*/
+void CSendAsSender::DoCancel()
+	{
+	switch( iState )
+		{
+		case ESenderConfirming:
+			{
+			iNotifier.NotifyCancel();
+			}break;
+		case ESenderMoving:
+		case ESenderSending:
+			{
+			__ASSERT_ALWAYS( iOperation != NULL, User::Invariant() );
+			iOperation->Cancel();
+			} break;
+#if (defined SYMBIAN_USER_PROMPT_SERVICE)
+		case ESenderAuthoriseSend:
+			{
+			iUpsSubsession.Close();
+			}break;
+#endif
+		case ESenderStartingConfirmedSend:
+		case ESenderStartingUnconfirmedSend:	
+		case ESenderIdle:	
+		case ESenderDone:
+		default:
+			// do nothing...
+			break;
+			}
+	Complete(KErrCancel);
+	}
+	
+/** 
+Handles leaves from the RunL method.
+@see CActive::RunL()
+*/
+TInt CSendAsSender::RunError(TInt aError)
+	{
+	Complete(aError);
+	return KErrNone;
+	}