--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contextframework/cfw/src/cfserver/CFMessageHandlerContext.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,1333 @@
+/*
+* Copyright (c) 2006-2008 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: Message handler context class implementation.
+*
+*/
+
+
+#include <e32base.h>
+#include <s32mem.h>
+#include <e32cmn.h>
+#include <cfcontextsourcecommand.h>
+
+#include "CFMessageHandlerContext.h"
+#include "CFContextObjectImpl.h"
+#include "cfextendedcontextinterface.h"
+#include "CFScriptInterface.h"
+#include "CFContextSubscriptionImpl.h"
+#include "cfcontextindication.h"
+#include "CFContextIndicationImpl.h"
+#include "CFServSession.h"
+#include "CFContextQueryImpl.h"
+#include "cfcommon.h"
+#include "cftrace.h"
+#include "CFContextDataProxy.h"
+#include "cfserviceutils.h"
+
+// CONSTANTS
+
+#ifdef _DEBUG
+LOCAL_C void Panic( const RMessage2& aMessage, TInt aCode )
+ {
+ CCFServSession::PanicClient( aMessage, aCode );
+ }
+#endif
+
+// Local function to clean up RContextQueryArray
+LOCAL_C void CleanupContextQueryArray( TAny* aArray )
+ {
+ RContextQueryArray* array = static_cast<RContextQueryArray*>( aArray );
+ array->ResetAndDestroy();
+ }
+
+// Puts RContextQueryArray in clean up stack
+LOCAL_C void CleanupResetAndDestroyPushL( RContextQueryArray& aArray )
+ {
+ TCleanupItem item( CleanupContextQueryArray, &aArray );
+ CleanupStack::PushL( item );
+ }
+
+// METHODS
+
+CCFMessageHandlerContext* CCFMessageHandlerContext::NewL(
+ MCFExtendedContextInterface& aCFContext,
+ MCFActionInterface& aCFAction,
+ MCFScriptInterface& aScriptInterface )
+ {
+ FUNC_LOG;
+
+ CCFMessageHandlerContext* self = CCFMessageHandlerContext::NewLC(
+ aCFContext,
+ aCFAction,
+ aScriptInterface );
+ CleanupStack::Pop( self );
+
+ return self;
+ }
+
+CCFMessageHandlerContext* CCFMessageHandlerContext::NewLC(
+ MCFExtendedContextInterface& aCFContext,
+ MCFActionInterface& aCFAction,
+ MCFScriptInterface& aScriptInterface )
+ {
+ FUNC_LOG;
+
+ CCFMessageHandlerContext* self = new( ELeave ) CCFMessageHandlerContext(
+ aCFContext,
+ aCFAction,
+ aScriptInterface );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+
+ return self;
+ }
+
+CCFMessageHandlerContext::~CCFMessageHandlerContext()
+ {
+ FUNC_LOG;
+
+ // Cancel outsanding request from client
+ CancelReceiveContextIndicationMessage();
+
+ // Remove all subscriptions from this session
+ iCFContext.UnsubscribeContexts( *this );
+ iCFContext.DeregisterPublisher( *this );
+
+ // Clean buffers
+ iIndicationQueue.ResetAndDestroy();
+ TInt count = iSubscriptionErrors.Count();
+ for( TInt i = 0; i < count; i++ )
+ {
+ delete iSubscriptionErrors[i].iContext;
+ }
+
+ // Close arrays which context are not owned
+ iContextRequestBuffer.Close();
+ }
+
+CCFMessageHandlerContext::CCFMessageHandlerContext(
+ MCFExtendedContextInterface& aCFContext,
+ MCFActionInterface& aCFAction,
+ MCFScriptInterface& aScriptInterface )
+ : CCFMessageHandlerBase( aCFContext, aCFAction, aScriptInterface )
+ {
+ FUNC_LOG;
+ }
+
+void CCFMessageHandlerContext::ConstructL()
+ {
+ FUNC_LOG;
+ }
+
+// METHODS
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::HandleMessageL
+//-----------------------------------------------------------------------------
+//
+TBool CCFMessageHandlerContext::HandleMessageL( const RMessage2& aMessage )
+ {
+ FUNC_LOG;
+
+ INFO_1( "[MessageHandlerContext] Handling IPC message: %d", aMessage.Function() );
+
+ TBool handled = ETrue;
+ switch( aMessage.Function() )
+ {
+
+ // Slot[0] = TDesC - CCFContextObject
+ case EPublishContext:
+ {
+ INFO( "Handling IPC message [EPublishContext]" );
+
+ // Stream context from client buffer
+ CCFContextObjectImpl* context = CCFContextObjectImpl::NewLC();
+ TInt length = aMessage.GetDesLengthL( 0 );
+ HBufC8* buffer = HBufC8::NewLC( length );
+ TPtr8 bufferPtr = buffer->Des();
+ aMessage.ReadL( 0, bufferPtr );
+ RDesReadStream readStream( bufferPtr );
+ readStream.PushL();
+ context->InternalizeL( readStream );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Send request to CF Engine
+ RThread clientThread;
+ aMessage.ClientL( clientThread );
+ CleanupClosePushL( clientThread );
+ TInt err = PublishContext( *context, clientThread );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &clientThread );
+ CleanupStack::PopAndDestroy( context );
+
+ // Complete
+ aMessage.Complete( err );
+
+ INFO( "Handled IPC message [EPublishContext]" );
+
+ break;
+ }
+
+ // Slot[0] = TDesC - CCFContextSubscription
+ case EAddSubscription:
+ {
+ INFO( "Handling IPC message [EAddSubscription]" );
+
+ // Stream subscription from client buffer
+ CCFContextSubscriptionImpl* subscription =
+ CCFContextSubscriptionImpl::NewLC();
+ TInt length = aMessage.GetDesLengthL( 0 );
+ HBufC8* buffer = HBufC8::NewLC( length );
+ TPtr8 bufferPtr = buffer->Des();
+ aMessage.ReadL( 0, bufferPtr );
+ RDesReadStream readStream( bufferPtr );
+ readStream.PushL();
+ subscription->InternalizeL( readStream );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Send request to CF Engine
+ RThread clientThread;
+ aMessage.ClientL( clientThread );
+ CleanupClosePushL( clientThread );
+ TInt err = AddSubscription( subscription, clientThread );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &clientThread );
+ CleanupStack::Pop( subscription );
+
+ // Handle results
+ if( err != KErrNone )
+ {
+ // Notify error
+ DoHandleContextSubscriptionErrorL( err,
+ subscription->ContextSource(),
+ subscription->ContextType() );
+ }
+
+ // Complete
+ aMessage.Complete( KErrNone );
+
+ INFO( "Handled IPC message [EAddSubscription]" );
+
+ break;
+ }
+
+ // Slot[0] = TDesC - CCFContextSubscription
+ case ERemoveSubscription:
+ {
+ INFO( "Handling IPC message [ERemoveSubscription]" );
+
+ // Stream subscription from client buffer
+ CCFContextSubscriptionImpl* subscription =
+ CCFContextSubscriptionImpl::NewLC();
+ TInt length = aMessage.GetDesLengthL( 0 );
+ HBufC8* buffer = HBufC8::NewLC( length );
+ TPtr8 bufferPtr = buffer->Des();
+ aMessage.ReadL( 0, bufferPtr );
+ RDesReadStream readStream( bufferPtr );
+ readStream.PushL();
+ subscription->InternalizeL( readStream );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Send request to CF Engine
+ RemoveSubscription( *subscription );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( subscription );
+
+ // Complete
+ aMessage.Complete( KErrNone );
+
+ INFO( "Handled IPC message [ERemoveSubscription]" );
+
+ break;
+ }
+
+ // Slot[0] = TDes - Buffer
+ // Slot[1] = TPckg<TInt> - Buffer size
+ case EReceiveContextIndicationMessage:
+ {
+ INFO( "Handling IPC message [EReceiveContextIndicationMessage]" );
+
+ ReceiveContextIndicationMessageL( aMessage );
+
+ INFO( "Handled IPC message [EReceiveContextIndicationMessage]" );
+
+ break;
+ }
+
+ // Slot[0] = TDes - Buffer
+ // Slot[1] = TPckg<TInt> - Buffer size
+ case EReceiveMessage:
+ {
+ INFO( "Handling IPC message [EReceiveMessage]" );
+
+ ReceiveMessageL( aMessage );
+
+ INFO( "Handled IPC message [EReceiveMessage]" );
+
+ break;
+ }
+
+ // Slot[0] = TDes - Buffer
+ case EGetContextIndication:
+ {
+ INFO( "Handling IPC message [EGetContextIndication]" );
+
+ // Client has increased buffer size
+ // Get next indication from queue
+ // Message will be completed in the method
+ CompleteNextIndicationFromQueueL( aMessage );
+
+ INFO( "Handled IPC message [EGetContextIndication]" );
+
+ break;
+ }
+
+ // Slot[0] = TDes - Buffer
+ case EGetMessage:
+ {
+ INFO( "Handling IPC message [EGetMessage]" );
+
+ // Client has increased buffer size
+ // Get next indication from queue
+ // Message will be completed in the method
+ CompleteNextMessageFromQueueL( aMessage );
+
+ INFO( "Handled IPC message [EGetMessage]" );
+
+ break;
+ }
+
+
+ // No parameters
+ case ECancelReceiveContextIndicationMessage:
+ {
+ INFO( "Handling IPC message [ECancelReceiveContextIndicationMessage]" );
+
+ CancelReceiveContextIndicationMessage();
+ aMessage.Complete( KErrNone );
+
+ INFO( "Handled IPC message [ECancelReceiveContextIndicationMessage]" );
+
+ break;
+ }
+
+ // No parameters
+ case ECancelReceiveMessage:
+ {
+ INFO( "Handling IPC message [ECancelReceiveContextIndicationMessage]" );
+
+ CancelReceiveMessage();
+ aMessage.Complete( KErrNone );
+
+ INFO( "Handled IPC message [ECancelReceiveContextIndicationMessage]" );
+
+ break;
+ }
+
+
+ // Slot[0] = TDes - Result buffer
+ // Slot[1] = TDesC - CCFContextQuery
+ // Slot[2] = TPckg<TInt> - Buffer size
+ case ERequestContext:
+ {
+ INFO( "Handling IPC message [ERequestContext]" );
+
+ TInt err = KErrNone;
+
+ // Check if the client has already requested contexts but
+ // has failed due too small buffer size
+ if( iContextRequestBuffer.Count() )
+ {
+ // Write request result into client side buffer
+ CompleteRequestContextL( aMessage );
+
+ // Reset buffer
+ iContextRequestBuffer.Reset();
+ }
+ else
+ {
+ // New request
+ // Stream query
+ CCFContextQueryImpl* query =
+ CCFContextQueryImpl::NewLC( KNullDesC, KNullDesC );
+ TInt bufferSize = aMessage.GetDesLengthL( 1 );
+ HBufC8* buffer = HBufC8::NewLC( bufferSize );
+ TPtr8 bufferPtr = buffer->Des();
+ aMessage.ReadL( 1, bufferPtr );
+ RDesReadStream readStream( bufferPtr );
+ readStream.PushL();
+ query->InternalizeL( readStream );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Send request to CF Engine
+ RThread clientThread;
+ aMessage.ClientL( clientThread );
+ CleanupClosePushL( clientThread );
+ err = RequestContext( *query, clientThread );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &clientThread );
+ CleanupStack::PopAndDestroy( query );
+
+ // Handle request context results
+ if( err == KErrNone && iContextRequestBuffer.Count() )
+ {
+ // Write request result into client side buffer if
+ // request succesfull
+ CompleteRequestContextL( aMessage );
+ }
+ else
+ {
+ // Complete with error code
+ aMessage.Complete( err );
+ }
+ }
+
+ INFO( "Handled IPC message [ERequestContext]" );
+
+ break;
+ }
+
+ // Slot[0] = TDes - Result buffer
+ // Slot[1] = TDesC - CCFContextQuery
+ // Slot[2] = TPckg<TInt> - Buffer size
+ case ERequestContextSet:
+ {
+ INFO( "Handling IPC message [ERequestContextSet]" );
+
+ TInt err = KErrNone;
+
+ // Check if the client has already requested contexts but
+ // has failed due too small buffer size
+ if( iContextRequestBuffer.Count() )
+ {
+ // Write request result into client side buffer
+ CompleteRequestContextL( aMessage );
+
+ // Reset buffer
+ iContextRequestBuffer.Reset();
+ }
+ else
+ {
+ // New request
+ // Stream query
+ RContextQueryArray queryArray;
+ CleanupResetAndDestroyPushL( queryArray );
+ TInt bufferSize = aMessage.GetDesLengthL( 1 );
+ HBufC8* buffer = HBufC8::NewLC( bufferSize );
+ TPtr8 bufferPtr = buffer->Des();
+ aMessage.ReadL( 1, bufferPtr );
+ RDesReadStream readStream( bufferPtr );
+ readStream.PushL();
+ TInt count = readStream.ReadInt16L();
+ for( TInt i = 0; i < count; i++ )
+ {
+ CCFContextQueryImpl* query =
+ CCFContextQueryImpl::NewLC( KNullDesC, KNullDesC );
+ query->InternalizeL( readStream );
+ queryArray.AppendL( query );
+ CleanupStack::Pop( query );
+ }
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Send request to CF Engine
+ RThread clientThread;
+ aMessage.ClientL( clientThread );
+ CleanupClosePushL( clientThread );
+ count = queryArray.Count();
+ for( TInt i = 0; i < count; i++ )
+ {
+ RequestContext( *queryArray[i], clientThread );
+ }
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &clientThread );
+ CleanupStack::PopAndDestroy( &queryArray );
+
+ // Handle request context results
+ if( err == KErrNone && iContextRequestBuffer.Count() )
+ {
+ // Write request result into client side buffer if
+ // request succesfull
+ CompleteRequestContextL( aMessage );
+ }
+ else
+ {
+ // Complete with error code
+ aMessage.Complete( err );
+ }
+ }
+
+ INFO( "Handled IPC message [ERequestContextSet]" );
+
+ break;
+ }
+
+ // Slot[0] = TDesC&
+ // Slot[1] = TDesC&
+ // Slot[2] = TSecurityPolicyBuf - read policy
+ // Slot[3] = TSecurityPolicyBuf - write policy
+ case EDefineContext:
+ {
+ INFO( "Handling IPC message [EDefineContext]" );
+
+ TInt err = KErrNone;
+
+ // Read context source
+ HBufC* contextSource = HBufC::NewLC( aMessage.GetDesLengthL( 0 ) );
+ TPtr contextSourcePtr = contextSource->Des();
+ aMessage.ReadL( 0, contextSourcePtr );
+
+ // Read context type
+ HBufC* contextType = HBufC::NewLC( aMessage.GetDesLengthL( 1 ) );
+ TPtr contextTypePtr = contextType->Des();
+ aMessage.ReadL( 1, contextTypePtr );
+
+ // Read security policy
+ TSecurityPolicyBuf readSecPolicyBuf;
+ aMessage.ReadL( 2, readSecPolicyBuf );
+ TSecurityPolicy readSecPolicy;
+ User::LeaveIfError( readSecPolicy.Set( readSecPolicyBuf ) ); // verifies the security policy
+
+ TSecurityPolicyBuf writeSecPolicyBuf;
+ aMessage.ReadL( 3, writeSecPolicyBuf );
+ TSecurityPolicy writeSecPolicy;
+ User::LeaveIfError( writeSecPolicy.Set( writeSecPolicyBuf ) ); // verifies the security policy
+
+
+ RThread clientThread;
+ aMessage.ClientL( clientThread );
+ CleanupClosePushL( clientThread );
+
+ // Define context in CF
+ err = iCFContext.DefineContext( contextSourcePtr,
+ contextTypePtr,
+ readSecPolicy,
+ writeSecPolicy,
+ this,
+ clientThread.SecureId() );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &clientThread );
+
+ // Cleanup
+ CleanupStack::PopAndDestroy( contextType );
+ CleanupStack::PopAndDestroy( contextSource );
+
+ aMessage.Complete( err );
+
+ INFO( "Handled IPC message [EDefineContext]" );
+
+ break;
+ }
+
+ // Slot[0] = TDes - Buffer
+ case EGetContextSubscriptionError:
+ {
+ INFO( "Handling IPC message [EGetContextSubscriptionError]" );
+
+ // Check that we actually have errors in the list
+ TInt err = KErrNone;
+ if( iSubscriptionErrors.Count() )
+ {
+ // We have a context subscription error, send it to client
+ CCFContextObjectImpl* context = iSubscriptionErrors[0].iContext;
+ iSubscriptionErrors.Remove( 0 );
+ CleanupStack::PushL( context );
+ HBufC8* buffer = HBufC8::NewLC( aMessage.GetDesMaxLengthL( 0 ) );
+ TPtr8 bufferPtr = buffer->Des();
+ RDesWriteStream writeStream( bufferPtr );
+ writeStream.PushL();
+ context->ExternalizeL( writeStream );
+
+ // Write content into client side buffer
+ aMessage.WriteL( 0, bufferPtr );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &writeStream );
+ CleanupStack::PopAndDestroy( buffer );
+ CleanupStack::PopAndDestroy( context );
+ }
+ else
+ {
+ // No errors found
+ err = KErrNotFound;
+ }
+
+ // Complete
+ aMessage.Complete( err );
+
+ INFO( "Handled IPC message [EGetContextSubscriptionError]" );
+
+ break;
+ }
+
+ // Slot[0]= TDesC - Context
+ // Slot[1]= TDesC - Context data
+ // Slot[2]= TPckg<TUid> - Context data UID
+ case EPublishContextWithData:
+ {
+ INFO( "Handling IPC message [EPublishContextWithData]" );
+
+ // Get context
+ CCFContextObjectImpl* context = CCFContextObjectImpl::NewLC();
+ TInt len = aMessage.GetDesLengthL( 0 );
+ HBufC8* contextBuf = HBufC8::NewLC( len );
+ TPtr8 contextBufPtr( contextBuf->Des() );
+ aMessage.ReadL( 0, contextBufPtr );
+ RDesReadStream readStream( contextBufPtr );
+ readStream.PushL();
+ context->InternalizeL( readStream );
+ CleanupStack::PopAndDestroy( &readStream );
+ CleanupStack::PopAndDestroy( contextBuf );
+
+ // Get context data
+ CCFContextDataProxy* contextData = CCFContextDataProxy::NewLC();
+ len = aMessage.GetDesLengthL( 1 );
+ HBufC8* contextDataBuf = HBufC8::NewLC( len );
+ TPtr8 contextDataBufPtr( contextDataBuf->Des() );
+ aMessage.ReadL( 1, contextDataBufPtr );
+ TPckgBuf<TUid> uidPckgBuf;
+ aMessage.ReadL( 2, uidPckgBuf );
+
+ contextData->SetContextData( contextDataBuf );
+ contextData->SetContextDataUid( uidPckgBuf() );
+ CleanupStack::Pop( contextDataBuf );
+
+ // Publish context
+ RThread clientThread;
+ aMessage.ClientL( clientThread );
+ CleanupClosePushL( clientThread );
+ TInt err = iCFContext.PublishContext( *context,
+ *contextData,
+ clientThread );
+ CleanupStack::PopAndDestroy( &clientThread );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( contextData );
+ CleanupStack::PopAndDestroy( context );
+
+ // Complete
+ aMessage.Complete( err );
+
+ INFO( "Handled IPC message [EPublishContextWithData]" );
+
+ break;
+ }
+
+ // Slot[0] = RFs handle
+ // Slot[1] = RFile handle
+ // Slot[2] = TPckgC< TUid > - Context Source UID
+ case EInstallSourceSetting:
+ {
+ RFile settingFile;
+ TInt err = settingFile.AdoptFromClient( aMessage, 0, 1 );
+ CleanupClosePushL( settingFile ); // CLEANUP<< settingFile
+ if ( err == KErrNone )
+ {
+ TPckgBuf< TUid > uidPckgBuf;
+ aMessage.ReadL( 2, uidPckgBuf );
+
+ RThread client;
+ aMessage.ClientL( client );
+
+ // Install setting
+ err = iCFContext.InstallContextSourceSetting( settingFile,
+ uidPckgBuf(),
+ client );
+
+ client.Close();
+ }
+ CleanupStack::PopAndDestroy( &settingFile );// CLEANUP>> settingFile
+ aMessage.Complete( err );
+
+ break;
+ }
+
+ // Slot[0] = TDesC& - Setting filename
+ // Slot[1] = TPckgC< TUid > - Context Source UID
+ case EUninstallSourceSetting:
+ {
+ // Read setting filename // CLEANUP<< filename
+ HBufC* filename = HBufC::NewLC( aMessage.GetDesLengthL( 0 ) );
+ TPtr filenamePtr = filename->Des();
+ aMessage.ReadL( 0, filenamePtr );
+
+ TPckgBuf< TUid > uidPckgBuf;
+ aMessage.ReadL( 1, uidPckgBuf );
+
+ RThread client;
+ aMessage.ClientL( client );
+
+ // Uninstall setting
+ TInt err = iCFContext.UninstallContextSourceSetting( *filename,
+ uidPckgBuf(),
+ client );
+
+ client.Close();
+ CleanupStack::PopAndDestroy( filename ); // CLEANUP>> filename
+ aMessage.Complete( err );
+
+ break;
+ }
+
+ // Slot[0] = TPckgC< TUid > - Context Source UID
+ case EUninstallSourceSettings:
+ {
+ // Read context source UID
+ TPckgBuf< TUid > uidPckgBuf;
+ aMessage.ReadL( 0, uidPckgBuf );
+
+ RThread client;
+ aMessage.ClientL( client );
+
+ // Uninstall setting
+ TInt err = iCFContext.UninstallContextSourceSettings( uidPckgBuf(),
+ client );
+
+ client.Close();
+ aMessage.Complete( err );
+
+ break;
+ }
+
+ default:
+ {
+ // Message not handled
+ handled = EFalse;
+ }
+ }
+
+ INFO_1( "Handled IPC message: %d", handled );
+
+ return handled;
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::ContextIndicationL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::ContextIndicationL(
+ CCFContextIndication* aIndication )
+ {
+ FUNC_LOG;
+
+ INFO_2( "Received context indication: %S: %S",
+ &aIndication->Context().Source(),
+ &aIndication->Context().Type() );
+
+ CCFContextIndicationImpl* indication =
+ static_cast<CCFContextIndicationImpl*>( aIndication );
+ iIndicationQueue.AppendL( indication );
+ CheckContextIndicationQueueL();
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::Client
+//-----------------------------------------------------------------------------
+//
+TInt CCFMessageHandlerContext::Client( RThread& aThread ) const
+ {
+ FUNC_LOG;
+
+ TInt err = KErrNone;
+ if( !iReceiveMessage.IsNull() )
+ {
+ // We have a message pending
+ err = iReceiveMessage.Client( aThread );
+ }
+ else
+ {
+ err = KErrNotFound;
+ }
+
+ return err;
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::HandleContextSubscriptionError
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::HandleContextSubscriptionError( TInt aError,
+ const TDesC& aSource,
+ const TDesC& aType )
+ {
+ FUNC_LOG;
+
+ // Client will not get notified about error if this fails
+ // Failure only due to OOM
+ TRAP_IGNORE( DoHandleContextSubscriptionErrorL( aError, aSource, aType ) );
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::Subscribers
+//-----------------------------------------------------------------------------
+//
+// from MCFContextSource
+void CCFMessageHandlerContext::Subscribers( const TDesC& aContextSource,
+ const TDesC& aContextType )
+ {
+ FUNC_LOG;
+
+ INFO_2( "Received subscribers indication: %S: %S",
+ &aContextSource,
+ &aContextType );
+
+ TRAPD( err, SubscribersL( aContextSource, aContextType ) );
+ if( err != KErrNone )
+ {
+ ERROR_2( err, "Failed to notify subscribers to client: [%S, %S]",
+ &aContextSource, &aContextType );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::PublishContext
+//-----------------------------------------------------------------------------
+//
+// from MCFContextSource
+void CCFMessageHandlerContext::NoSubscribers( const TDesC& aContextSource,
+ const TDesC& aContextType )
+ {
+ FUNC_LOG;
+
+ INFO_2( "Received no subscribers indication: %S: %S",
+ &aContextSource,
+ &aContextType );
+
+ TRAPD( err, NoSubscribersL( aContextSource, aContextType ) );
+ if( err != KErrNone )
+ {
+ ERROR_2( err, "Failed to notify no subscribers to client: [%S, %S]",
+ &aContextSource, &aContextType );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::HandleCommand
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::HandleCommand(
+ const CCFContextSourceCommand& aCommand )
+ {
+ FUNC_LOG;
+
+ TPtrC commandName( aCommand.Name() );
+ INFO_1( "Received handle command action: %S", &commandName );
+
+ TRAPD( err, HandleCommandL( aCommand ) );
+ if( err != KErrNone )
+ {
+ ERROR_2( err, "Failed to notify handle command action [%S] to client: [%x]",
+ &commandName,
+ aCommand.SourceUid() );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::PublishContext
+//-----------------------------------------------------------------------------
+//
+TInt CCFMessageHandlerContext::PublishContext( CCFContextObject& aContext,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ return iCFContext.PublishContext( aContext, aClientThread );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::AddSubscription
+//-----------------------------------------------------------------------------
+//
+TInt CCFMessageHandlerContext::AddSubscription( CCFContextSubscription* aSubscription,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ return iCFContext.SubscribeContext( aSubscription, this, aClientThread );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::RemoveSubscriptionL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::RemoveSubscription(
+ CCFContextSubscription& aSubscription )
+ {
+ FUNC_LOG;
+
+ iCFContext.UnsubscribeContext( aSubscription, *this );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CancelReceiveContextIndicationMessage
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CancelReceiveContextIndicationMessage()
+ {
+ FUNC_LOG;
+
+ if( !iReceiveMessage.IsNull() )
+ {
+ iReceiveMessage.Complete( KErrCancel );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CancelReceiveMessage
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CancelReceiveMessage()
+ {
+ FUNC_LOG;
+
+ if( !iReceiveContextSourceMsg.IsNull() )
+ {
+ iReceiveContextSourceMsg.Complete( KErrCancel );
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::RequestContext
+//-----------------------------------------------------------------------------
+//
+TInt CCFMessageHandlerContext::RequestContext( CCFContextQuery& aContextQuery,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ // request the context
+ return iCFContext.RequestContext( iContextRequestBuffer,
+ aContextQuery,
+ aClientThread );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::ReceiveContextIndicationMessageL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::ReceiveContextIndicationMessageL(
+ const RMessage2& aMessage)
+ {
+ FUNC_LOG;
+
+ __ASSERT_DEBUG( iReceiveMessage.IsNull(),
+ CCFServSession::PanicClient( aMessage, EReceiveReceiveAlreadyActive ) );
+
+ // Store message
+ iReceiveMessage = aMessage;
+
+ // First check if we have subscription errors in the queue
+ if( iSubscriptionErrors.Count() )
+ {
+ IndicateSubscriptionErrorL();
+ }
+
+ // Check indications
+ else if( iIndicationQueue.Count() )
+ {
+ CheckContextIndicationQueueL();
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::ReceiveMessageL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::ReceiveMessageL( const RMessage2& aMessage )
+ {
+ FUNC_LOG;
+
+ __ASSERT_DEBUG( iReceiveContextSourceMsg.IsNull(),
+ CCFServSession::PanicClient( aMessage, EReceiveReceiveAlreadyActive ) );
+
+ // Store message
+ iReceiveContextSourceMsg = aMessage;
+
+ // Check if we have messages in the queue
+ if( iMessageQueue.Count() )
+ {
+ CheckMessageQueueL();
+ }
+ }
+
+
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::IndicateSubscriptionErrorL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::IndicateSubscriptionErrorL()
+ {
+ FUNC_LOG;
+
+ // Get next error, client will request the context related to the error
+ TSubscriptionError error = iSubscriptionErrors[0];
+ TPckgBuf<TInt> sizeBuf( error.iContext->Size() );
+ iReceiveMessage.WriteL( 1, sizeBuf );
+ iReceiveMessage.Complete( error.iError );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CompleteNextIndicationFromQueueL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CompleteNextIndicationFromQueueL(
+ const RMessage2& aMessage )
+ {
+ FUNC_LOG;
+
+ // Leave if the aMessage is null
+ if( aMessage.IsNull() )
+ {
+ User::Leave( KErrArgument );
+ }
+
+ // Check that we have indications in queue
+ else if( iIndicationQueue.Count() )
+ {
+ CCFContextIndicationImpl* indication = iIndicationQueue[0];
+ HBufC8* buffer = HBufC8::NewLC( indication->Size() );
+ TPtr8 bufferPtr = buffer->Des();
+ RDesWriteStream writeStream( bufferPtr );
+ writeStream.PushL();
+ indication->ExternalizeL( writeStream );
+ CleanupStack::PopAndDestroy( &writeStream );
+
+ // Write buffer into client side and complete
+ aMessage.WriteL( 0, bufferPtr );
+ aMessage.Complete( KErrNone );
+
+ // Remove indication from queue
+ delete indication;
+ iIndicationQueue.Remove( 0 );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( buffer );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CheckContextIndicationQueueL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CheckContextIndicationQueueL()
+ {
+ FUNC_LOG;
+
+ // We must have something in the queue and receive message pending
+ if( iIndicationQueue.Count() && !iReceiveMessage.IsNull() )
+ {
+ // First check that client side buffer is big enough
+ CCFContextIndicationImpl* indication = iIndicationQueue[0];
+ TInt clientBufferSize = iReceiveMessage.GetDesMaxLengthL( 0 );
+ TInt indicationSize = indication->Size();
+ if( indicationSize <= clientBufferSize )
+ {
+ // Client has sufficient buffer
+ CompleteNextIndicationFromQueueL( iReceiveMessage );
+ }
+ else
+ {
+ // Client has insufficient buffer size
+ // Write new buffer size in client memory and complete
+ TPckgBuf<TInt> sizeBuf( indicationSize );
+ iReceiveMessage.WriteL( 1, sizeBuf );
+ iReceiveMessage.Complete( KErrTooBig );
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CompleteNextMessageFromQueueL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CompleteNextMessageFromQueueL(
+ const RMessage2& aMessage )
+ {
+ FUNC_LOG;
+
+ __ASSERT_DEBUG( iMessageQueue.Count(), Panic( aMessage, KErrNotFound ) );
+ __ASSERT_DEBUG( !aMessage.IsNull(), Panic( aMessage, KErrArgument ) );
+
+ if( iMessageQueue.Count() )
+ {
+ // Write buffer into client side and complete
+ HBufC8* messageBuffer = iMessageQueue[0];
+ aMessage.WriteL( 0, *messageBuffer );
+ aMessage.Complete( KErrNone );
+
+ // Remove indication from queue
+ delete messageBuffer;
+ iMessageQueue.Remove( 0 );
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CheckMessageQueueL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CheckMessageQueueL()
+ {
+ FUNC_LOG;
+
+ // We must have something in the queue and receive message pending
+ if( iMessageQueue.Count() && !iReceiveContextSourceMsg.IsNull() )
+ {
+ // First check that client side buffer is big enough
+ TInt clientBufferSize = iReceiveContextSourceMsg.GetDesMaxLengthL( 0 );
+ TInt indicationSize = iMessageQueue[0]->Size();
+ if( indicationSize <= clientBufferSize )
+ {
+ // Client has sufficient buffer
+ // Write buffer into client side and complete
+ HBufC8* messageBuffer = iMessageQueue[0];
+ iReceiveContextSourceMsg.WriteL( 0, *messageBuffer );
+ iReceiveContextSourceMsg.Complete( KErrNone );
+
+ // Remove indication from queue
+ delete messageBuffer;
+ iMessageQueue.Remove( 0 );
+
+ }
+ else
+ {
+ // Client has insufficient buffer size
+ // Write new buffer size in client memory and complete
+ TPckgBuf<TInt> sizeBuf( indicationSize );
+ iReceiveContextSourceMsg.WriteL( 1, sizeBuf );
+ iReceiveContextSourceMsg.Complete( KErrTooBig );
+ }
+ }
+ }
+
+
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::CompleteRequestContextL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::CompleteRequestContextL(
+ const RMessage2& aMessage )
+ {
+ FUNC_LOG;
+
+ // Check if client has a sufficient buffer
+ TInt resultArraySize = 0;
+ resultArraySize += sizeof( TInt );
+ TInt count = iContextRequestBuffer.Count();
+ CCFContextObjectImpl* context = NULL;
+ for( TInt i = 0; i < count; i++ )
+ {
+ context = static_cast<CCFContextObjectImpl*>(
+ iContextRequestBuffer[i] );
+ resultArraySize += context->Size();
+ }
+ TInt clientBufferSize = aMessage.GetDesMaxLengthL( 0 );
+ if( resultArraySize <= clientBufferSize )
+ {
+ // Client has a sufficient buffer
+ HBufC8* buffer = HBufC8::NewLC( resultArraySize );
+ TPtr8 bufferPtr = buffer->Des();
+ RDesWriteStream writeStream( bufferPtr );
+ writeStream.PushL();
+ writeStream.WriteInt16L( count );
+ for( TInt i = 0; i < count; i++ )
+ {
+ context = static_cast<CCFContextObjectImpl*>(
+ iContextRequestBuffer[i] );
+ context->ExternalizeL( writeStream );
+ }
+ writeStream.CommitL();
+ aMessage.WriteL( 0, bufferPtr );
+
+ // Clean up
+ CleanupStack::PopAndDestroy( &writeStream );
+ CleanupStack::PopAndDestroy( buffer );
+
+ // Reset context request buffer
+ iContextRequestBuffer.Reset();
+
+ // Complete message
+ aMessage.Complete( KErrNone );
+ }
+ else
+ {
+ // Client has an insufficient buffer
+ TPckgBuf<TInt> resultArraySizeBuf( resultArraySize );
+ aMessage.WriteL( 2, resultArraySizeBuf );
+
+ // Complete message
+ aMessage.Complete( KErrTooBig );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFMessageHandlerContext::DoHandleContextSubscriptionErrorL
+//-----------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::DoHandleContextSubscriptionErrorL( TInt aError,
+ const TDesC& aSource,
+ const TDesC& aType )
+ {
+ FUNC_LOG;
+
+ // Context related to error
+ CCFContextObjectImpl* context = CCFContextObjectImpl::NewLC();
+ context->SetSourceL( aSource );
+ context->SetTypeL( aType );
+
+ // Append error to queue
+ TSubscriptionError error;
+ error.iError = aError;
+ error.iContext = context;
+
+ // Ignore append errors
+ iSubscriptionErrors.AppendL( error );
+ CleanupStack::Pop( context );
+ if( !iReceiveMessage.IsNull() )
+ {
+ // Can only fail due OOM
+ IndicateSubscriptionErrorL();
+ }
+ }
+
+//------------------------------------------------------------------------------
+// CCFMessageHandlerContext::SubscribersL
+//------------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::SubscribersL( const TDesC& aContextSource,
+ const TDesC& aContextType )
+ {
+ FUNC_LOG;
+
+ // calculate message length
+ TInt size = 0;
+ size += sizeof( TInt ); // message type
+ size += sizeof( TInt ) + aContextSource.Size();
+ size += sizeof( TInt ) + aContextType.Size();
+
+ // create a required buffer and stream
+ HBufC8* buffer = HBufC8::NewLC( size ); // CLEANUP << buffer
+ TPtr8 bufferPtr = buffer->Des();
+ RDesWriteStream writeStream( bufferPtr );
+ writeStream.PushL(); // CLEANUP << writeStream
+
+ // write message to the buffer
+ writeStream.WriteInt32L( ESubscribers );
+ writeStream.WriteInt32L( aContextSource.Length() );
+ writeStream.WriteL( aContextSource, aContextSource.Length() );
+ writeStream.WriteInt32L( aContextType.Length() );
+ writeStream.WriteL( aContextType, aContextType.Length() );
+ writeStream.CommitL();
+
+ CleanupStack::PopAndDestroy( &writeStream ); // CLEANUP >> writeStream
+
+ // append pointer to the message array
+ iMessageQueue.AppendL( buffer );
+ CleanupStack::Pop( buffer ); // CLEANUP >> buffer
+
+ CheckMessageQueueL();
+ }
+
+//------------------------------------------------------------------------------
+// CCFMessageHandlerContext::NoSubscribersL
+//------------------------------------------------------------------------------
+//
+void CCFMessageHandlerContext::NoSubscribersL( const TDesC& aContextSource,
+ const TDesC& aContextType )
+ {
+ FUNC_LOG;
+
+ // calculate message length
+ TInt size = 0;
+ size += sizeof( TInt ); // message type
+ size += sizeof( TInt ) + aContextSource.Size();
+ size += sizeof( TInt ) + aContextType.Size();
+
+ // create a required buffer and stream
+ HBufC8* buffer = HBufC8::NewLC( size ); // CLEANUP << buffer
+ TPtr8 bufferPtr = buffer->Des();
+ RDesWriteStream writeStream( bufferPtr );
+ writeStream.PushL(); // CLEANUP << writeStream
+
+ // write message to the buffer
+ writeStream.WriteInt32L( ENoSubscribers );
+ writeStream.WriteInt32L( aContextSource.Length() );
+ writeStream.WriteL( aContextSource, aContextSource.Length() );
+ writeStream.WriteInt32L( aContextType.Length() );
+ writeStream.WriteL( aContextType, aContextType.Length() );
+ writeStream.CommitL();
+
+ CleanupStack::PopAndDestroy( &writeStream ); // CLEANUP >> writeStream
+
+ // append pointer to the message array
+ iMessageQueue.AppendL( buffer );
+ CleanupStack::Pop( buffer ); // CLEANUP >> buffer
+
+ CheckMessageQueueL();
+ }
+
+void CCFMessageHandlerContext::HandleCommandL(
+ const CCFContextSourceCommand& aCommand )
+ {
+ FUNC_LOG;
+
+ TInt size = sizeof( TInt ); // message type
+ size += aCommand.Size(); // the command
+
+ // Stream command into descriptor
+ HBufC8* buffer = HBufC8::NewLC( size ); // CLEANUP<< buffer
+ TPtr8 bufferPtr = buffer->Des();
+ RDesWriteStream stream( bufferPtr );
+ stream.PushL(); // CLEANUP<< stream
+
+ // Write message to the buffer
+ stream.WriteInt32L( EHandleCommand );
+ aCommand.ExternalizeL( stream );
+ stream.CommitL();
+
+ CleanupStack::PopAndDestroy( &stream ); // CLEANUP>> stream
+
+ // Append buffer to the message array
+ iMessageQueue.AppendL( buffer );
+ CleanupStack::Pop( buffer ); // CLEANUP>> buffer
+
+ CheckMessageQueueL();
+ }
+
+// End of File