messagingfw/sendas/server/src/csendassession.cpp
changeset 0 8e480a14352b
equal deleted inserted replaced
-1:000000000000 0:8e480a14352b
       
     1 // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 //
       
    15 
       
    16 #include "csendassession.h"
       
    17 
       
    18 #include <msvids.h>
       
    19 #include <s32mem.h> 
       
    20 #include <csendasaccounts.h>
       
    21 #include <csendasmessagetypes.h>
       
    22 #include <mtmuids.h>
       
    23 #include <mtclreg.h>
       
    24 #include <mtclbase.h>
       
    25 
       
    26 #include "csendasserver.h"
       
    27 #include "csendasmtmmanager.h"
       
    28 #include "csendasmessage.h"
       
    29 #include "sendasserverdefs.h"
       
    30 #include "tsendasserverpanic.h"
       
    31 
       
    32 CSendAsSession* CSendAsSession::NewL(const TVersion& aVersion, CSendAsServer& aServer)
       
    33 	{
       
    34 	TVersion version(KSendAsServerVersionMajor, KSendAsServerVersionMinor, KSendAsServerVersionBuild);
       
    35 	if( !User::QueryVersionSupported(version, aVersion) )
       
    36 		{
       
    37 		User::Leave(KErrNotSupported);
       
    38 		}
       
    39 	
       
    40 	CSendAsSession* self = new(ELeave) CSendAsSession(aServer);
       
    41 	CleanupStack::PushL(self);
       
    42 	self->ConstructL();
       
    43 	CleanupStack::Pop(self);
       
    44 	return self;
       
    45 	}
       
    46 	
       
    47 void CSendAsSession::ConstructL()
       
    48 	{
       
    49 	iMessages = CObjectIx::NewL();
       
    50 	iContainer = iServer.NewContainerL();
       
    51 	TMsvSelectionOrdering order(KMsvNoGrouping, EMsvSortByDetails, ETrue);
       
    52 	iMsvEntry = CMsvEntry::NewL(GetMsvSessionL(), KMsvRootIndexEntryId, order);
       
    53 	iSendAsAccounts = CSendAsAccounts::NewL();
       
    54 	
       
    55 	// Prepare available message type list
       
    56 	iAvailableMessageTypes = CSendAsMessageTypes::NewL();
       
    57 	ResetTypeFilterL();
       
    58 	}
       
    59 	
       
    60 CSendAsSession::CSendAsSession(CSendAsServer& aServer)
       
    61 : iServer(aServer)
       
    62 	{
       
    63 	}
       
    64 
       
    65 CSendAsSession::~CSendAsSession()
       
    66 	{
       
    67 	delete iMessages;
       
    68 	// iContainer will be deleted by the server
       
    69 	iServer.SessionClosed(iContainer);
       
    70 	delete iSendAsAccounts;
       
    71 	delete iAvailableMessageTypes;
       
    72 	delete iMsvEntry;
       
    73 	}
       
    74 	
       
    75 /** Service the incoming message.
       
    76 
       
    77 If the message is for the session object, it will be dispatched to
       
    78 the correct handler.  If the message is for the subsession object,
       
    79 it will be dispatched to the handler located in the subsession.
       
    80 
       
    81 This allows all of the subsession logic to be internal to itself.
       
    82 
       
    83 If a handler requires an asynchronous response, then this method
       
    84 should return ETrue.  If this method leaves, the trap harness in
       
    85 the ServiceL method will catch the error and complete the message
       
    86 with the error code.
       
    87 
       
    88 @param	aMessage
       
    89 The IPC message object.
       
    90 */
       
    91 TBool CSendAsSession::DoServiceL(const RMessage2& aMessage)
       
    92 	{
       
    93 	// session methods
       
    94 	switch (aMessage.Function())
       
    95 		{
       
    96 		case ESASSetFilter:
       
    97 			DoSetMessageTypeFilterL(aMessage);
       
    98 			break;
       
    99 		case ESASClearFilter:
       
   100 			DoClearMessageTypeFilterL();
       
   101 			break;
       
   102 		case ESAMDestroySubSession:
       
   103 			// this is a sub session message, which means that the handle is transmitted
       
   104 			// automatically, but we will handle it at the session level so we can
       
   105 			// not only close the subsession, but also delete the object properly.
       
   106 			RemoveMessage(aMessage.Int3());
       
   107 			break;
       
   108 		case ESASGetMessageTypeListLength:
       
   109 			DoGetMessageTypeListLengthL(aMessage);
       
   110 			break;
       
   111 		case ESASGetMessageTypes:
       
   112 			DoGetMessageTypeListL(aMessage);
       
   113 			break;
       
   114 		case ESASGetAccountListLength:
       
   115 			DoGetAccountListLengthL(aMessage);
       
   116 			break;
       
   117 		case ESASGetAccountList:
       
   118 			DoGetAccountListL(aMessage);
       
   119 			break;
       
   120 		case ESASCreateSubSession:
       
   121 			CreateSubsessionL(aMessage);
       
   122 			break;
       
   123 		default:
       
   124 			{
       
   125 			// must be a subsession method
       
   126 			CSendAsMessage* msg = MessageFromHandle(aMessage.Int3());
       
   127 			if( msg == NULL )
       
   128 				{
       
   129 				PanicClient(aMessage, ESendAsClientPanicBadSubSessionHandle);
       
   130 				User::Leave(KErrBadHandle);
       
   131 				}
       
   132 			return msg->DoSubSessionServiceL(aMessage);
       
   133 			}
       
   134 		}
       
   135 	return EFalse;	
       
   136 	}
       
   137 
       
   138 /** Create a new subsession object to represent a message.
       
   139 
       
   140 Each message is represented by a CSendAsMessage object.  These objects
       
   141 are derived from CContainer.  This allows us to use the object container
       
   142 framework to keep track of allocated objects and to ensure that the
       
   143 object handles are unique.
       
   144 
       
   145 The RMessage is required so that the session can pass the new
       
   146 subsession handle to the client-side RSubSession object.
       
   147 
       
   148 @param	aMessage
       
   149 The IPC message object.
       
   150 */
       
   151 void CSendAsSession::CreateSubsessionL(const RMessage2& aMessage)
       
   152 	{
       
   153 	// new message (subsession)
       
   154 	CSendAsMessage* message = CSendAsMessage::NewL(*this);
       
   155 	CleanupClosePushL(*message);
       
   156 
       
   157 	// add message class into the container and obtain a handle for it.
       
   158 	iContainer->AddL(message);
       
   159 	TInt id = iMessages->AddL(message);
       
   160 	CleanupStack::Pop(message);
       
   161 	
       
   162 	// write the handle back to the client
       
   163 	TPckg<TInt> pckg(id);
       
   164 	TInt err = aMessage.Write(3, pckg);
       
   165 
       
   166 	if( err != KErrNone )
       
   167 		{
       
   168 		iMessages->Remove(id);
       
   169 		message->Close();
       
   170 
       
   171 		User::Leave(err);
       
   172 		}
       
   173 	++iMessageCount;
       
   174 	}
       
   175 
       
   176 /** Find a subsession pointer from its handle.
       
   177 
       
   178 A message sent from an RSubSession-derived object will always contain
       
   179 a handle to the server-side subsession object in parameter 3.
       
   180 
       
   181 This method takes that handle and looks it up in the object index to
       
   182 find the pointer to the correct subsession instance.
       
   183 
       
   184 @param	aHandle
       
   185 The handle for the subsession object
       
   186 
       
   187 @return
       
   188 The pointer to the subsesion object referred to by aHandle if it exists,
       
   189 otherwise NULL is returned.
       
   190 */
       
   191 CSendAsMessage* CSendAsSession::MessageFromHandle(TUint aHandle)
       
   192 	{
       
   193 	return static_cast<CSendAsMessage*>(iMessages->At(aHandle));
       
   194 	}
       
   195 	
       
   196 void CSendAsSession::RemoveMessage(TUint aHandle)
       
   197 	{
       
   198 	// this operation will delete the subsession.
       
   199 	iMessages->Remove(aHandle);
       
   200 	--iMessageCount;
       
   201 	}
       
   202 	
       
   203 void CSendAsSession::PanicClient(const RMessage2& aMessage, TSendAsClientPanic aPanic) const
       
   204 	{
       
   205 	_LIT(KSendAsServerSession, "SendAsSession");
       
   206 	aMessage.Panic(KSendAsServerSession, aPanic);
       
   207 	}
       
   208 
       
   209 /** Add a message type filter to the list.
       
   210 
       
   211 This removes any non-compliant MTMs from the list of available MTMs.
       
   212 
       
   213 This is a cumulative operation, filters are applied as they are received
       
   214 and the list is shortened each time.
       
   215 
       
   216 @param	aMessage
       
   217 The IPC message object.
       
   218 */
       
   219 void CSendAsSession::DoSetMessageTypeFilterL(const RMessage2& aMessage)
       
   220 	{
       
   221 	// extract filter
       
   222 	TPckgBuf<TSendAsMessageTypeFilter> filterBuf;
       
   223 	aMessage.ReadL(0, filterBuf);
       
   224 	
       
   225 	// apply to available mtm list
       
   226 	AddTypeFilterL(filterBuf());
       
   227 	}
       
   228 
       
   229 /** Remove the message type filter.
       
   230 
       
   231 In reality, this means that we repopulate the entire list.
       
   232 */
       
   233 void CSendAsSession::DoClearMessageTypeFilterL()
       
   234 	{
       
   235 	ResetTypeFilterL();
       
   236 	}
       
   237 
       
   238 void CSendAsSession::DoGetMessageTypeListLengthL(const RMessage2& aMessage)
       
   239 	{
       
   240 	// return size of message types data
       
   241 	TPckgBuf<TUint32> buf(iAvailableMessageTypes->Size());
       
   242 	aMessage.WriteL(0, buf);
       
   243 	}
       
   244 	
       
   245 void CSendAsSession::DoGetMessageTypeListL(const RMessage2& aMessage)
       
   246 	{
       
   247 	// buffer to hold message types data
       
   248 	HBufC8* buffer = HBufC8::NewLC(iAvailableMessageTypes->Size());
       
   249 	
       
   250 	// stream 
       
   251 	RDesWriteStream strm;
       
   252 	CleanupClosePushL(strm);
       
   253 	TPtr8 ptr(buffer->Des());
       
   254 	strm.Open(ptr);
       
   255 
       
   256 	// write to stream
       
   257 	iAvailableMessageTypes->ExternalizeL(strm);
       
   258 	strm.CommitL();
       
   259 	aMessage.WriteL(0, *buffer);
       
   260 
       
   261 	// clean up
       
   262 	CleanupStack::PopAndDestroy(2, buffer); // buffer, strm
       
   263 	}
       
   264 
       
   265 void CSendAsSession::DoGetAccountListLengthL(const RMessage2& aMessage)
       
   266 	{
       
   267 	// message slot 1 contains the mtm uid 
       
   268 	TPckgBuf<TUid> uidBuf;
       
   269 	aMessage.ReadL(1, uidBuf);
       
   270 
       
   271 	// reset the account list
       
   272 	iSendAsAccounts->Reset();
       
   273 	
       
   274 	// get account list for this mtm
       
   275 	TUid acctUid = uidBuf();
       
   276 	iMsvEntry->SetEntryL(KMsvRootIndexEntryId);
       
   277 	CMsvEntrySelection* selection = iMsvEntry->ChildrenWithMtmL(acctUid);
       
   278 	CleanupStack::PushL(selection);
       
   279 	
       
   280 	// populate account list
       
   281 	TInt count = selection->Count();
       
   282 	iSendAsAccounts->SetMessageType(acctUid);
       
   283 	for (TInt i=0; i<count; ++i)
       
   284 		{
       
   285 		TSendAsAccount id = selection->At(i);
       
   286 		// set context
       
   287 		iMsvEntry->SetEntryL(id);
       
   288 		// add account		
       
   289 		iSendAsAccounts->AppendAccountL(iMsvEntry->Entry().iDetails, id);
       
   290 		}
       
   291 	CleanupStack::PopAndDestroy(selection);
       
   292 
       
   293 	// get size
       
   294 	TPckgBuf<TInt> buf(iSendAsAccounts->Size());
       
   295 	aMessage.WriteL(0, buf);
       
   296 	}
       
   297 	
       
   298 void CSendAsSession::DoGetAccountListL(const RMessage2& aMessage)
       
   299 	{
       
   300 	// buffer to hold accounts data
       
   301 	HBufC8* buffer = HBufC8::NewLC(iSendAsAccounts->Size());
       
   302 	
       
   303 	// buffer write stream
       
   304 	RDesWriteStream strm;
       
   305 	CleanupClosePushL(strm);
       
   306 	TPtr8 ptr(buffer->Des());
       
   307 	strm.Open(ptr);
       
   308 
       
   309 	// write to buffer
       
   310 	iSendAsAccounts->ExternalizeL(strm);
       
   311 	
       
   312 	// commit and return buffer
       
   313 	strm.CommitL();
       
   314 	aMessage.WriteL(0, *buffer);
       
   315 
       
   316 	// clean up
       
   317 	CleanupStack::PopAndDestroy(2, buffer);	// buffer, strm
       
   318 	}
       
   319 	
       
   320 CMsvSession& CSendAsSession::GetMsvSessionL()
       
   321 	{ 
       
   322 	return iServer.GetMsvSessionL(); 
       
   323 	}
       
   324 
       
   325 CSendAsActiveContainer& CSendAsSession::ActiveContainer()
       
   326 	{
       
   327 	return iServer.ActiveContainer();
       
   328 	}
       
   329 
       
   330 const TUid& CSendAsSession::NotifierUid() const
       
   331 	{
       
   332 	return iServer.NotifierUid();
       
   333 	}
       
   334 
       
   335 const TUid& CSendAsSession::EditUtilsPluginUid() const
       
   336 	{
       
   337 	return iServer.EditUtilsPluginUid();
       
   338 	}
       
   339 
       
   340 /*
       
   341  *	methods from CSession2
       
   342  */
       
   343  
       
   344 /** Session ServiceL method.
       
   345 
       
   346 This method traps the real serviceL method so that leaves can
       
   347 be trapped and returned as error completion codes on the message.
       
   348 
       
   349 This prevents the session from leaving during the server AO's
       
   350 RunL and causing a panic.
       
   351 
       
   352 @param	aMessage
       
   353 The IPC message object.
       
   354 */
       
   355 void CSendAsSession::ServiceL(const RMessage2& aMessage)
       
   356 	{
       
   357 	TBool async = EFalse;
       
   358 	TRAPD(err, async = DoServiceL(aMessage));
       
   359 	
       
   360 	// complete the message if necessary.
       
   361 	if (!async || err != KErrNone)
       
   362 		{
       
   363 		aMessage.Complete(err);
       
   364 		}
       
   365 	}
       
   366 
       
   367 
       
   368 /** Handles session disconnect.
       
   369 
       
   370 @param	aMessage
       
   371 The IPC message object.
       
   372 */
       
   373 void CSendAsSession::Disconnect(const RMessage2& aMessage)
       
   374 	{
       
   375 	// Cancel all sub-session objects.
       
   376 	TInt count = iMessages->Count();
       
   377 	for( TInt i=0; i<count; ++i)
       
   378 		{
       
   379 		CSendAsMessage* message = static_cast<CSendAsMessage*>((*iMessages)[i]);
       
   380 		message->CancelMessage();
       
   381 		}
       
   382 	
       
   383 	// Must call the base class implementation - this will delete the object.
       
   384 	CSession2::Disconnect(aMessage);
       
   385 	}
       
   386 	
       
   387 
       
   388 /*
       
   389  *	available Client MTM array management and access methods.
       
   390  */
       
   391 	
       
   392 /** Resets the available message type list
       
   393 
       
   394 */
       
   395 void CSendAsSession::ResetTypeFilterL()
       
   396 	{
       
   397 	// get unfiltered MTM array
       
   398 	RArray<TUid>& aMtmUidArray = iServer.GetMtmManager()->GetMtmUidArray();
       
   399 	
       
   400 	// get client registry
       
   401 	CClientMtmRegistry* aClientRegistry = iServer.GetMtmManager()->GetClientMtmRegistry();
       
   402 
       
   403 	// reset filtered MTM array
       
   404 	iAvailableMessageTypes->Reset();
       
   405 	
       
   406 	// populate filtered MTM array
       
   407 	TInt count = aMtmUidArray.Count();
       
   408 	for( TInt i=0; i<count; ++i )
       
   409 		{
       
   410 		// mtm uid
       
   411 		TUid mtmUid = aMtmUidArray[i];
       
   412 		// mtm name
       
   413 		TPtrC name = aClientRegistry->RegisteredMtmDllInfo(mtmUid).HumanReadableName();
       
   414 		iAvailableMessageTypes->AppendMessageTypeL(name, mtmUid);
       
   415 		}
       
   416 	}
       
   417 
       
   418 /** Reduces available message type list according to filter 
       
   419 
       
   420 @param	aFilter
       
   421 The filter to be applied
       
   422 */
       
   423 void CSendAsSession::AddTypeFilterL(const TSendAsMessageTypeFilter& aFilter)
       
   424 	{
       
   425 	if( aFilter.iMessageCapability == KUidMtmQueryCanSendMsg )
       
   426 		{
       
   427 		// the list of mtms available to sendas sessions is created with this 
       
   428 		// capability by default by the sendas MTM manager, so no action needed
       
   429 		return;
       
   430 		}
       
   431 
       
   432 	// locals used in scan loop
       
   433 	CBaseMtm* mtm = NULL;
       
   434 	TInt      response;
       
   435 	TInt      error;
       
   436 	TBool     capable;
       
   437 	
       
   438 	// scan list of mtms and filter out those without the required capabilities
       
   439 	TInt count = iAvailableMessageTypes->Count();
       
   440 	while( count-- > 0 )
       
   441 		{
       
   442 		// get mtm by uid		
       
   443 		mtm = iServer.GetMtmManager()->FindStoredMtmL(iAvailableMessageTypes->MessageTypeUid(count));
       
   444 
       
   445 		// check if capability supported
       
   446 		response = 0;
       
   447 		error = mtm->QueryCapability(aFilter.iMessageCapability, response);
       
   448 		
       
   449 		// if capability supported, check conditions 
       
   450 		capable = EFalse;
       
   451 		if( error == KErrNone )
       
   452 			{
       
   453 			switch (aFilter.iCondition)
       
   454 				{
       
   455 			case RSendAs::ESendAsNoCondition:
       
   456 				capable = ETrue;
       
   457 				break;
       
   458 			case RSendAs::ESendAsEquals:
       
   459 				capable = (response == aFilter.iValue);
       
   460 				break;
       
   461 			case RSendAs::ESendAsNotEquals:
       
   462 				capable = (response != aFilter.iValue);
       
   463 				break;
       
   464 			case RSendAs::ESendAsGreaterThan:
       
   465 				capable = (response > aFilter.iValue);
       
   466 				break;
       
   467 			case RSendAs::ESendAsLessThan:
       
   468 				capable = (response < aFilter.iValue);
       
   469 				break;
       
   470 			case RSendAs::ESendAsBitwiseAnd:
       
   471 				capable = (response & aFilter.iValue);
       
   472 				break;
       
   473 			case RSendAs::ESendAsBitwiseOr:
       
   474 				capable = (response | aFilter.iValue);
       
   475 				break;
       
   476 			case RSendAs::ESendAsBitwiseNand:
       
   477 				capable = !(response & aFilter.iValue);
       
   478 				break;
       
   479 			case RSendAs::ESendAsBitwiseNor:
       
   480 				capable = !(response | aFilter.iValue);
       
   481 				break;
       
   482 			default:
       
   483 				break;
       
   484 				}
       
   485 			}
       
   486 		else if( error != KErrNotSupported )
       
   487 			{
       
   488 			User::Leave(error); 
       
   489 			}
       
   490 
       
   491 		if( !capable )
       
   492 			{
       
   493 			// mtm is not capable, so remove it from the available list
       
   494 			iAvailableMessageTypes->RemoveMessageType(count);
       
   495 			}
       
   496 		}
       
   497 	}
       
   498 
       
   499 /** Updates the array of available Client MTMs
       
   500 
       
   501 */
       
   502 void CSendAsSession::HandleMtmChange()
       
   503 	{
       
   504 	// get unfiltered MTM UID array
       
   505 	RArray<TUid>& aMtmUidArray = iServer.GetMtmManager()->GetMtmUidArray();
       
   506 	
       
   507 	// check for removed mtm from filtered lists
       
   508 	TInt count = iAvailableMessageTypes->Count();
       
   509 	for( TInt i=0; i<count; ++i )
       
   510 		{
       
   511 		if (aMtmUidArray.Find(iAvailableMessageTypes->MessageTypeUid(i)) == KErrNotFound)
       
   512 			{
       
   513 			iAvailableMessageTypes->RemoveMessageType(i);
       
   514 			break;
       
   515 			}
       
   516 		}
       
   517 	}
       
   518 
       
   519 /** Returns the client MTM specified by UID 
       
   520 
       
   521 @param	aMtmUid
       
   522 The UID of the Client MTM
       
   523 */
       
   524 CBaseMtm* CSendAsSession::GetClientMtmL(TUid aMtmUid)
       
   525 	{
       
   526 	return ( iServer.GetMtmManager()->GetClientMtmL(aMtmUid) );
       
   527 	}