--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/contextframework/cfw/src/cfserver/CFContextManager.cpp Tue Feb 02 10:12:00 2010 +0200
@@ -0,0 +1,930 @@
+/*
+* Copyright (c) 2002-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: CCFContextManager class implementation.
+*
+*/
+
+
+#include <cfcontextdataobject.h>
+
+#include "CFContextManager.h"
+#include "CFContextQueryImpl.h"
+#include "CFContextObjectImpl.h"
+#include "cfcontextsubscriptionlistener.h"
+#include "CFContextSubscriptionImpl.h"
+#include "CFCacheElement.h"
+#include "cfutils.h"
+#include "cftrace.h"
+#include "CFContextDataProxy.h"
+#include "cfcommon.h"
+
+// Public Constructors and destructors
+CCFContextManager* CCFContextManager::NewL(
+ MCFSecurityChecker& aSecurityChecker )
+ {
+ FUNC_LOG;
+
+ CCFContextManager* self = CCFContextManager::NewLC( aSecurityChecker );
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+CCFContextManager* CCFContextManager::NewLC(
+ MCFSecurityChecker& aSecurityChecker )
+ {
+ FUNC_LOG;
+
+ CCFContextManager* self
+ = new (ELeave) CCFContextManager( aSecurityChecker );
+ CleanupStack::PushL(self);
+ self->ConstructL();
+
+ return self;
+ }
+
+CCFContextManager::~CCFContextManager()
+ {
+ FUNC_LOG;
+
+ iCleanupCacheElements.Close();
+ iContextCache.ResetAndDestroy();
+ iContextCache.Close();
+ delete iPreviousContext;
+ delete iCacheOrder;
+ delete iCacheSearchKey;
+
+ iSubscriptions.ResetAndDestroy();
+ }
+
+CCFContextManager::CCFContextManager( MCFSecurityChecker& aSecurityChecker )
+ {
+ FUNC_LOG;
+
+ iSecurityChecker = &aSecurityChecker;
+ }
+
+void CCFContextManager::ConstructL()
+ {
+ FUNC_LOG;
+
+ iCacheOrder = new (ELeave) TLinearOrder<CCFCacheElement>
+ (CCFCacheElement::CompareByTypeAndSource);
+
+ iCacheSearchKey = CCFCacheElement::NewL();
+
+ iPreviousContext = CCFContextObject::NewL();
+ }
+
+// METHODS
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::PublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::PublishContextL( CCFContextObject &aContext,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ ValidatePublishContextL( aContext, aClientThread );
+ DoPublishContextL( aContext );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::PublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::PublishContextL( CCFContextObject &aContext,
+ RThread& aClientThread,
+ CCFContextDataObject& aData )
+ {
+ FUNC_LOG;
+
+ ValidatePublishContextL( aContext, aClientThread );
+ DoPublishContextL( aContext, &aData );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RequestContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::RequestContextL( RContextObjectArray& aResultBuffer,
+ CCFContextQuery& aContextQuery,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ // Accessing the context cache for the latest context values is enough
+ DoRequestContextL( aResultBuffer, aContextQuery, &aClientThread );
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RequestContextL
+//-----------------------------------------------------------------------------
+//
+CCFContextObject* CCFContextManager::RequestContextL( const TDesC& aContextType,
+ const TDesC& aContextSource,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ // check the cache
+ iCacheSearchKey->Context().SetTypeL( aContextType );
+ iCacheSearchKey->Context().SetSourceL( aContextSource );
+ TInt index = KErrNone;
+ if( iContextCache.FindInOrder( iCacheSearchKey, index,
+ *iCacheOrder ) == KErrNone )
+ {
+ // index points to the matching object
+ if( index >= 0 && index < iContextCache.Count() )
+ {
+ User::LeaveIfError( DoReadSecurityCheck(
+ *iContextCache[index],
+ aClientThread ) );
+ return &iContextCache[index]->Context();
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+ else // == KErrNotFound
+ { // index points to "the place to be"
+ return NULL;
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::SubscriptionAddedL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::SubscriptionAddedL(
+ CCFContextSubscriptionImpl& aSubscription,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ TInt count = iContextCache.Count();
+ CCFCacheElement* element = NULL;
+ for( TInt i = 0; i < count; i++ )
+ {
+ element = iContextCache[i];
+ if( aSubscription.Matches( element->Context().Type(),
+ element->Context().Source() ) )
+ {
+ TInt err = DoReadSecurityCheck( *element, aClientThread );
+ if (err == KErrNone)
+ {
+ element->AddSubscriptionL( aSubscription );
+ }
+ else
+ {
+ aSubscription.SubscriptionListener().HandleContextSubscriptionError( err,
+ element->Context().Source(),
+ element->Context().Type() );
+ }
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::SubscriptionRemoved
+//-----------------------------------------------------------------------------
+//
+TBool CCFContextManager::SubscriptionRemoved(
+ CCFContextSubscriptionImpl& aSubscription)
+ {
+ FUNC_LOG;
+
+ TBool cleanupElement( EFalse );
+ for( TInt i = 0; i < iContextCache.Count(); i++ )
+ {
+ TInt j = iContextCache[ i ]->Subscriptions().Count() - 1;
+ for( ; j >= 0; j-- )
+ {
+ if( &aSubscription == iContextCache[ i ]->Subscriptions()[ j ] )
+ {
+ CCFCacheElement* cacheElement = iContextCache[ i ];
+ if ( iPublishingForCacheElement
+ && ( iPublishingForCacheElement == cacheElement ) )
+ {
+ cleanupElement = ETrue;
+ cacheElement->NullifySubscription( j );
+ TInt err = iCleanupCacheElements.InsertInAddressOrder(
+ cacheElement );
+ if ( err == KErrAlreadyExists )
+ {
+ err = KErrNone;
+ }
+ ERROR( err, "CCFContextManager::SubscriptionRemoved - Adding cache element to cleanup array failed!" );
+ }
+ else
+ {
+ cacheElement->RemoveSubscription( j );
+ }
+ }
+ }
+ }
+
+ return cleanupElement;
+ }
+
+
+//----------------------------------------------------------------------------
+// CCFContextManager::DefineContextL
+//----------------------------------------------------------------------------
+//
+void CCFContextManager::DefineContextL( const TDesC& aContextSource,
+ const TDesC& aContextType,
+ const TSecurityPolicy& aReadSecurityPolicy,
+ const TSecurityPolicy& aWriteSecurityPolicy )
+ {
+ FUNC_LOG;
+
+ RThread thread;
+ CleanupClosePushL( thread );
+
+ DefineContextL( aContextSource, aContextType, aReadSecurityPolicy,
+ aWriteSecurityPolicy, NULL, thread.SecureId() );
+
+ CleanupStack::PopAndDestroy( );
+ }
+
+
+//----------------------------------------------------------------------------
+// CCFContextManager::DefineContextL
+//----------------------------------------------------------------------------
+//
+void CCFContextManager::DefineContextL( const TDesC& aContextSource,
+ const TDesC& aContextType,
+ const TSecurityPolicy& aReadSecurityPolicy,
+ const TSecurityPolicy& aWriteSecurityPolicy,
+ MCFContextSource* aContextPublisher,
+ const TUid& aPublisherUid )
+ {
+ FUNC_LOG;
+
+ // Prepare and find context
+ iCacheSearchKey->Context().SetSourceL( aContextSource );
+ iCacheSearchKey->Context().SetTypeL( aContextType );
+ iCacheSearchKey->Context().SetValueL( KNullDesC );
+ iCacheSearchKey->SetReadSecurityPolicy( aReadSecurityPolicy );
+ iCacheSearchKey->SetWriteSecurityPolicy( aWriteSecurityPolicy );
+ iCacheSearchKey->SetContextPublisher( aContextPublisher, aPublisherUid );
+
+ TInt index = KErrNone;
+ TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
+ index,
+ *iCacheOrder );
+
+ if ( searchError != KErrNone )
+ {
+ // New context type
+ User::LeaveIfError(
+ iContextCache.Insert( iCacheSearchKey, index ) );
+ CacheElementAddedL( *iCacheSearchKey );
+ iCacheSearchKey = NULL;
+ iCacheSearchKey = CCFCacheElement::NewL();
+
+ // Signalling new context type
+ iPreviousContext->SetSourceL( KNullDesC );
+ iPreviousContext->SetTypeL( KNullDesC );
+
+ INFO_2( "New context defined: [%S: %S]",
+ &aContextSource,
+ &aContextType );
+ }
+ else
+ {
+ TInt err = KErrNone;
+ CCFCacheElement* cacheElement = iContextCache[index];
+ if( cacheElement->PublisherUid() == aPublisherUid )
+ {
+ if( RedefineAllowed( *cacheElement, aContextPublisher, aPublisherUid ) )
+ {
+ cacheElement->SetContextPublisher( aContextPublisher,
+ aPublisherUid );
+ INFO_3( "Context [%S: %S] redefined by client [%x]",
+ &aContextSource, &aContextType, aPublisherUid.iUid );
+ }
+ else
+ {
+ err = KErrAlreadyExists;
+ }
+ }
+ else
+ {
+ err = KErrAlreadyExists;
+ }
+
+ ERROR_2( err, "Context already defined: [%S: %S]",
+ &aContextSource,
+ &aContextType );
+ User::LeaveIfError( err );
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::GetReadSecurityPolicyL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::GetReadSecurityPolicyL( const TDesC& aContextSource,
+ const TDesC& aContextType,
+ TSecurityPolicy& aPolicy )
+ {
+ FUNC_LOG;
+
+ TInt count = iContextCache.Count();
+ CCFCacheElement* cacheElement = NULL;
+ for( TInt i = 0; i < count; i++ )
+ {
+ cacheElement = iContextCache[ i ];
+
+ if( cacheElement->Context().Source().Compare( aContextSource ) == 0
+ && cacheElement->Context().Type().Compare( aContextType ) == 0 )
+ {
+ aPolicy = cacheElement->GetReadSecurityPolicy();
+ return;
+ }
+ }
+
+ ERROR_2( KErrNotFound, "Security Policy for [%S: %S] not found!",
+ &aContextSource, &aContextType );
+ User::Leave( KErrNotFound );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::GetWriteSecurityPolicyL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::GetWriteSecurityPolicyL( const TDesC& aContextSource,
+ const TDesC& aContextType,
+ TSecurityPolicy& aPolicy )
+ {
+ FUNC_LOG;
+
+ TInt count = iContextCache.Count();
+ CCFCacheElement* cacheElement = NULL;
+ for( TInt i = 0; i < count; i++ )
+ {
+ cacheElement = iContextCache[ i ];
+
+ if( cacheElement->Context().Source().Compare( aContextSource ) == 0
+ && cacheElement->Context().Type().Compare( aContextType ) == 0 )
+ {
+ aPolicy = cacheElement->GetWriteSecurityPolicy();
+ return;
+ }
+ }
+
+ ERROR_2( KErrNotFound, "Security Policy for [%S: %S] not found!",
+ &aContextSource, &aContextType );
+ User::Leave( KErrNotFound );
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DeregisterPublisher
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::DeregisterPublisher( MCFContextSource& aPublisher )
+ {
+ FUNC_LOG;
+
+ for( TInt i = 0; i < iContextCache.Count() ; i++ )
+ {
+ CCFCacheElement* cacheElement = iContextCache[ i ];
+ if( cacheElement->ContextPublisher() == &aPublisher )
+ {
+ cacheElement->SetContextPublisher( NULL );
+ }
+ }
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::GetLatestFromCacheL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::GetLatestFromCacheL(
+ RContextObjectArray& aLatestContexts,
+ queryMatchFunction aMatchFunction,
+ const CCFContextQueryImpl& aContextQuery,
+ RThread* aClientThread )
+ {
+ FUNC_LOG;
+
+ TInt count = iContextCache.Count();
+ CCFCacheElement* cacheElement = NULL;
+ for( TInt i = 0; i < count; ++i )
+ {
+ cacheElement = iContextCache[ i ];
+ if( cacheElement->Context().Value().Length()
+ && ( aContextQuery.*aMatchFunction )(
+ cacheElement->Context().Type(),
+ cacheElement->Context().Source() ) )
+ {
+ if( !aClientThread ||
+ DoReadSecurityCheck( *cacheElement, *aClientThread ) == KErrNone )
+ {
+ aLatestContexts.AppendL( &cacheElement->Context() );
+ }
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::LogContextCache
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::LogContextCache()
+ {
+#ifdef DEBUG_LOG_CONTEXT_CACHE
+ INFO( "CONTEXT CACHE start:" );
+ TInt cacheIndex;
+ for (cacheIndex = 0; cacheIndex < iContextCache.Count(); ++cacheIndex)
+ {
+ iContextCache[cacheIndex]->DebugPrintContents();
+ }
+ INFO( "CONTEXT CACHE start:" );
+ INFO( "CONTEXT CACHE BY TYPE start:" );
+ for (cacheIndex = 0; cacheIndex < iContextCacheByType.Count() ;
+ ++cacheIndex)
+ {
+ iContextCacheByType[cacheIndex]->DebugPrintContents();
+ }
+ INFO( "CONTEXT CACHE BY TYPE end:" );
+#endif // DEBUG_LOG_CONTEXT_CACHE
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoSecurityCheck
+//-----------------------------------------------------------------------------
+//
+TInt CCFContextManager::DoReadSecurityCheck( CCFCacheElement& aContextCache,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ // Security check only needed if request is from other process than CF
+ TInt err = KErrNone;
+
+ TBool securityCheckOk =
+ iSecurityChecker->CheckClientSecurity( aClientThread,
+ aContextCache.GetReadSecurityPolicy() );
+
+ if( !securityCheckOk )
+ {
+ // Insuffcient security, indicate client
+ err = KErrAccessDenied;
+ }
+
+ return err;
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoSecurityCheck
+//-----------------------------------------------------------------------------
+//
+TInt CCFContextManager::DoWriteSecurityCheck( CCFCacheElement& aContextCache,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ // Security check only needed if request is from other process than CF
+ TInt err = KErrNone;
+
+ TBool securityCheckOk =
+ iSecurityChecker->CheckClientSecurity( aClientThread,
+ aContextCache.GetWriteSecurityPolicy() );
+
+ if( !securityCheckOk )
+ {
+ // Insuffcient security, indicate client
+ err = KErrAccessDenied;
+ }
+
+ return err;
+ }
+
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoRequestContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::DoRequestContextL( RContextObjectArray& aResultBuffer,
+ CCFContextQuery& aContextQuery,
+ RThread* aClientThread )
+ {
+ FUNC_LOG;
+
+ CCFContextQueryImpl& queryImpl = (CCFContextQueryImpl&) aContextQuery;
+ GetLatestFromCacheL( aResultBuffer,
+ &CCFContextQueryImpl::Matches,
+ queryImpl,
+ aClientThread );
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::SubscribeContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::SubscribeContextL(
+ CCFContextSubscription* aSubscription,
+ MCFContextSubscriptionListener* aListener,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ CCFContextSubscriptionImpl* subscriptionImpl =
+ static_cast<CCFContextSubscriptionImpl*>( aSubscription );
+ subscriptionImpl->SetSubscriptionListener( *aListener );
+
+ // Append new subscription into array
+ TInt err = iSubscriptions.Append( subscriptionImpl );
+ if( err != KErrNone )
+ {
+ User::Leave( err );
+ }
+
+ // Notify data manager that new subscription has been added
+ TRAP( err,
+ SubscriptionAddedL( *subscriptionImpl, aClientThread ) );
+ if( err )
+ {
+ iSubscriptions.Remove( iSubscriptions.Count() -1 );
+ User::Leave( err );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RemoveSubscription
+//-----------------------------------------------------------------------------
+//
+TBool CCFContextManager::RemoveSubscription(
+ CCFContextSubscription& aSubscription,
+ MCFContextSubscriptionListener& aListener )
+ {
+ FUNC_LOG;
+
+ TBool cleanupElement( EFalse );
+ CCFContextSubscriptionImpl* subscriptionImpl =
+ static_cast<CCFContextSubscriptionImpl*>( &aSubscription );
+
+ subscriptionImpl->SetSubscriptionListener( aListener );
+ TBool deleteSubscriptionImpl( EFalse );
+
+ TInt i = iSubscriptions.Count() - 1;
+ while ( i >= 0 )
+ {
+ if ( i >= iSubscriptions.Count() )
+ {
+ // Context source has removed subscriptions via synchronous call
+ // e.g. from managers call to source's NoSubscribers() function.
+ i = iSubscriptions.Count() - 1;
+ }
+
+ if ( i < 0 )
+ {
+ INFO( "All subscriptions removed" );
+ break;
+ }
+
+ if ( iSubscriptions[ i ]->IsSame( *subscriptionImpl ) )
+ {
+ CCFContextSubscriptionImpl* subscription = iSubscriptions[ i ];
+ iSubscriptions.Remove( i );
+ INFO_2( "CCFContextManager::RemoveSubscription - Subscription [%S: %S] removed",
+ &subscription->ContextSource(),
+ &subscription->ContextType() );
+ if ( SubscriptionRemoved( *subscription ) )
+ {
+ cleanupElement = ETrue;
+ }
+ if ( subscription != subscriptionImpl )
+ {
+ delete subscription;
+ }
+ else
+ {
+ // Delay deleting when the same subscription instance is used
+ // internally for both subscribe and unsubscribe.
+ deleteSubscriptionImpl = ETrue;
+ }
+ }
+ --i;
+ }
+
+ if ( deleteSubscriptionImpl )
+ {
+ delete subscriptionImpl;
+ }
+
+ return cleanupElement;
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::RemoveSubscription
+//-----------------------------------------------------------------------------
+//
+TBool CCFContextManager::RemoveSubscriptions(
+ MCFContextSubscriptionListener* aListener)
+ {
+ FUNC_LOG;
+
+ TBool cleanupElement( EFalse );
+
+ TInt i = iSubscriptions.Count() - 1;
+ while ( i >= 0 )
+ {
+ if ( i >= iSubscriptions.Count() )
+ {
+ // Context source has removed subscriptions via synchronous call
+ // e.g. from managers call to source's NoSubscribers() function.
+ i = iSubscriptions.Count() - 1;
+ }
+
+ if ( i < 0 )
+ {
+ INFO( "All subscriptions removed" );
+ break;
+ }
+
+ CCFContextSubscriptionImpl* subscription = iSubscriptions[ i ];
+ if ( &( subscription->SubscriptionListener() ) == aListener )
+ {
+ iSubscriptions.Remove( i );
+ if ( SubscriptionRemoved( *subscription ) )
+ {
+ cleanupElement = ETrue;
+ }
+ delete subscription;
+ subscription = NULL;
+ }
+ --i;
+ }
+
+ return cleanupElement;
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::CleanupCacheElementSubscriptions
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::CleanupCacheElementSubscriptions()
+ {
+ FUNC_LOG;
+
+ for ( TInt i = 0; i < iCleanupCacheElements.Count(); ++i )
+ {
+ CCFCacheElement* element = iCleanupCacheElements[ i ];
+ element->RemoveNullSubscriptions();
+ }
+ iCleanupCacheElements.Reset();
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::CacheElementAddedL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::CacheElementAddedL(
+ CCFCacheElement& aCacheElement )
+ {
+ FUNC_LOG;
+
+ TInt count = iSubscriptions.Count();
+ CCFContextSubscriptionImpl* subscription = NULL;
+ for( TInt i = 0; i < count; i++ )
+ {
+ subscription = iSubscriptions[i];
+ if( subscription->Matches( aCacheElement.Context().Type(),
+ aCacheElement.Context().Source() ) )
+ {
+ // Check security
+ RThread thread;
+ TInt err =
+ subscription->SubscriptionListener().Client( thread );
+ if( err == KErrNone )
+ {
+ err = DoReadSecurityCheck( aCacheElement, thread );
+ if( err == KErrNone )
+ {
+ aCacheElement.AddSubscriptionL( *subscription );
+ }
+ else
+ {
+ subscription->SubscriptionListener().HandleContextSubscriptionError(
+ err,
+ aCacheElement.Context().Source(),
+ aCacheElement.Context().Type() );
+ }
+ }
+ else
+ {
+ subscription->SubscriptionListener().HandleContextSubscriptionError(
+ err,
+ aCacheElement.Context().Source(),
+ aCacheElement.Context().Type() );
+ }
+ thread.Close();
+ }
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::ValidatePublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::ValidatePublishContextL( CCFContextObject& aContext,
+ RThread& aClientThread )
+ {
+ FUNC_LOG;
+
+ // Define context
+ iCacheSearchKey->Context().CopyL( aContext );
+ CCFCacheElement* currentCacheElement = iCacheSearchKey;
+ TInt index = KErrNone;
+ TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
+ index,
+ *iCacheOrder);
+
+ // Both source and type must match.
+ // Otherwise context has not been defined and will lead to error.
+ if( searchError == KErrNone )
+ {
+ if( index >= 0 && index < iContextCache.Count() )
+ {
+ // index and indexByType points to the matching cache elements
+ currentCacheElement = iContextCache[index];
+ }
+ else
+ {
+ // index not found -> leave
+ ERROR_GEN( "Context cache element not found from cache list" );
+ User::Leave( KErrNotFound );
+ }
+
+ // Perform security check
+ TInt err = DoWriteSecurityCheck( *currentCacheElement, aClientThread );
+ ERROR_2( err, "Security check failed: [%S: %S]",
+ &aContext.Source(),
+ &aContext.Type() );
+ User::LeaveIfError( err );
+ }
+ else
+ {
+ // Indicate client that specified context cannot be found
+ ERROR_2( KErrNotFound, "Published context not found: [%S: %S]",
+ &aContext.Source(),
+ &aContext.Type() );
+ User::Leave( KErrNotFound );
+ }
+ }
+
+//-----------------------------------------------------------------------------
+// CCFContextManager::DoPublishContextL
+//-----------------------------------------------------------------------------
+//
+void CCFContextManager::DoPublishContextL( CCFContextObject& aContext,
+ CCFContextDataObject* aData )
+ {
+ FUNC_LOG;
+
+ // Define context
+ aContext.SetTimestampToHomeTime();
+ iCacheSearchKey->Context().CopyL( aContext );
+ CCFCacheElement* currentCacheElement = iCacheSearchKey;
+ TBool valueChanged = EFalse;
+ TInt index = KErrNone;
+ TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
+ index,
+ *iCacheOrder);
+
+ // Both source and type must match.
+ // Otherwise context has not been defined and will lead to error.
+ if( searchError == KErrNone )
+ {
+ if( index >= 0 && index < iContextCache.Count() )
+ {
+ // index and indexByType points to the matching cache elements
+ currentCacheElement = iContextCache[ index ];
+ }
+ else
+ {
+ // index not found -> leave
+ ERROR( KErrNotFound, "Context cache element not found from cache list" );
+ User::Leave( KErrNotFound );
+ }
+
+ // store previous values
+ iPreviousContext->CopyL( currentCacheElement->Context() );
+
+ // Check if we have to update cache and indicate subscribers
+ if( currentCacheElement->Context().Value() != aContext.Value() )
+ {
+ // Update context
+ currentCacheElement->Context().CopyL( aContext );
+ valueChanged = ETrue;
+ }
+
+ LogContextCache();
+
+ // Let subscriptions do the indication if needed
+ iPublishingForCacheElement = currentCacheElement;
+ const RPointerArray< CCFContextSubscriptionImpl >& subscriptions =
+ currentCacheElement->Subscriptions();
+ TInt count = subscriptions.Count();
+ CCFContextSubscriptionImpl* subscription = NULL;
+ for( TInt i = 0 ; i < count; i++ )
+ {
+ subscription = subscriptions[ i ];
+ if( subscription )
+ {
+ if( aData && subscription->DataObjectEnabled() )
+ {
+ subscription->EvaluateContextChangeL( aContext,
+ *aData,
+ valueChanged );
+ }
+ else
+ {
+ subscription->EvaluateContextChangeL( aContext,
+ *iPreviousContext,
+ valueChanged );
+ }
+ }
+ }
+ iPublishingForCacheElement = NULL;
+
+ INFO_3( "Published context: [%S: %S: %S]",
+ &aContext.Source(),
+ &aContext.Type(),
+ &aContext.Value() );
+ if( aData )
+ {
+ INFO_1( "Published data object: [0x%x]", aData->Uid() );
+ }
+ }
+ else
+ {
+ // Indicate client that specified context cannot be found
+ ERROR_2( KErrNotFound, "Published context not found: [%S: %S]",
+ &aContext.Source(),
+ &aContext.Type() );
+ User::Leave( KErrNotFound );
+ }
+ }
+
+//------------------------------------------------------------------------------
+// CCFContextManager::RedefineAllowed
+//------------------------------------------------------------------------------
+//
+TBool CCFContextManager::RedefineAllowed( CCFCacheElement& aElement,
+ const MCFContextSource* aSource,
+ const TUid& aUid ) const
+ {
+ FUNC_LOG;
+
+ TBool allowed = EFalse;
+
+ // Redefine is allowed:
+ // - Same client session from the same client process
+ if( aElement.ContextPublisher() == aSource &&
+ aElement.PublisherUid() == aUid )
+ {
+ allowed = ETrue;
+ }
+
+ // - The owner is NULL and the client process is the same
+ else if( !aElement.ContextPublisher() &&
+ aElement.PublisherUid() == aUid )
+ {
+ allowed = ETrue;
+ }
+
+ // - Owner is NULL and the redefine is done by context source plug-in
+ else if( !aElement.ContextPublisher() &&
+ KCFServerSid == aUid )
+ {
+ allowed = ETrue;
+ }
+
+ return allowed;
+ }
+
+// End of file
+