contextframework/cfw/src/cfserver/CFMessageHandlerContext.cpp
changeset 0 2e3d3ce01487
--- /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