contextutility/src/hgcontextutilityimpl.cpp
branchRCL_3
changeset 14 15e4dd19031c
parent 12 502e5d91ad42
child 15 a0713522ab97
equal deleted inserted replaced
12:502e5d91ad42 14:15e4dd19031c
     1 /*
       
     2 * Copyright (c) 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:  Context publishing helper dll
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <cfcontextobject.h>
       
    20 #include <cfclient.h>
       
    21 #include <mdesession.h>
       
    22 #include <mdeobject.h>
       
    23 #include <s32mem.h>
       
    24 #include <MVPbkContactLink.h>
       
    25 #include <MVPbkStoreContact.h>
       
    26 #include <MVPbkStreamable.h>
       
    27 #include <CVPbkContactLinkArray.h>
       
    28 #include <e32debug.h>
       
    29 #include <w32std.h>
       
    30 #include "hgcontextutilityimpl.h"
       
    31 #include "hgcontexttypes.h"
       
    32 
       
    33 // max number of entries processed when aContextData is an array in PublishContextL
       
    34 const TInt KMaxEntriesInMulti = 20;
       
    35 
       
    36 // separator character in combined string for multiple entries
       
    37 const TInt KMultiSepChar = 0x0001;
       
    38 
       
    39 // granularity for string array
       
    40 const TInt KArrayGranularity = 4;
       
    41 
       
    42 // argument for CBufFlat ctor when serializing contact links
       
    43 const TInt KBufGranularity = 64;
       
    44 
       
    45 // default security policy (use LocalServices cap) for contexts
       
    46 _LIT_SECURITY_POLICY_C1( KContextSecurity, ECapabilityLocalServices );
       
    47 
       
    48 // -----------------------------------------------------------------------------
       
    49 // CHgContextUtilityImpl::NewL
       
    50 // -----------------------------------------------------------------------------
       
    51 //
       
    52 CHgContextUtilityImpl* CHgContextUtilityImpl::NewL()
       
    53     {
       
    54     CHgContextUtilityImpl* self = NewLC();
       
    55     CleanupStack::Pop( self );
       
    56     return self;
       
    57     }
       
    58 
       
    59 // -----------------------------------------------------------------------------
       
    60 // CHgContextUtilityImpl::NewLC
       
    61 // -----------------------------------------------------------------------------
       
    62 //
       
    63 CHgContextUtilityImpl* CHgContextUtilityImpl::NewLC()
       
    64     {
       
    65     CHgContextUtilityImpl* self = new ( ELeave ) CHgContextUtilityImpl;
       
    66     CleanupStack::PushL( self );
       
    67     self->ConstructL();
       
    68     return self;
       
    69     }
       
    70 
       
    71 // -----------------------------------------------------------------------------
       
    72 // CHgContextUtilityImpl::CHgContextUtilityImpl
       
    73 // -----------------------------------------------------------------------------
       
    74 //
       
    75 CHgContextUtilityImpl::CHgContextUtilityImpl()
       
    76         : CTimer( CActive::EPriorityStandard )
       
    77     {
       
    78     CActiveScheduler::Add( this );
       
    79     }
       
    80 
       
    81 // -----------------------------------------------------------------------------
       
    82 // CHgContextUtilityImpl::ConstructL
       
    83 // -----------------------------------------------------------------------------
       
    84 //
       
    85 void CHgContextUtilityImpl::ConstructL()
       
    86     {
       
    87     CTimer::ConstructL();
       
    88 
       
    89     iEnv = CCoeEnv::Static(); // may be NULL
       
    90 
       
    91     // Do not create iCFClient here as cf server may not be available yet
       
    92     // if we are early in the boot phase.
       
    93     
       
    94     // set defaults
       
    95     RePublishWhenFgL( EFalse );
       
    96     AllowPublishFromBackground( EFalse );
       
    97     }
       
    98 
       
    99 // -----------------------------------------------------------------------------
       
   100 // CHgContextUtilityImpl::~CHgContextUtilityImpl
       
   101 // -----------------------------------------------------------------------------
       
   102 //
       
   103 CHgContextUtilityImpl::~CHgContextUtilityImpl()
       
   104     {
       
   105     Cancel();
       
   106     delete iPendingContextType;
       
   107     delete iPendingContextData;
       
   108     delete iPendingContextDataArray;
       
   109     delete iCFClient;
       
   110     delete iLastContextType;
       
   111     delete iLastContextData;
       
   112     if ( iFgWatchEnabled && iEnv )
       
   113         {
       
   114         iEnv->RemoveForegroundObserver( *this );
       
   115         }
       
   116     
       
   117     iMusicContextInfo.ResetAndDestroy();
       
   118     }
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // CHgContextUtilityImpl::CFReady
       
   122 // -----------------------------------------------------------------------------
       
   123 //
       
   124 TBool CHgContextUtilityImpl::CFReady()
       
   125     {
       
   126     if ( !iCFClient )
       
   127         {
       
   128         TRAPD( err, iCFClient = CCFClient::NewL( *this ) );
       
   129         if ( err != KErrNone )
       
   130             {
       
   131             RDebug::Printf( "[hgctxutil] cfw not ready" );
       
   132             return EFalse;
       
   133             }
       
   134         }
       
   135     return ETrue;
       
   136     }
       
   137 
       
   138 // -----------------------------------------------------------------------------
       
   139 // CHgContextUtilityImpl::PublishContextL
       
   140 // All other non-static versions of this function will fall back to this one.
       
   141 // -----------------------------------------------------------------------------
       
   142 //
       
   143 void CHgContextUtilityImpl::PublishContextL( const TDesC& aContextType,
       
   144         const TDesC& aContextData )
       
   145     {
       
   146     RDebug::Print( _L("[hgctxutil] PublishContextL [%S] [%S]"),
       
   147         &aContextType, &aContextData );
       
   148     // create cf client instance if not yet done
       
   149     // and check foreground status if needed
       
   150     if ( CFReady() && AllowedToPublish() )
       
   151         {
       
   152         // call static version with our cf client instance
       
   153         PublishContextL( *iCFClient, aContextType, aContextData );
       
   154         }
       
   155     // store type and value for later use
       
   156     // (even when cfserver is not available yet, the data may still be
       
   157     //  used later when the app comes to foreground, for example)
       
   158     if ( iLastContextType != &aContextType )
       
   159         {
       
   160         delete iLastContextType; iLastContextType = 0;
       
   161         iLastContextType = aContextType.AllocL();
       
   162         }
       
   163     if ( iLastContextData != &aContextData )
       
   164         {
       
   165         delete iLastContextData; iLastContextData = 0;
       
   166         iLastContextData = aContextData.AllocL();
       
   167         }
       
   168     }
       
   169 
       
   170 // -----------------------------------------------------------------------------
       
   171 // AppendCharL
       
   172 // Appends a char to aDst, calls ReAllocL when needed, assumes that aDst
       
   173 // is also on cleanupstack (at top position) so it updates that pointer too.
       
   174 // -----------------------------------------------------------------------------
       
   175 //
       
   176 LOCAL_C void AppendCharL( HBufC*& aDst, TChar aChar )
       
   177     {
       
   178     TPtr des( aDst->Des() );
       
   179     if ( des.Length() == des.MaxLength() )
       
   180         {
       
   181         HBufC* oldDst = aDst;
       
   182         aDst = aDst->ReAllocL( des.MaxLength() * 2 );
       
   183         CleanupStack::Pop( oldDst ); // pop the old pointer
       
   184         CleanupStack::PushL( aDst ); // and push the new (possibly different) one
       
   185         des.Set( aDst->Des() );
       
   186         }
       
   187     des.Append( aChar );
       
   188     }
       
   189 
       
   190 // -----------------------------------------------------------------------------
       
   191 // CHgContextUtilityImpl::BuildCombinedStringL
       
   192 // -----------------------------------------------------------------------------
       
   193 //
       
   194 HBufC* CHgContextUtilityImpl::BuildCombinedStringL(
       
   195         const MDesCArray& aArray )
       
   196     {
       
   197     TInt arrayCount = aArray.MdcaCount();
       
   198     if ( arrayCount >= 2 )
       
   199         {
       
   200         // Rules:
       
   201         // 1. escape all separator chars in the input with a preceeding \
       
   202         // 2. escape all \ chars in the input with \\
       
   203         // 3. take only the first KMaxEntriesInMulti elements from the array
       
   204         // 4. append a separator also after last entry
       
   205         // 5. prepend two separators to the combined string
       
   206         TInt processedEntryCount = Min( arrayCount, KMaxEntriesInMulti );
       
   207         // calculate a big enough size so we can avoid ReAllocL calls later
       
   208         TInt sz = 0;
       
   209         for ( TInt i = 0; i < processedEntryCount; ++i )
       
   210             {
       
   211             sz += aArray.MdcaPoint( i ).Length() + 1;
       
   212             }
       
   213         sz += 2; // for the magic prefix
       
   214         HBufC* value = HBufC::NewLC( sz );
       
   215         AppendCharL( value, KMultiSepChar );
       
   216         AppendCharL( value, KMultiSepChar );
       
   217         for ( TInt i = 0; i < processedEntryCount; ++i )
       
   218             {
       
   219             TPtrC entry( aArray.MdcaPoint( i ) );
       
   220             // append, also do the escaping
       
   221             for ( TInt j = 0, je = entry.Length(); j != je; ++j )
       
   222                 {
       
   223                 TChar c = entry[j];
       
   224                 if ( c == KMultiSepChar || c == '\\' )
       
   225                     {
       
   226                     AppendCharL( value, '\\' );
       
   227                     }
       
   228                 AppendCharL( value, c );
       
   229                 }
       
   230             AppendCharL( value, KMultiSepChar );
       
   231             }
       
   232         CleanupStack::Pop( value );
       
   233         return value;
       
   234         }
       
   235     return 0;
       
   236     }
       
   237 
       
   238 // -----------------------------------------------------------------------------
       
   239 // CHgContextUtilityImpl::SplitCombinedStringL
       
   240 // -----------------------------------------------------------------------------
       
   241 //
       
   242 void CHgContextUtilityImpl::SplitCombinedStringL(
       
   243         const TDesC& aString, CDesCArray& aArray )
       
   244     {
       
   245     TInt inputLength = aString.Length();
       
   246     TBool isMulti = inputLength > 2
       
   247         && aString[0] == KMultiSepChar && aString[1] == KMultiSepChar;
       
   248     if ( isMulti )
       
   249         {
       
   250         // allocate a work buffer that is big enough for sure
       
   251         HBufC* buf = HBufC::NewLC( inputLength );
       
   252         TPtr des( buf->Des() );
       
   253         TBool esc = EFalse;
       
   254         // go through the string, find entries, and add them to output array
       
   255         for ( TInt i = 2; i < inputLength; ++i ) // start from 2 because of the magic prefix
       
   256             {
       
   257             TChar c = aString[i];
       
   258             if ( c == '\\' && !esc )
       
   259                 {
       
   260                 esc = ETrue;
       
   261                 }
       
   262             else if ( c == KMultiSepChar && !esc )
       
   263                 {
       
   264                 // found separator: append to output array, clear buffer, and continue
       
   265                 aArray.AppendL( des );
       
   266                 des.Zero();
       
   267                 }
       
   268             else
       
   269                 {
       
   270                 esc = EFalse;
       
   271                 des.Append( c );
       
   272                 }
       
   273             }
       
   274         CleanupStack::PopAndDestroy( buf );
       
   275         }
       
   276     else
       
   277         {
       
   278         // not a combined string: append to array as it is
       
   279         aArray.AppendL( aString );
       
   280         }
       
   281     }
       
   282 
       
   283 // -----------------------------------------------------------------------------
       
   284 // CHgContextUtilityImpl::PublishContextL
       
   285 // -----------------------------------------------------------------------------
       
   286 //
       
   287 void CHgContextUtilityImpl::PublishContextL( const TDesC& aContextType,
       
   288         const MDesCArray& aContextData )
       
   289     {
       
   290     TInt entryCount = aContextData.MdcaCount();
       
   291     // do nothing if array is empty
       
   292     if ( !entryCount )
       
   293         {
       
   294         return;
       
   295         }
       
   296     // nothing special when having only 1 item
       
   297     if ( entryCount == 1 )
       
   298         {
       
   299         PublishContextL( aContextType, aContextData.MdcaPoint( 0 ) );
       
   300         return;
       
   301         }
       
   302     // at least two items: create the special combined string
       
   303     HBufC* value = BuildCombinedStringL( aContextData );
       
   304     CleanupStack::PushL( value );
       
   305     // publish the combined string
       
   306     PublishContextL( aContextType, *value );
       
   307     CleanupStack::PopAndDestroy( value );
       
   308     }
       
   309 
       
   310 // -----------------------------------------------------------------------------
       
   311 // CHgContextUtilityImpl::PublishContextL
       
   312 // This is the version of the function where the real work is performed.
       
   313 // -----------------------------------------------------------------------------
       
   314 //
       
   315 void CHgContextUtilityImpl::PublishContextL( CCFClient& aCFClient,
       
   316         const TDesC& aContextType, const TDesC& aContextData )
       
   317     {
       
   318     CCFContextObject* context = CCFContextObject::NewLC();
       
   319     context->SetSourceL( KHgCFSource );
       
   320     context->SetTypeL( aContextType );
       
   321     context->SetValueL( aContextData );
       
   322     TInt err = aCFClient.PublishContext( *context );
       
   323     if ( err == KErrNotFound )
       
   324         {
       
   325         User::LeaveIfError( aCFClient.DefineContext( KHgCFSource,
       
   326             aContextType, KContextSecurity ) );
       
   327         err = aCFClient.PublishContext( *context );
       
   328         if ( err != KErrArgument ) // ignore -6 which comes e.g. when trying to publish an empty value
       
   329             {
       
   330             User::LeaveIfError( err );
       
   331             }
       
   332         }
       
   333     else if ( err != KErrArgument )
       
   334         {
       
   335         User::LeaveIfError( err );
       
   336         }
       
   337     CleanupStack::PopAndDestroy( context );
       
   338     }
       
   339 
       
   340 // -----------------------------------------------------------------------------
       
   341 // CHgContextUtilityImpl::GetContextL
       
   342 // -----------------------------------------------------------------------------
       
   343 //
       
   344 HBufC* CHgContextUtilityImpl::GetContextL( const TDesC& aContextSource,
       
   345         const TDesC& aContextType )
       
   346     {
       
   347     HBufC* ret = 0;
       
   348     if ( CFReady() )
       
   349         {
       
   350         CCFContextQuery* query = CCFContextQuery::NewLC();
       
   351         query->SetSourceL( aContextSource );
       
   352         query->SetTypeL( aContextType );
       
   353         RContextObjectArray result;
       
   354         TInt err = iCFClient->RequestContext( *query, result );
       
   355         if ( err == KErrNone && result.Count() )
       
   356             {
       
   357             ret = result[0]->Value().Alloc();
       
   358             }
       
   359         result.ResetAndDestroy();
       
   360         CleanupStack::PopAndDestroy( query );
       
   361         }
       
   362     return ret;
       
   363     }
       
   364 
       
   365 // -----------------------------------------------------------------------------
       
   366 // CHgContextUtilityImpl::GetContextL
       
   367 // -----------------------------------------------------------------------------
       
   368 //
       
   369 HBufC* CHgContextUtilityImpl::GetContextL( const TDesC& aContextType )
       
   370     {
       
   371     return GetContextL( KHgCFSource, aContextType );
       
   372     }
       
   373 
       
   374 // -----------------------------------------------------------------------------
       
   375 // CHgContextUtilityImpl::PublishContextDelayedL
       
   376 // -----------------------------------------------------------------------------
       
   377 //
       
   378 void CHgContextUtilityImpl::PublishContextDelayedL( const TDesC& aContextType,
       
   379         const TDesC& aContextData, TTimeIntervalMicroSeconds32 aDelay )
       
   380     {
       
   381     Cancel();
       
   382     delete iPendingContextType; iPendingContextType = 0;
       
   383     iPendingContextType = aContextType.AllocL();
       
   384     delete iPendingContextData; iPendingContextData = 0;
       
   385     iPendingContextData = aContextData.AllocL();
       
   386     delete iPendingContextDataArray; iPendingContextDataArray = 0;
       
   387     After( aDelay );
       
   388     }
       
   389 
       
   390 // -----------------------------------------------------------------------------
       
   391 // CHgContextUtilityImpl::PublishContextDelayedL
       
   392 // -----------------------------------------------------------------------------
       
   393 //
       
   394 void CHgContextUtilityImpl::PublishContextDelayedL( const TDesC& aContextType,
       
   395         const MDesCArray& aContextData, TTimeIntervalMicroSeconds32 aDelay )
       
   396     {
       
   397     Cancel();
       
   398     delete iPendingContextType; iPendingContextType = 0;
       
   399     iPendingContextType = aContextType.AllocL();
       
   400     delete iPendingContextData; iPendingContextData = 0;
       
   401     if ( iPendingContextDataArray )
       
   402         {
       
   403         iPendingContextDataArray->Reset();
       
   404         }
       
   405     else
       
   406         {
       
   407         iPendingContextDataArray = new ( ELeave ) CDesC16ArrayFlat( KArrayGranularity );
       
   408         }
       
   409     for ( TInt i = 0, ie = aContextData.MdcaCount(); i != ie; ++i )
       
   410         {
       
   411         iPendingContextDataArray->AppendL( aContextData.MdcaPoint( i ) );
       
   412         }
       
   413     After( aDelay );
       
   414     }
       
   415 
       
   416 // -----------------------------------------------------------------------------
       
   417 // CHgContextUtilityImpl::RunL
       
   418 // -----------------------------------------------------------------------------
       
   419 //
       
   420 void CHgContextUtilityImpl::RunL()
       
   421     {
       
   422     if ( iPendingContextType )
       
   423         {
       
   424         if ( iPendingContextData )
       
   425             {
       
   426             PublishContextL( *iPendingContextType, *iPendingContextData );
       
   427             }
       
   428         else if ( iPendingContextDataArray )
       
   429             {
       
   430             PublishContextL( *iPendingContextType, *iPendingContextDataArray );
       
   431             }
       
   432         }
       
   433     }
       
   434 
       
   435 // -----------------------------------------------------------------------------
       
   436 // CHgContextUtilityImpl::RunError
       
   437 // -----------------------------------------------------------------------------
       
   438 //
       
   439 TInt CHgContextUtilityImpl::RunError( TInt /*aError*/ )
       
   440     {
       
   441     return KErrNone;
       
   442     }
       
   443 
       
   444 // empty implementations for cfw
       
   445 
       
   446 // -----------------------------------------------------------------------------
       
   447 // CHgContextUtilityImpl::ContextIndicationL
       
   448 // -----------------------------------------------------------------------------
       
   449 //
       
   450 void CHgContextUtilityImpl::ContextIndicationL(
       
   451 		const CCFContextIndication& /*aChangedContext*/ )
       
   452 	{
       
   453 	// empty
       
   454 	}
       
   455 
       
   456 // -----------------------------------------------------------------------------
       
   457 // CHgContextUtilityImpl::ActionIndicationL
       
   458 // -----------------------------------------------------------------------------
       
   459 //
       
   460 void CHgContextUtilityImpl::ActionIndicationL(
       
   461 		const CCFActionIndication& /*aActionToExecute*/ )
       
   462 	{
       
   463 	// empty
       
   464 	}
       
   465 
       
   466 // -----------------------------------------------------------------------------
       
   467 // CHgContextUtilityImpl::HandleContextFrameworkError
       
   468 // -----------------------------------------------------------------------------
       
   469 //
       
   470 void CHgContextUtilityImpl::HandleContextFrameworkError( TCFError /*aError*/,
       
   471 	    const TDesC& /*aSource*/,
       
   472 	    const TDesC& /*aType*/ )
       
   473 	{
       
   474 	// empty
       
   475 	}
       
   476 
       
   477 // -----------------------------------------------------------------------------
       
   478 // CHgContextUtilityImpl::Extension
       
   479 // -----------------------------------------------------------------------------
       
   480 //
       
   481 TAny* CHgContextUtilityImpl::Extension( const TUid& /*aExtensionUid*/ ) const
       
   482 	{
       
   483 	return 0;
       
   484 	}
       
   485 
       
   486 // -----------------------------------------------------------------------------
       
   487 // CHgContextUtilityImpl::MakeLinkPublishableLC
       
   488 // -----------------------------------------------------------------------------
       
   489 //
       
   490 HBufC* CHgContextUtilityImpl::MakeLinkPublishableLC(
       
   491         const MVPbkContactLink& aLink )
       
   492     {
       
   493     HBufC* ret = 0;
       
   494     // serialize the link and place it into a 16-bit descriptor
       
   495     // prefixed with one special mark character
       
   496     const MVPbkStreamable* strm = aLink.Streamable();
       
   497     User::LeaveIfNull(strm);
       
   498     CBufFlat* buf = CBufFlat::NewL( KBufGranularity );
       
   499     CleanupStack::PushL( buf );
       
   500     RBufWriteStream ws;
       
   501     CleanupClosePushL( ws );
       
   502     ws.Open( *buf );
       
   503     strm->ExternalizeL( ws );
       
   504     CleanupStack::PopAndDestroy( &ws );
       
   505     TPtr8 p( buf->Ptr( 0 ) );
       
   506     ret = HBufC::NewLC( p.Length() + 1 );
       
   507     TPtr des( ret->Des() );
       
   508     des.Copy( p );
       
   509     _LIT( KTemp, " " );
       
   510     des.Insert( 0, KTemp );
       
   511     des[0] = KHgCFValueLinkMarker; // codescanner::accessArrayElementWithoutCheck2
       
   512     CleanupStack::Pop( ret );
       
   513     CleanupStack::PopAndDestroy( buf );
       
   514     CleanupStack::PushL( ret );
       
   515     return ret;
       
   516     }
       
   517 
       
   518 // -----------------------------------------------------------------------------
       
   519 // CHgContextUtilityImpl::PublishContactContextL
       
   520 // -----------------------------------------------------------------------------
       
   521 //
       
   522 void CHgContextUtilityImpl::PublishContactContextL(
       
   523         const MVPbkStoreContact& aContact,
       
   524         const TTimeIntervalMicroSeconds32& aDelay )
       
   525     {
       
   526     MVPbkContactLink* link = aContact.CreateLinkLC();
       
   527     if ( link )
       
   528         {
       
   529         HBufC* pubstr = MakeLinkPublishableLC( *link );
       
   530         PublishContactContextL( *pubstr, aDelay );
       
   531         CleanupStack::PopAndDestroy( pubstr );
       
   532         }
       
   533     CleanupStack::PopAndDestroy( );//link
       
   534     }
       
   535 
       
   536 // -----------------------------------------------------------------------------
       
   537 // CHgContextUtilityImpl::PublishContactContextL
       
   538 // -----------------------------------------------------------------------------
       
   539 //
       
   540 void CHgContextUtilityImpl::PublishContactContextL(
       
   541         const MVPbkContactLink& aContactLink,
       
   542         const TTimeIntervalMicroSeconds32& aDelay )
       
   543     {
       
   544     HBufC* pubstr = MakeLinkPublishableLC( aContactLink );
       
   545     PublishContactContextL( *pubstr, aDelay );
       
   546     CleanupStack::PopAndDestroy( pubstr );
       
   547     }
       
   548 
       
   549 // -----------------------------------------------------------------------------
       
   550 // CHgContextUtilityImpl::PublishContactContextL
       
   551 // -----------------------------------------------------------------------------
       
   552 //
       
   553 void CHgContextUtilityImpl::PublishContactContextL(
       
   554         const TDesC& aContactName,
       
   555         const TTimeIntervalMicroSeconds32& aDelay )
       
   556     {
       
   557     if ( !aDelay.Int() )
       
   558         {
       
   559         PublishContextL( KHgCFTypeContact, aContactName );
       
   560         }
       
   561     else
       
   562         {
       
   563         PublishContextDelayedL( KHgCFTypeContact, aContactName, aDelay );
       
   564         }
       
   565     }
       
   566 
       
   567 // -----------------------------------------------------------------------------
       
   568 // CHgContextUtilityImpl::PublishContactContextL
       
   569 // -----------------------------------------------------------------------------
       
   570 //
       
   571 void CHgContextUtilityImpl::PublishContactContextL(
       
   572         const RPointerArray<MVPbkStoreContact>& aContacts,
       
   573         const TTimeIntervalMicroSeconds32& aDelay )
       
   574     {
       
   575     CDesCArray* arr = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
       
   576     CleanupStack::PushL( arr );
       
   577     for ( TInt i = 0, ie = aContacts.Count(); i != ie; ++i )
       
   578         {
       
   579         MVPbkContactLink* link = aContacts[i]->CreateLinkLC();
       
   580         if ( link )
       
   581             {
       
   582             HBufC* pubstr = MakeLinkPublishableLC( *link );
       
   583             arr->AppendL( *pubstr );
       
   584             CleanupStack::PopAndDestroy( pubstr );
       
   585             }
       
   586         CleanupStack::PopAndDestroy( );//link
       
   587         }
       
   588     PublishContactContextL( *arr, aDelay );
       
   589     CleanupStack::PopAndDestroy( arr );
       
   590     }
       
   591 
       
   592 // -----------------------------------------------------------------------------
       
   593 // CHgContextUtilityImpl::PublishContactContextL
       
   594 // -----------------------------------------------------------------------------
       
   595 //
       
   596 void CHgContextUtilityImpl::PublishContactContextL(
       
   597         const CVPbkContactLinkArray& aContactLinks,
       
   598         const TTimeIntervalMicroSeconds32& aDelay )
       
   599     {
       
   600     CDesCArray* arr = new ( ELeave ) CDesCArrayFlat( KArrayGranularity );
       
   601     CleanupStack::PushL( arr );
       
   602     for ( TInt i = 0, ie = aContactLinks.Count(); i != ie; ++i )
       
   603         {
       
   604         HBufC* pubstr = MakeLinkPublishableLC( aContactLinks.At( i ) );
       
   605         arr->AppendL( *pubstr );
       
   606         CleanupStack::PopAndDestroy( pubstr );
       
   607         }
       
   608     PublishContactContextL( *arr, aDelay );
       
   609     CleanupStack::PopAndDestroy( arr );
       
   610     }
       
   611 
       
   612 // -----------------------------------------------------------------------------
       
   613 // CHgContextUtilityImpl::PublishContactContextL
       
   614 // -----------------------------------------------------------------------------
       
   615 //
       
   616 void CHgContextUtilityImpl::PublishContactContextL(
       
   617         const MDesCArray& aContactNames,
       
   618         const TTimeIntervalMicroSeconds32& aDelay )
       
   619     {
       
   620     if ( !aDelay.Int() )
       
   621         {
       
   622         PublishContextL( KHgCFTypeContact, aContactNames );
       
   623         }
       
   624     else
       
   625         {
       
   626         PublishContextDelayedL( KHgCFTypeContact, aContactNames, aDelay );
       
   627         }
       
   628     }
       
   629 
       
   630 // -----------------------------------------------------------------------------
       
   631 // CHgContextUtilityImpl::PublishTextContextL
       
   632 // -----------------------------------------------------------------------------
       
   633 //
       
   634 void CHgContextUtilityImpl::PublishTextContextL( const TDesC& aText,
       
   635         const TTimeIntervalMicroSeconds32& aDelay )
       
   636     {
       
   637     if ( !aDelay.Int() )
       
   638         {
       
   639         PublishContextL( KHgCFTypeText, aText );
       
   640         }
       
   641     else
       
   642         {
       
   643         PublishContextDelayedL( KHgCFTypeText, aText, aDelay );
       
   644         }
       
   645     }
       
   646 
       
   647 // -----------------------------------------------------------------------------
       
   648 // CHgContextUtilityImpl::PublishUrlContextL
       
   649 // -----------------------------------------------------------------------------
       
   650 //   
       
   651 void CHgContextUtilityImpl::PublishUrlContextL( const TDesC& aUrl,
       
   652         const TTimeIntervalMicroSeconds32& aDelay )
       
   653     {
       
   654     if ( !aDelay.Int() )
       
   655         {
       
   656         PublishContextL( KHgCFTypeUrl, aUrl );
       
   657         }
       
   658     else
       
   659         {
       
   660         PublishContextDelayedL( KHgCFTypeUrl, aUrl, aDelay );
       
   661         }
       
   662     }
       
   663 
       
   664 // -----------------------------------------------------------------------------
       
   665 // CHgContextUtilityImpl::PublishTimeContextL
       
   666 // -----------------------------------------------------------------------------
       
   667 //
       
   668 void CHgContextUtilityImpl::PublishTimeContextL( const TTime& aTime,
       
   669         const TTimeIntervalMicroSeconds32& aDelay )
       
   670     {
       
   671     // YYYYMMDD:HHMMSS.MMMMMM
       
   672     const TInt KDateTimeLength = 22;
       
   673     const TInt KYearLength = 4;
       
   674     const TInt KMonthLength = 2;
       
   675     const TInt KDayLength = 2;
       
   676     _LIT( KTimeZero, ":010101.000000");
       
   677 
       
   678     TDateTime dt = aTime.DateTime();
       
   679     TBuf<KDateTimeLength> buf;
       
   680     buf.AppendNumFixedWidth( dt.Year(), EDecimal, KYearLength );
       
   681     buf.AppendNumFixedWidth( dt.Month(), EDecimal, KMonthLength );
       
   682     buf.AppendNumFixedWidth( dt.Day(), EDecimal, KDayLength );
       
   683     buf.Append( KTimeZero );
       
   684     if ( !aDelay.Int() )
       
   685         {
       
   686         PublishContextL( KHgCFTypeActiveDate, buf );
       
   687         }
       
   688     else
       
   689         {
       
   690         PublishContextDelayedL( KHgCFTypeActiveDate, buf, aDelay );
       
   691         }
       
   692     }
       
   693 
       
   694 // -----------------------------------------------------------------------------
       
   695 // CHgContextUtilityImpl::PublishPhotoContextL
       
   696 // -----------------------------------------------------------------------------
       
   697 //
       
   698 void CHgContextUtilityImpl::PublishPhotoContextL(
       
   699         const TDesC& aFilename,
       
   700         const TTimeIntervalMicroSeconds32& aDelay )
       
   701     {
       
   702     if ( !aDelay.Int() )
       
   703         {
       
   704         PublishContextL( KHgCFTypePhoto, aFilename );
       
   705         }
       
   706     else
       
   707         {
       
   708         PublishContextDelayedL( KHgCFTypePhoto, aFilename, aDelay );
       
   709         }
       
   710     }
       
   711 
       
   712 // -----------------------------------------------------------------------------
       
   713 // CHgContextUtilityImpl::PublishPhotoContextL
       
   714 // -----------------------------------------------------------------------------
       
   715 //
       
   716 void CHgContextUtilityImpl::PublishPhotoContextL(
       
   717         TItemId aMdeItemId,
       
   718         CMdESession& aMdeSession,
       
   719         const TTimeIntervalMicroSeconds32& aDelay )
       
   720     {
       
   721     CMdEObject* obj = aMdeSession.GetObjectL( aMdeItemId );
       
   722     if ( obj )
       
   723         {
       
   724         CleanupStack::PushL( obj );
       
   725         PublishPhotoContextL( obj->Uri(), aDelay );
       
   726         CleanupStack::PopAndDestroy( obj );
       
   727         }
       
   728     else
       
   729         {
       
   730         User::Leave( KErrNotFound );
       
   731         }
       
   732     }
       
   733 
       
   734 // -----------------------------------------------------------------------------
       
   735 // CHgContextUtilityImpl::PublishTvContextL
       
   736 // -----------------------------------------------------------------------------
       
   737 //
       
   738 void CHgContextUtilityImpl::PublishTvContextL( const TDesC& aChannelName,
       
   739         const TDesC& aProgramName, const TDesC& aProgramDescription,
       
   740         const TDesC& aGenre )
       
   741     {
       
   742     TPtrC channelName( aChannelName.Length() ? aChannelName
       
   743         : KHgCFValueUnknownInfo );
       
   744     TPtrC programName( aProgramName.Length() ? aProgramName
       
   745         : KHgCFValueUnknownInfo );
       
   746     TPtrC programDesc( aProgramDescription.Length() ? aProgramDescription
       
   747         : KHgCFValueUnknownInfo );
       
   748     TPtrC programGenre( aGenre.Length() ? aGenre : KHgCFValueUnknownInfo );
       
   749 
       
   750     // Publish description/genre first because it is unlikely to have those
       
   751     // in rules so their content will be available for sure when an action
       
   752     // is triggered.
       
   753     PublishContextL( KHgCFTypeTvProgramDesc, programDesc );
       
   754     PublishContextL( KHgCFTypeTvProgramGenre, programGenre );
       
   755     PublishContextL( KHgCFTypeTvChannelName, channelName );
       
   756     PublishContextL( KHgCFTypeTvProgramName, programName );
       
   757     }
       
   758 
       
   759 // -----------------------------------------------------------------------------
       
   760 // CHgContextUtilityImpl::PublishServiceIdL
       
   761 // -----------------------------------------------------------------------------
       
   762 //
       
   763 void CHgContextUtilityImpl::PublishServiceIdL( const TDesC& aServiceId,
       
   764         const TDesC& aAccountId,
       
   765         const TTimeIntervalMicroSeconds32& aDelay )
       
   766     {
       
   767     HBufC* combinedIdBuf = HBufC::NewLC( aServiceId.Length()
       
   768         + aAccountId.Length() + 1 );
       
   769     TPtr combinedId( combinedIdBuf->Des() );
       
   770     _LIT( KCombinedFormat, "%S:%S" );
       
   771     combinedId.Format( KCombinedFormat, &aServiceId, &aAccountId );
       
   772     PublishContactContextL( combinedId, aDelay );
       
   773     CleanupStack::PopAndDestroy( combinedIdBuf );
       
   774     }
       
   775 
       
   776 // -----------------------------------------------------------------------------
       
   777 // CHgContextUtilityImpl::RePublishWhenFgL
       
   778 // -----------------------------------------------------------------------------
       
   779 //
       
   780 void CHgContextUtilityImpl::RePublishWhenFgL( TBool aEnable )
       
   781     {
       
   782     if ( iEnv )
       
   783         {
       
   784         if ( iFgWatchEnabled )
       
   785             {
       
   786             iEnv->RemoveForegroundObserver( *this );
       
   787             }
       
   788         iFgWatchEnabled = aEnable;
       
   789         if ( iFgWatchEnabled )
       
   790             {
       
   791             iEnv->AddForegroundObserverL( *this );
       
   792             }
       
   793         }
       
   794     }
       
   795 
       
   796 // callbacks from CCoeEnv
       
   797 
       
   798 // -----------------------------------------------------------------------------
       
   799 // CHgContextUtilityImpl::HandleGainingForeground
       
   800 // -----------------------------------------------------------------------------
       
   801 //
       
   802 void CHgContextUtilityImpl::HandleGainingForeground()
       
   803     {
       
   804     if ( iLastContextType && iLastContextData )
       
   805         {
       
   806         TRAP_IGNORE( PublishContextL( *iLastContextType, *iLastContextData ) );
       
   807         }
       
   808     }
       
   809 
       
   810 // -----------------------------------------------------------------------------
       
   811 // CHgContextUtilityImpl::HandleLosingForeground
       
   812 // -----------------------------------------------------------------------------
       
   813 //
       
   814 void CHgContextUtilityImpl::HandleLosingForeground()
       
   815     {
       
   816     // nothing to do here
       
   817     }
       
   818 
       
   819 // -----------------------------------------------------------------------------
       
   820 // CHgContextUtilityImpl::IsForeground
       
   821 // -----------------------------------------------------------------------------
       
   822 //
       
   823 TBool CHgContextUtilityImpl::IsForeground()
       
   824     {
       
   825     if ( iEnv )
       
   826         {
       
   827         TInt rootWgId = iEnv->RootWin().WindowGroupId();
       
   828         TInt focusWgId = iEnv->WsSession().GetFocusWindowGroup();
       
   829         return rootWgId == focusWgId;
       
   830         }
       
   831     else
       
   832         {
       
   833         return ETrue;
       
   834         }
       
   835     }
       
   836 
       
   837 // -----------------------------------------------------------------------------
       
   838 // CHgContextUtilityImpl::AllowedToPublish
       
   839 // -----------------------------------------------------------------------------
       
   840 //
       
   841 TBool CHgContextUtilityImpl::AllowedToPublish()
       
   842     {
       
   843     TBool result = !iEnv || iAllowPublishFromBackground || IsForeground();
       
   844     RDebug::Printf( "[hgctxutil] AllowedToPublish = %d", result );
       
   845     return result;
       
   846     }
       
   847 
       
   848 // -----------------------------------------------------------------------------
       
   849 // CHgContextUtilityImpl::AllowPublishFromBackground
       
   850 // -----------------------------------------------------------------------------
       
   851 //
       
   852 void CHgContextUtilityImpl::AllowPublishFromBackground( TBool aAllow )
       
   853     {
       
   854     iAllowPublishFromBackground = aAllow;
       
   855     }
       
   856 
       
   857 // -----------------------------------------------------------------------------
       
   858 // CHgContextUtilityImpl::AddMusicContextInfoL
       
   859 // -----------------------------------------------------------------------------
       
   860 //
       
   861 void CHgContextUtilityImpl::AddMusicContextInfoL( 
       
   862     const TDesC& aKey, const TDesC& aData )
       
   863     {   
       
   864     // Key needs to be provided and also it shouldn't exist in the table.
       
   865     // Latter case is simple safe measure, as RPtrHasMap won't delete existing
       
   866     // objects in InsertL, so adding same key twice would cause memory leak.
       
   867     // The use case of adding same key twice is not 'real world' case, so 
       
   868     // this method can simply leave, when same key is offered again.
       
   869     __ASSERT_ALWAYS( aKey.Length(), User::Leave( KErrNotFound ) );
       
   870     __ASSERT_ALWAYS( 
       
   871         !iMusicContextInfo.Find( aKey ), User::Leave( KErrAlreadyExists ) );
       
   872     
       
   873     // Hash table needs pointers and it should own the pointers, so allocate
       
   874     // key and data, and add them to table. In case the data is empty, add
       
   875     // unknown information, since some data needs to be in the action field.
       
   876     HBufC* key = aKey.AllocLC();
       
   877     HBufC* data = aData.Length() ? 
       
   878         aData.AllocLC() : KHgCFValueUnknownInfo().AllocLC();
       
   879     iMusicContextInfo.InsertL( key, data );
       
   880     CleanupStack::Pop( 2, key );
       
   881     }
       
   882 
       
   883 // -----------------------------------------------------------------------------
       
   884 // CHgContextUtilityImpl::PublishMusicContextL
       
   885 // -----------------------------------------------------------------------------
       
   886 //
       
   887 void CHgContextUtilityImpl::PublishMusicContextL( 
       
   888     const TTimeIntervalMicroSeconds32& aDelay )
       
   889     {
       
   890     // If nothing has been done, just leave. No point of publishing entirely
       
   891     // empty music context.
       
   892     __ASSERT_ALWAYS( iMusicContextInfo.Count(), User::Leave( KErrNotReady ) );    
       
   893     
       
   894     // Before publishing anything, make sure all keys contain at least some
       
   895     // data.
       
   896     VerifyAndPublishMusicContextL( KHgCFTypeMusicState, aDelay );
       
   897     VerifyAndPublishMusicContextL( KHgCFTypeMusicArtist, aDelay );
       
   898     VerifyAndPublishMusicContextL( KHgCFTypeMusicTitle, aDelay );
       
   899     VerifyAndPublishMusicContextL( KHgCFTypeMusicAlbum, aDelay );
       
   900     VerifyAndPublishMusicContextL( KHgCFTypeMusicAlbumArt, aDelay );
       
   901     VerifyAndPublishMusicContextL( KHgCFTypeMusicUri, aDelay );
       
   902     VerifyAndPublishMusicContextL( KHgCFTypeMusicGenre, aDelay );
       
   903     VerifyAndPublishMusicContextL( KHgCFTypeMusicType, aDelay );
       
   904     
       
   905     // Clear all data from hash table, so new music context can be published.
       
   906     iMusicContextInfo.ResetAndDestroy();
       
   907     }
       
   908 
       
   909 // -----------------------------------------------------------------------------
       
   910 // CHgContextUtilityImpl::VerifyAndPublishMusicContextL
       
   911 // -----------------------------------------------------------------------------
       
   912 //
       
   913 void CHgContextUtilityImpl::VerifyAndPublishMusicContextL( 
       
   914     const TDesC& aKey,
       
   915     const TTimeIntervalMicroSeconds32& aDelay )
       
   916     {
       
   917     TDesC* data = iMusicContextInfo.Find( aKey );
       
   918     if ( !data )
       
   919         {
       
   920         // Key didn't contain any data, just create the key with empty info.
       
   921         AddMusicContextInfoL( aKey, KNullDesC );
       
   922         data = iMusicContextInfo.Find( aKey );
       
   923         }
       
   924     
       
   925     PublishContextL( aKey, *data, aDelay );
       
   926     }
       
   927 
       
   928 // -----------------------------------------------------------------------------
       
   929 // CHgContextUtilityImpl::PublishContextL
       
   930 // -----------------------------------------------------------------------------
       
   931 //
       
   932 void CHgContextUtilityImpl::PublishContextL(
       
   933     const TDesC & aContextType, 
       
   934     const TDesC & aContextData, 
       
   935     const TTimeIntervalMicroSeconds32& aDelay )
       
   936     {
       
   937     if ( !aDelay.Int() )
       
   938         {
       
   939         PublishContextL( aContextType, aContextData );
       
   940         }
       
   941     else
       
   942         {
       
   943         PublishContextDelayedL( aContextType, aContextData, aDelay );
       
   944         }
       
   945     }
       
   946 
       
   947 // -----------------------------------------------------------------------------
       
   948 // CHgContextUtilityImpl::PublishRadioContextL
       
   949 // -----------------------------------------------------------------------------
       
   950 //
       
   951 void CHgContextUtilityImpl::PublishRadioContextL( 
       
   952         const TDesC& aRadioName,
       
   953         const TDesC& aRadioUrl,
       
   954         const TDesC& aRadioFrequency,
       
   955         const TDesC& aRadioRDSPI )
       
   956     {
       
   957     TPtrC radioName( aRadioName.Length() ? aRadioName
       
   958         : KHgCFValueUnknownInfo );
       
   959     TPtrC radioUrl( aRadioUrl.Length() ? aRadioUrl
       
   960         : KHgCFValueUnknownInfo );
       
   961     TPtrC radioFrequency( aRadioFrequency.Length() ? aRadioFrequency
       
   962         : KHgCFValueUnknownInfo );
       
   963     TPtrC radioRDSPI( aRadioRDSPI.Length() ? aRadioRDSPI
       
   964         : KHgCFValueUnknownInfo );
       
   965 
       
   966     PublishContextL( KHgCFTypeMusicRadioRDSPI, radioRDSPI );
       
   967     PublishContextL( KHgCFTypeMusicRadioFrequency, radioFrequency );
       
   968     PublishContextL( KHgCFTypeMusicRadioUrl, radioUrl );
       
   969     PublishContextL( KHgCFTypeMusicRadioName, radioName );
       
   970     }
       
   971 
       
   972 // end of file