contextframework/cfw/src/cfserver/CFContextManager.cpp
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 /*
       
     2 * Copyright (c) 2002-2008 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  CCFContextManager class implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <cfcontextdataobject.h>
       
    20 
       
    21 #include "CFContextManager.h"
       
    22 #include "CFContextQueryImpl.h"
       
    23 #include "CFContextObjectImpl.h"
       
    24 #include "cfcontextsubscriptionlistener.h"
       
    25 #include "CFContextSubscriptionImpl.h"
       
    26 #include "CFCacheElement.h"
       
    27 #include "cfutils.h"
       
    28 #include "cftrace.h"
       
    29 #include "CFContextDataProxy.h"
       
    30 #include "cfcommon.h"
       
    31 
       
    32 // Public Constructors and destructors
       
    33 CCFContextManager* CCFContextManager::NewL(
       
    34 	MCFSecurityChecker& aSecurityChecker )
       
    35     {
       
    36     FUNC_LOG;
       
    37 
       
    38     CCFContextManager* self = CCFContextManager::NewLC( aSecurityChecker );
       
    39     CleanupStack::Pop(self);
       
    40 
       
    41     return self;
       
    42     }
       
    43 
       
    44 CCFContextManager* CCFContextManager::NewLC(
       
    45 	MCFSecurityChecker& aSecurityChecker )
       
    46     {
       
    47     FUNC_LOG;
       
    48 
       
    49     CCFContextManager* self
       
    50     	= new (ELeave) CCFContextManager( aSecurityChecker );
       
    51     CleanupStack::PushL(self);
       
    52     self->ConstructL();
       
    53 
       
    54     return self;
       
    55     }
       
    56 
       
    57 CCFContextManager::~CCFContextManager()
       
    58     {
       
    59     FUNC_LOG;
       
    60 
       
    61     iCleanupCacheElements.Close();
       
    62     iContextCache.ResetAndDestroy();
       
    63     iContextCache.Close();
       
    64     delete iPreviousContext;
       
    65     delete iCacheOrder;
       
    66     delete iCacheSearchKey;
       
    67 
       
    68     iSubscriptions.ResetAndDestroy();
       
    69     }
       
    70 
       
    71 CCFContextManager::CCFContextManager( MCFSecurityChecker& aSecurityChecker )
       
    72     {
       
    73     FUNC_LOG;
       
    74 
       
    75     iSecurityChecker = &aSecurityChecker;
       
    76     }
       
    77 
       
    78 void CCFContextManager::ConstructL()
       
    79     {
       
    80     FUNC_LOG;
       
    81 
       
    82     iCacheOrder = new (ELeave) TLinearOrder<CCFCacheElement>
       
    83         (CCFCacheElement::CompareByTypeAndSource);
       
    84 
       
    85     iCacheSearchKey = CCFCacheElement::NewL();
       
    86 
       
    87     iPreviousContext = CCFContextObject::NewL();
       
    88     }
       
    89 
       
    90 // METHODS
       
    91 
       
    92 //-----------------------------------------------------------------------------
       
    93 // CCFContextManager::PublishContextL
       
    94 //-----------------------------------------------------------------------------
       
    95 //
       
    96 void CCFContextManager::PublishContextL( CCFContextObject &aContext,
       
    97     RThread& aClientThread )
       
    98     {
       
    99     FUNC_LOG;
       
   100 
       
   101     ValidatePublishContextL( aContext, aClientThread );
       
   102     DoPublishContextL( aContext );
       
   103     }
       
   104 
       
   105 //-----------------------------------------------------------------------------
       
   106 // CCFContextManager::PublishContextL
       
   107 //-----------------------------------------------------------------------------
       
   108 //
       
   109 void CCFContextManager::PublishContextL( CCFContextObject &aContext,
       
   110     RThread& aClientThread,
       
   111     CCFContextDataObject& aData )
       
   112     {
       
   113     FUNC_LOG;
       
   114 
       
   115     ValidatePublishContextL( aContext, aClientThread );
       
   116     DoPublishContextL( aContext, &aData );
       
   117     }
       
   118 
       
   119 //-----------------------------------------------------------------------------
       
   120 // CCFContextManager::RequestContextL
       
   121 //-----------------------------------------------------------------------------
       
   122 //
       
   123 void CCFContextManager::RequestContextL( RContextObjectArray& aResultBuffer,
       
   124     CCFContextQuery& aContextQuery,
       
   125     RThread& aClientThread )
       
   126     {
       
   127     FUNC_LOG;
       
   128 
       
   129     // Accessing the context cache for the latest context values is enough
       
   130     DoRequestContextL( aResultBuffer, aContextQuery, &aClientThread );
       
   131     }
       
   132 
       
   133 
       
   134 //-----------------------------------------------------------------------------
       
   135 // CCFContextManager::RequestContextL
       
   136 //-----------------------------------------------------------------------------
       
   137 //
       
   138 CCFContextObject* CCFContextManager::RequestContextL( const TDesC& aContextType,
       
   139     const TDesC& aContextSource,
       
   140     RThread& aClientThread )
       
   141     {
       
   142     FUNC_LOG;
       
   143 
       
   144     // check the cache
       
   145     iCacheSearchKey->Context().SetTypeL( aContextType );
       
   146     iCacheSearchKey->Context().SetSourceL( aContextSource );
       
   147     TInt index = KErrNone;
       
   148     if( iContextCache.FindInOrder( iCacheSearchKey, index,
       
   149         *iCacheOrder ) == KErrNone )
       
   150         {
       
   151         // index points to the matching object
       
   152         if( index >= 0 && index < iContextCache.Count() )
       
   153             {
       
   154             User::LeaveIfError( DoReadSecurityCheck(
       
   155                 *iContextCache[index],
       
   156                 aClientThread ) );
       
   157             return &iContextCache[index]->Context();
       
   158             }
       
   159         else
       
   160             {
       
   161             return NULL;
       
   162             }
       
   163         }
       
   164     else    // == KErrNotFound
       
   165         {   // index points to "the place to be"
       
   166         return NULL;
       
   167         }
       
   168     }
       
   169 
       
   170 //-----------------------------------------------------------------------------
       
   171 // CCFContextManager::SubscriptionAddedL
       
   172 //-----------------------------------------------------------------------------
       
   173 //
       
   174 void CCFContextManager::SubscriptionAddedL(
       
   175     CCFContextSubscriptionImpl& aSubscription,
       
   176     RThread& aClientThread )
       
   177     {
       
   178     FUNC_LOG;
       
   179 
       
   180     TInt count = iContextCache.Count();
       
   181     CCFCacheElement* element = NULL;
       
   182     for( TInt i = 0; i < count; i++ )
       
   183         {
       
   184         element = iContextCache[i];
       
   185         if( aSubscription.Matches( element->Context().Type(),
       
   186             element->Context().Source() ) )
       
   187             {
       
   188             TInt err = DoReadSecurityCheck( *element, aClientThread );
       
   189             if (err == KErrNone)
       
   190             	{
       
   191             	element->AddSubscriptionL( aSubscription );
       
   192             	}
       
   193             else
       
   194             	{
       
   195             	aSubscription.SubscriptionListener().HandleContextSubscriptionError( err,
       
   196             		element->Context().Source(),
       
   197             		element->Context().Type() );
       
   198             	}
       
   199             }
       
   200         }
       
   201     }
       
   202 
       
   203 //-----------------------------------------------------------------------------
       
   204 // CCFContextManager::SubscriptionRemoved
       
   205 //-----------------------------------------------------------------------------
       
   206 //
       
   207 TBool CCFContextManager::SubscriptionRemoved(
       
   208     CCFContextSubscriptionImpl& aSubscription)
       
   209     {
       
   210     FUNC_LOG;
       
   211 
       
   212     TBool cleanupElement( EFalse );
       
   213     for( TInt i = 0; i < iContextCache.Count(); i++ )
       
   214         {
       
   215         TInt j = iContextCache[ i ]->Subscriptions().Count() - 1;
       
   216         for( ; j >= 0; j-- )
       
   217             {
       
   218             if( &aSubscription == iContextCache[ i ]->Subscriptions()[ j ] )
       
   219                 {
       
   220                 CCFCacheElement* cacheElement = iContextCache[ i ];
       
   221                 if ( iPublishingForCacheElement
       
   222                     && ( iPublishingForCacheElement == cacheElement ) )
       
   223                     {
       
   224                     cleanupElement = ETrue;
       
   225                     cacheElement->NullifySubscription( j );
       
   226                     TInt err = iCleanupCacheElements.InsertInAddressOrder(
       
   227                             cacheElement );
       
   228                     if ( err == KErrAlreadyExists )
       
   229                         {
       
   230                         err = KErrNone;
       
   231                         }
       
   232                     ERROR( err, "CCFContextManager::SubscriptionRemoved - Adding cache element to cleanup array failed!" );
       
   233                     }
       
   234                 else
       
   235                     {
       
   236                     cacheElement->RemoveSubscription( j );
       
   237                     }
       
   238                 }
       
   239             }
       
   240         }
       
   241 
       
   242     return cleanupElement;
       
   243     }
       
   244 
       
   245 
       
   246 //----------------------------------------------------------------------------
       
   247 // CCFContextManager::DefineContextL
       
   248 //----------------------------------------------------------------------------
       
   249 //
       
   250 void CCFContextManager::DefineContextL( const TDesC& aContextSource,
       
   251     const TDesC& aContextType,
       
   252     const TSecurityPolicy& aReadSecurityPolicy,
       
   253     const TSecurityPolicy& aWriteSecurityPolicy )
       
   254     {
       
   255     FUNC_LOG;
       
   256 
       
   257     RThread thread;
       
   258     CleanupClosePushL( thread );
       
   259 
       
   260     DefineContextL( aContextSource, aContextType, aReadSecurityPolicy,
       
   261     		aWriteSecurityPolicy, NULL, thread.SecureId() );
       
   262 
       
   263     CleanupStack::PopAndDestroy( );
       
   264     }
       
   265 
       
   266 
       
   267 //----------------------------------------------------------------------------
       
   268 // CCFContextManager::DefineContextL
       
   269 //----------------------------------------------------------------------------
       
   270 //
       
   271 void CCFContextManager::DefineContextL( const TDesC& aContextSource,
       
   272     const TDesC& aContextType,
       
   273     const TSecurityPolicy& aReadSecurityPolicy,
       
   274     const TSecurityPolicy& aWriteSecurityPolicy,
       
   275     MCFContextSource* aContextPublisher,
       
   276     const TUid& aPublisherUid )
       
   277     {
       
   278     FUNC_LOG;
       
   279 
       
   280     // Prepare and find context
       
   281     iCacheSearchKey->Context().SetSourceL( aContextSource );
       
   282     iCacheSearchKey->Context().SetTypeL( aContextType );
       
   283     iCacheSearchKey->Context().SetValueL( KNullDesC );
       
   284     iCacheSearchKey->SetReadSecurityPolicy( aReadSecurityPolicy );
       
   285     iCacheSearchKey->SetWriteSecurityPolicy( aWriteSecurityPolicy );
       
   286     iCacheSearchKey->SetContextPublisher( aContextPublisher, aPublisherUid );
       
   287 
       
   288     TInt index = KErrNone;
       
   289     TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
       
   290         index,
       
   291         *iCacheOrder );
       
   292 
       
   293     if ( searchError != KErrNone )
       
   294         {
       
   295         // New context type
       
   296         User::LeaveIfError(
       
   297             iContextCache.Insert( iCacheSearchKey, index ) );
       
   298         CacheElementAddedL( *iCacheSearchKey );
       
   299         iCacheSearchKey = NULL;
       
   300         iCacheSearchKey = CCFCacheElement::NewL();
       
   301 
       
   302         // Signalling new context type
       
   303         iPreviousContext->SetSourceL( KNullDesC );
       
   304         iPreviousContext->SetTypeL( KNullDesC );
       
   305 
       
   306         INFO_2( "New context defined: [%S: %S]",
       
   307             &aContextSource,
       
   308             &aContextType );
       
   309         }
       
   310     else
       
   311         {
       
   312         TInt err = KErrNone;
       
   313         CCFCacheElement* cacheElement = iContextCache[index];
       
   314         if( cacheElement->PublisherUid() == aPublisherUid )
       
   315             {
       
   316             if( RedefineAllowed( *cacheElement, aContextPublisher, aPublisherUid ) )
       
   317                 {
       
   318                 cacheElement->SetContextPublisher( aContextPublisher,
       
   319                     aPublisherUid );
       
   320                 INFO_3( "Context [%S: %S] redefined by client [%x]",
       
   321                     &aContextSource, &aContextType, aPublisherUid.iUid );
       
   322                 }
       
   323             else
       
   324                 {
       
   325                 err = KErrAlreadyExists;
       
   326                 }
       
   327             }
       
   328         else
       
   329             {
       
   330             err = KErrAlreadyExists;
       
   331             }
       
   332 
       
   333         ERROR_2( err, "Context already defined: [%S: %S]",
       
   334             &aContextSource,
       
   335             &aContextType );
       
   336         User::LeaveIfError( err );
       
   337         }
       
   338     }
       
   339 
       
   340 
       
   341 //-----------------------------------------------------------------------------
       
   342 // CCFContextManager::GetReadSecurityPolicyL
       
   343 //-----------------------------------------------------------------------------
       
   344 //
       
   345 void CCFContextManager::GetReadSecurityPolicyL( const TDesC& aContextSource,
       
   346             const TDesC& aContextType,
       
   347 			TSecurityPolicy& aPolicy )
       
   348 	{
       
   349 	FUNC_LOG;
       
   350 
       
   351     TInt count = iContextCache.Count();
       
   352     CCFCacheElement* cacheElement = NULL;
       
   353     for( TInt i = 0; i < count; i++ )
       
   354         {
       
   355         cacheElement = iContextCache[ i ];
       
   356 
       
   357         if( cacheElement->Context().Source().Compare( aContextSource ) == 0
       
   358         	&& cacheElement->Context().Type().Compare( aContextType ) == 0 )
       
   359         	{
       
   360 			aPolicy = cacheElement->GetReadSecurityPolicy();
       
   361 			return;
       
   362         	}
       
   363         }
       
   364 
       
   365 	ERROR_2( KErrNotFound, "Security Policy for [%S: %S] not found!",
       
   366 		&aContextSource, &aContextType );
       
   367 	User::Leave( KErrNotFound );
       
   368 	}
       
   369 
       
   370 //-----------------------------------------------------------------------------
       
   371 // CCFContextManager::GetWriteSecurityPolicyL
       
   372 //-----------------------------------------------------------------------------
       
   373 //
       
   374 void CCFContextManager::GetWriteSecurityPolicyL( const TDesC& aContextSource,
       
   375             const TDesC& aContextType,
       
   376 			TSecurityPolicy& aPolicy )
       
   377 	{
       
   378 	FUNC_LOG;
       
   379 
       
   380     TInt count = iContextCache.Count();
       
   381     CCFCacheElement* cacheElement = NULL;
       
   382     for( TInt i = 0; i < count; i++ )
       
   383         {
       
   384         cacheElement = iContextCache[ i ];
       
   385 
       
   386         if( cacheElement->Context().Source().Compare( aContextSource ) == 0
       
   387         	&& cacheElement->Context().Type().Compare( aContextType ) == 0 )
       
   388         	{
       
   389 			aPolicy = cacheElement->GetWriteSecurityPolicy();
       
   390 			return;
       
   391         	}
       
   392         }
       
   393 
       
   394 	ERROR_2( KErrNotFound, "Security Policy for [%S: %S] not found!",
       
   395 		&aContextSource, &aContextType );
       
   396 	User::Leave( KErrNotFound );
       
   397 	}
       
   398 
       
   399 
       
   400 //-----------------------------------------------------------------------------
       
   401 // CCFContextManager::DeregisterPublisher
       
   402 //-----------------------------------------------------------------------------
       
   403 //
       
   404 void CCFContextManager::DeregisterPublisher( MCFContextSource& aPublisher )
       
   405 	{
       
   406     FUNC_LOG;
       
   407 
       
   408     for( TInt i = 0; i < iContextCache.Count() ; i++ )
       
   409         {
       
   410         CCFCacheElement* cacheElement = iContextCache[ i ];
       
   411         if( cacheElement->ContextPublisher() == &aPublisher )
       
   412         	{
       
   413 			cacheElement->SetContextPublisher( NULL );
       
   414         	}
       
   415         }
       
   416 	}
       
   417 
       
   418 
       
   419 //-----------------------------------------------------------------------------
       
   420 // CCFContextManager::GetLatestFromCacheL
       
   421 //-----------------------------------------------------------------------------
       
   422 //
       
   423 void CCFContextManager::GetLatestFromCacheL(
       
   424     RContextObjectArray& aLatestContexts,
       
   425     queryMatchFunction aMatchFunction,
       
   426     const CCFContextQueryImpl& aContextQuery,
       
   427     RThread* aClientThread )
       
   428     {
       
   429     FUNC_LOG;
       
   430 
       
   431     TInt count = iContextCache.Count();
       
   432     CCFCacheElement* cacheElement = NULL;
       
   433     for( TInt i = 0; i < count; ++i )
       
   434         {
       
   435         cacheElement = iContextCache[ i ];
       
   436         if( cacheElement->Context().Value().Length()
       
   437             && ( aContextQuery.*aMatchFunction )(
       
   438                 cacheElement->Context().Type(),
       
   439                 cacheElement->Context().Source() ) )
       
   440             {
       
   441             if( !aClientThread ||
       
   442                 DoReadSecurityCheck( *cacheElement, *aClientThread ) == KErrNone )
       
   443                 {
       
   444                 aLatestContexts.AppendL( &cacheElement->Context() );
       
   445                 }
       
   446             }
       
   447         }
       
   448     }
       
   449 
       
   450 //-----------------------------------------------------------------------------
       
   451 // CCFContextManager::LogContextCache
       
   452 //-----------------------------------------------------------------------------
       
   453 //
       
   454 void CCFContextManager::LogContextCache()
       
   455     {
       
   456 #ifdef DEBUG_LOG_CONTEXT_CACHE
       
   457     INFO( "CONTEXT CACHE start:" );
       
   458     TInt cacheIndex;
       
   459     for (cacheIndex = 0; cacheIndex < iContextCache.Count(); ++cacheIndex)
       
   460         {
       
   461         iContextCache[cacheIndex]->DebugPrintContents();
       
   462         }
       
   463     INFO( "CONTEXT CACHE start:" );
       
   464     INFO( "CONTEXT CACHE BY TYPE start:" );
       
   465     for (cacheIndex = 0; cacheIndex < iContextCacheByType.Count() ;
       
   466     ++cacheIndex)
       
   467         {
       
   468         iContextCacheByType[cacheIndex]->DebugPrintContents();
       
   469         }
       
   470     INFO( "CONTEXT CACHE BY TYPE end:" );
       
   471 #endif // DEBUG_LOG_CONTEXT_CACHE
       
   472     }
       
   473 
       
   474 //-----------------------------------------------------------------------------
       
   475 // CCFContextManager::DoSecurityCheck
       
   476 //-----------------------------------------------------------------------------
       
   477 //
       
   478 TInt CCFContextManager::DoReadSecurityCheck( CCFCacheElement& aContextCache,
       
   479     RThread& aClientThread )
       
   480     {
       
   481     FUNC_LOG;
       
   482 
       
   483     // Security check only needed if request is from other process than CF
       
   484     TInt err = KErrNone;
       
   485 
       
   486     TBool securityCheckOk =
       
   487         iSecurityChecker->CheckClientSecurity( aClientThread,
       
   488             aContextCache.GetReadSecurityPolicy() );
       
   489 
       
   490     if( !securityCheckOk )
       
   491         {
       
   492         // Insuffcient security, indicate client
       
   493         err = KErrAccessDenied;
       
   494         }
       
   495 
       
   496     return err;
       
   497     }
       
   498 
       
   499 //-----------------------------------------------------------------------------
       
   500 // CCFContextManager::DoSecurityCheck
       
   501 //-----------------------------------------------------------------------------
       
   502 //
       
   503 TInt CCFContextManager::DoWriteSecurityCheck( CCFCacheElement& aContextCache,
       
   504     RThread& aClientThread )
       
   505     {
       
   506     FUNC_LOG;
       
   507 
       
   508     // Security check only needed if request is from other process than CF
       
   509     TInt err = KErrNone;
       
   510 
       
   511     TBool securityCheckOk =
       
   512         iSecurityChecker->CheckClientSecurity( aClientThread,
       
   513             aContextCache.GetWriteSecurityPolicy() );
       
   514 
       
   515     if( !securityCheckOk )
       
   516         {
       
   517         // Insuffcient security, indicate client
       
   518         err = KErrAccessDenied;
       
   519         }
       
   520 
       
   521     return err;
       
   522     }
       
   523 
       
   524 
       
   525 //-----------------------------------------------------------------------------
       
   526 // CCFContextManager::DoRequestContextL
       
   527 //-----------------------------------------------------------------------------
       
   528 //
       
   529 void CCFContextManager::DoRequestContextL( RContextObjectArray& aResultBuffer,
       
   530     CCFContextQuery& aContextQuery,
       
   531     RThread* aClientThread )
       
   532     {
       
   533     FUNC_LOG;
       
   534 
       
   535     CCFContextQueryImpl& queryImpl = (CCFContextQueryImpl&) aContextQuery;
       
   536     GetLatestFromCacheL( aResultBuffer,
       
   537         &CCFContextQueryImpl::Matches,
       
   538         queryImpl,
       
   539         aClientThread );
       
   540     }
       
   541 
       
   542 //-----------------------------------------------------------------------------
       
   543 // CCFContextManager::SubscribeContextL
       
   544 //-----------------------------------------------------------------------------
       
   545 //
       
   546 void CCFContextManager::SubscribeContextL(
       
   547     CCFContextSubscription* aSubscription,
       
   548     MCFContextSubscriptionListener* aListener,
       
   549     RThread& aClientThread )
       
   550     {
       
   551     FUNC_LOG;
       
   552 
       
   553 	CCFContextSubscriptionImpl* subscriptionImpl =
       
   554         static_cast<CCFContextSubscriptionImpl*>( aSubscription );
       
   555     subscriptionImpl->SetSubscriptionListener( *aListener );
       
   556 
       
   557     // Append new subscription into array
       
   558     TInt err = iSubscriptions.Append( subscriptionImpl );
       
   559     if( err != KErrNone )
       
   560         {
       
   561         User::Leave( err );
       
   562         }
       
   563 
       
   564     // Notify data manager that new subscription has been added
       
   565     TRAP( err,
       
   566         SubscriptionAddedL( *subscriptionImpl, aClientThread ) );
       
   567     if( err )
       
   568         {
       
   569         iSubscriptions.Remove( iSubscriptions.Count() -1 );
       
   570         User::Leave( err );
       
   571         }
       
   572     }
       
   573 
       
   574 //-----------------------------------------------------------------------------
       
   575 // CCFContextManager::RemoveSubscription
       
   576 //-----------------------------------------------------------------------------
       
   577 //
       
   578 TBool CCFContextManager::RemoveSubscription(
       
   579     CCFContextSubscription& aSubscription,
       
   580     MCFContextSubscriptionListener& aListener )
       
   581     {
       
   582     FUNC_LOG;
       
   583 
       
   584     TBool cleanupElement( EFalse );
       
   585    	CCFContextSubscriptionImpl* subscriptionImpl =
       
   586    	    static_cast<CCFContextSubscriptionImpl*>( &aSubscription );
       
   587 
       
   588     subscriptionImpl->SetSubscriptionListener( aListener );
       
   589     TBool deleteSubscriptionImpl( EFalse );
       
   590 
       
   591     TInt i = iSubscriptions.Count() - 1;
       
   592     while ( i >= 0 )
       
   593         {
       
   594         if ( i >= iSubscriptions.Count() )
       
   595             {
       
   596             // Context source has removed subscriptions via synchronous call
       
   597             // e.g. from managers call to source's NoSubscribers() function.
       
   598             i = iSubscriptions.Count() - 1;
       
   599             }
       
   600 
       
   601         if ( i < 0 )
       
   602             {
       
   603             INFO( "All subscriptions removed" );
       
   604             break;
       
   605             }
       
   606 
       
   607         if ( iSubscriptions[ i ]->IsSame( *subscriptionImpl ) )
       
   608             {
       
   609             CCFContextSubscriptionImpl* subscription = iSubscriptions[ i ];
       
   610             iSubscriptions.Remove( i );
       
   611             INFO_2( "CCFContextManager::RemoveSubscription - Subscription [%S: %S] removed",
       
   612                     &subscription->ContextSource(),
       
   613                     &subscription->ContextType() );
       
   614             if ( SubscriptionRemoved( *subscription ) )
       
   615                 {
       
   616                 cleanupElement = ETrue;
       
   617                 }
       
   618             if ( subscription != subscriptionImpl )
       
   619                 {
       
   620                 delete subscription;
       
   621                 }
       
   622             else
       
   623                 {
       
   624                 // Delay deleting when the same subscription instance is used
       
   625                 // internally for both subscribe and unsubscribe.
       
   626                 deleteSubscriptionImpl = ETrue;
       
   627                 }
       
   628             }
       
   629         --i;
       
   630         }
       
   631 
       
   632     if ( deleteSubscriptionImpl )
       
   633         {
       
   634         delete subscriptionImpl;
       
   635         }
       
   636 
       
   637     return cleanupElement;
       
   638     }
       
   639 
       
   640 //-----------------------------------------------------------------------------
       
   641 // CCFContextManager::RemoveSubscription
       
   642 //-----------------------------------------------------------------------------
       
   643 //
       
   644 TBool CCFContextManager::RemoveSubscriptions(
       
   645     MCFContextSubscriptionListener* aListener)
       
   646     {
       
   647     FUNC_LOG;
       
   648 
       
   649     TBool cleanupElement( EFalse );
       
   650 
       
   651     TInt i = iSubscriptions.Count() - 1;
       
   652     while ( i >= 0 )
       
   653         {
       
   654         if ( i >= iSubscriptions.Count() )
       
   655             {
       
   656             // Context source has removed subscriptions via synchronous call
       
   657             // e.g. from managers call to source's NoSubscribers() function.
       
   658             i = iSubscriptions.Count() - 1;
       
   659             }
       
   660 
       
   661         if ( i < 0 )
       
   662             {
       
   663             INFO( "All subscriptions removed" );
       
   664             break;
       
   665             }
       
   666 
       
   667         CCFContextSubscriptionImpl* subscription = iSubscriptions[ i ];
       
   668         if ( &( subscription->SubscriptionListener() ) == aListener )
       
   669             {
       
   670             iSubscriptions.Remove( i );
       
   671             if ( SubscriptionRemoved( *subscription ) )
       
   672                 {
       
   673                 cleanupElement = ETrue;
       
   674                 }
       
   675             delete subscription;
       
   676             subscription = NULL;
       
   677             }
       
   678         --i;
       
   679         }
       
   680 
       
   681     return cleanupElement;
       
   682     }
       
   683 
       
   684 //-----------------------------------------------------------------------------
       
   685 // CCFContextManager::CleanupCacheElementSubscriptions
       
   686 //-----------------------------------------------------------------------------
       
   687 //
       
   688 void CCFContextManager::CleanupCacheElementSubscriptions()
       
   689     {
       
   690     FUNC_LOG;
       
   691 
       
   692     for ( TInt i = 0; i < iCleanupCacheElements.Count(); ++i )
       
   693         {
       
   694         CCFCacheElement* element = iCleanupCacheElements[ i ];
       
   695         element->RemoveNullSubscriptions();
       
   696         }
       
   697     iCleanupCacheElements.Reset();
       
   698     }
       
   699 
       
   700 //-----------------------------------------------------------------------------
       
   701 // CCFContextManager::CacheElementAddedL
       
   702 //-----------------------------------------------------------------------------
       
   703 //
       
   704 void CCFContextManager::CacheElementAddedL(
       
   705     CCFCacheElement& aCacheElement )
       
   706     {
       
   707     FUNC_LOG;
       
   708 
       
   709     TInt count = iSubscriptions.Count();
       
   710     CCFContextSubscriptionImpl* subscription = NULL;
       
   711     for( TInt i = 0; i < count; i++ )
       
   712         {
       
   713         subscription = iSubscriptions[i];
       
   714         if( subscription->Matches( aCacheElement.Context().Type(),
       
   715             aCacheElement.Context().Source() ) )
       
   716             {
       
   717             // Check security
       
   718             RThread thread;
       
   719             TInt err =
       
   720                 subscription->SubscriptionListener().Client( thread );
       
   721             if( err == KErrNone )
       
   722                 {
       
   723                 err = DoReadSecurityCheck( aCacheElement, thread );
       
   724                 if( err == KErrNone )
       
   725                     {
       
   726                     aCacheElement.AddSubscriptionL( *subscription );
       
   727                     }
       
   728                 else
       
   729                     {
       
   730                     subscription->SubscriptionListener().HandleContextSubscriptionError(
       
   731                         err,
       
   732             			aCacheElement.Context().Source(),
       
   733             			aCacheElement.Context().Type() );
       
   734                     }
       
   735                 }
       
   736             else
       
   737                 {
       
   738                 subscription->SubscriptionListener().HandleContextSubscriptionError(
       
   739                     err,
       
   740             		aCacheElement.Context().Source(),
       
   741             		aCacheElement.Context().Type() );
       
   742                 }
       
   743             thread.Close();
       
   744             }
       
   745         }
       
   746     }
       
   747 
       
   748 //-----------------------------------------------------------------------------
       
   749 // CCFContextManager::ValidatePublishContextL
       
   750 //-----------------------------------------------------------------------------
       
   751 //
       
   752 void CCFContextManager::ValidatePublishContextL( CCFContextObject& aContext,
       
   753     RThread& aClientThread )
       
   754     {
       
   755     FUNC_LOG;
       
   756 
       
   757     // Define context
       
   758     iCacheSearchKey->Context().CopyL( aContext );
       
   759     CCFCacheElement* currentCacheElement = iCacheSearchKey;
       
   760     TInt index = KErrNone;
       
   761     TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
       
   762         index,
       
   763         *iCacheOrder);
       
   764 
       
   765     // Both source and type must match.
       
   766     // Otherwise context has not been defined and will lead to error.
       
   767     if( searchError == KErrNone )
       
   768         {
       
   769         if( index >= 0 && index < iContextCache.Count() )
       
   770             {
       
   771             // index and indexByType points to the matching cache elements
       
   772             currentCacheElement = iContextCache[index];
       
   773             }
       
   774         else
       
   775             {
       
   776             // index not found -> leave
       
   777             ERROR_GEN( "Context cache element not found from cache list" );
       
   778             User::Leave( KErrNotFound );
       
   779             }
       
   780 
       
   781         // Perform security check
       
   782         TInt err = DoWriteSecurityCheck( *currentCacheElement, aClientThread );
       
   783         ERROR_2( err, "Security check failed: [%S: %S]",
       
   784              &aContext.Source(),
       
   785              &aContext.Type() );
       
   786         User::LeaveIfError( err );
       
   787         }
       
   788     else
       
   789         {
       
   790         // Indicate client that specified context cannot be found
       
   791         ERROR_2( KErrNotFound, "Published context not found: [%S: %S]",
       
   792             &aContext.Source(),
       
   793             &aContext.Type() );
       
   794         User::Leave( KErrNotFound );
       
   795         }
       
   796     }
       
   797 
       
   798 //-----------------------------------------------------------------------------
       
   799 // CCFContextManager::DoPublishContextL
       
   800 //-----------------------------------------------------------------------------
       
   801 //
       
   802 void CCFContextManager::DoPublishContextL( CCFContextObject& aContext,
       
   803     CCFContextDataObject* aData )
       
   804     {
       
   805     FUNC_LOG;
       
   806 
       
   807     // Define context
       
   808     aContext.SetTimestampToHomeTime();
       
   809     iCacheSearchKey->Context().CopyL( aContext );
       
   810     CCFCacheElement* currentCacheElement = iCacheSearchKey;
       
   811     TBool valueChanged = EFalse;
       
   812     TInt index = KErrNone;
       
   813     TInt searchError = iContextCache.FindInOrder( iCacheSearchKey,
       
   814         index,
       
   815         *iCacheOrder);
       
   816 
       
   817     // Both source and type must match.
       
   818     // Otherwise context has not been defined and will lead to error.
       
   819     if( searchError == KErrNone )
       
   820         {
       
   821         if( index >= 0 && index < iContextCache.Count() )
       
   822             {
       
   823             // index and indexByType points to the matching cache elements
       
   824             currentCacheElement = iContextCache[ index ];
       
   825             }
       
   826         else
       
   827             {
       
   828             // index not found -> leave
       
   829             ERROR( KErrNotFound, "Context cache element not found from cache list" );
       
   830             User::Leave( KErrNotFound );
       
   831             }
       
   832 
       
   833         // store previous values
       
   834         iPreviousContext->CopyL( currentCacheElement->Context() );
       
   835 
       
   836         // Check if we have to update cache and indicate subscribers
       
   837         if( currentCacheElement->Context().Value() != aContext.Value() )
       
   838             {
       
   839             // Update context
       
   840             currentCacheElement->Context().CopyL( aContext );
       
   841             valueChanged = ETrue;
       
   842             }
       
   843 
       
   844         LogContextCache();
       
   845 
       
   846         // Let subscriptions do the indication if needed
       
   847         iPublishingForCacheElement = currentCacheElement;
       
   848         const RPointerArray< CCFContextSubscriptionImpl >& subscriptions =
       
   849             currentCacheElement->Subscriptions();
       
   850         TInt count = subscriptions.Count();
       
   851         CCFContextSubscriptionImpl* subscription = NULL;
       
   852         for( TInt i = 0 ; i < count; i++ )
       
   853             {
       
   854             subscription = subscriptions[ i ];
       
   855             if( subscription )
       
   856                 {
       
   857                 if( aData && subscription->DataObjectEnabled() )
       
   858                     {
       
   859                     subscription->EvaluateContextChangeL( aContext,
       
   860                         *aData,
       
   861                         valueChanged );
       
   862                     }
       
   863                 else
       
   864                     {
       
   865                     subscription->EvaluateContextChangeL( aContext,
       
   866                         *iPreviousContext,
       
   867                         valueChanged );
       
   868                     }
       
   869                 }
       
   870             }
       
   871         iPublishingForCacheElement = NULL;
       
   872 
       
   873         INFO_3( "Published context: [%S: %S: %S]",
       
   874             &aContext.Source(),
       
   875             &aContext.Type(),
       
   876             &aContext.Value() );
       
   877         if( aData )
       
   878             {
       
   879             INFO_1( "Published data object: [0x%x]", aData->Uid() );
       
   880             }
       
   881         }
       
   882     else
       
   883         {
       
   884         // Indicate client that specified context cannot be found
       
   885         ERROR_2( KErrNotFound, "Published context not found: [%S: %S]",
       
   886             &aContext.Source(),
       
   887             &aContext.Type() );
       
   888         User::Leave( KErrNotFound );
       
   889         }
       
   890     }
       
   891 
       
   892 //------------------------------------------------------------------------------
       
   893 // CCFContextManager::RedefineAllowed
       
   894 //------------------------------------------------------------------------------
       
   895 //
       
   896 TBool CCFContextManager::RedefineAllowed( CCFCacheElement& aElement,
       
   897     const MCFContextSource* aSource,
       
   898     const TUid& aUid ) const
       
   899     {
       
   900     FUNC_LOG;
       
   901 
       
   902     TBool allowed = EFalse;
       
   903 
       
   904     // Redefine is allowed:
       
   905     // - Same client session from the same client process
       
   906     if( aElement.ContextPublisher() == aSource &&
       
   907         aElement.PublisherUid() == aUid )
       
   908         {
       
   909         allowed = ETrue;
       
   910         }
       
   911 
       
   912     // - The owner is NULL and the client process is the same
       
   913     else if( !aElement.ContextPublisher() &&
       
   914         aElement.PublisherUid() == aUid )
       
   915         {
       
   916         allowed = ETrue;
       
   917         }
       
   918 
       
   919     // - Owner is NULL and the redefine is done by context source plug-in
       
   920     else if( !aElement.ContextPublisher() &&
       
   921         KCFServerSid == aUid )
       
   922         {
       
   923         allowed = ETrue;
       
   924         }
       
   925 
       
   926     return allowed;
       
   927     }
       
   928 
       
   929 // End of file
       
   930