--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/omadrm/drmengine/server/src/drmconsume.cpp Thu Dec 17 08:52:27 2009 +0200
@@ -0,0 +1,1138 @@
+/*
+* Copyright (c) 2005 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Implementation of the class CDRMConsume.
+*
+*/
+
+
+// INCLUDE FILES
+#include "drmconsume.h"
+#include "drmenginetypedefs.h"
+#include "drmrightsdb.h"
+#include "drmrightsserver.h"
+#include "drmdbsession.h"
+#include "drmlog.h"
+#include "drmeventmodify.h"
+#include "drmnotifier.h"
+#ifdef RD_DRM_METERING
+#include "drmmeteringdb.h"
+#include "drmmeteringdbdata.h"
+#include "roapstorageclient.h"
+#include "drmricontext.h"
+#endif
+
+// EXTERNAL DATA STRUCTURES
+// EXTERNAL FUNCTION PROTOTYPES
+// CONSTANTS
+// MACROS
+
+#define NOTIFIER static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+ iSession.Server() ) )->Notifier()
+
+#define DB static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+ iSession.Server() ) )->Database()
+
+#define SECURETIME( a ) static_cast< CDRMRightsServer* >\
+ ( const_cast< CServer2* >( \
+ iSession.Server() ) )->GetSecureTime( a )
+
+#define SERVER static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+ iSession.Server() ) )
+
+#ifdef RD_DRM_METERING
+#define METERINGDB static_cast< CDRMRightsServer* >( const_cast< CServer2* >( \
+ iSession.Server() ) )->MeteringDatabase()
+#endif
+
+#define SETBIT( a, b ) ( a ) |= ( b )
+#define CLRBIT( a, b ) ( a ) &= ~( 0xff & b )
+#define ISSET( a, b ) ( ( a ) & ( b ) )
+
+// LOCAL CONSTANTS AND MACROS
+// Keeps track about modified permissions for UpdateDBL().
+//static const TUint8 KConsumeParentModified = 0x01;
+static const TUint8 KConsumeChildModified = 0x02;
+
+static const TUint8 KConsumeHasSecureTime = 0x08;
+
+// These keep track whether to decrease timed counters when consuming time
+// based stuff (iTimedCounts member). A used timed count bit is set to zero.
+// In the beginning all of these are set to one.
+//static const TUint8 KParentToplevelCount = 0x01;
+//static const TUint8 KParentPermCount = 0x02;
+static const TUint8 KChildToplevelCount = 0x04;
+static const TUint8 KChildPermCount = 0x08;
+
+static const TUint16 KConsumeDefaultTimer = 300; // 5mins
+
+// LOCAL FUNCTION PROTOTYPES
+static inline void PickSmaller( TTime& aFirst,
+ const TTime& aSecond );
+
+// ============================= LOCAL FUNCTIONS ==========================
+
+// ------------------------------------------------------------------------
+// PickSmaller (overloaded)
+//
+// Set the smaller one to aFirst
+// ------------------------------------------------------------------------
+//
+void PickSmaller( TTime& aFirst,
+ const TTime& aSecond )
+ {
+ if ( aSecond < aFirst )
+ {
+ aFirst = aSecond;
+ }
+ }
+
+// ------------------------------------------------------------------------
+// PickSmaller (overloaded)
+//
+// Set the smaller one to aFirst
+// ------------------------------------------------------------------------
+//
+void PickSmaller( TTimeIntervalSeconds& aFirst,
+ const TTimeIntervalSeconds& aSecond )
+ {
+ if ( aSecond < aFirst )
+ {
+ aFirst = aSecond;
+ }
+ }
+
+// ============================ MEMBER FUNCTIONS ==========================
+
+// ------------------------------------------------------------------------
+// CDRMConsume::NewLC
+// ------------------------------------------------------------------------
+//
+CDRMConsume* CDRMConsume::NewLC( CDRMDbSession& aSession,
+ const TDesC8& aURI,
+ const TDesC8* aParentId )
+ {
+ DRMLOG( _L( "CDRMConsume::NewLC" ) );
+ CDRMConsume* self = new( ELeave ) CDRMConsume( aSession );
+
+ CleanupStack::PushL( self );
+
+ self->ConstructL( aURI, aParentId );
+
+ DRMLOG( _L( "CDRMConsume::NewLC ok" ) );
+ return self;
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::~CDRMConsume
+// ------------------------------------------------------------------------
+//
+CDRMConsume::~CDRMConsume()
+ {
+ DRMLOG( _L( "CDRMConsume::~" ) );
+ TInt error( KErrNone );
+
+ if( IsActive() )
+ {
+ Cancel();
+ }
+ else
+ {
+ TRAP( error, DoCancelL() );
+ }
+ #ifdef RD_DRM_METERING
+ // Update metering count and metering accumulated time to the database.
+ TRAP( error, UpdateMeteringDbL() );
+ #endif
+ // ignore errors
+ //TRAP( error, UpdateDBL() );
+
+ delete iURI; iURI = NULL;
+ delete iParentId; iParentId = NULL;
+ delete iChild; iChild = NULL;
+ delete iCombined; iCombined = NULL;
+ DRMLOG( _L( "CDRMConsume::~ ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::CDRMConsume
+//
+// The internal state members iTimedCounts and iCounters are by default
+// set to 00001111b, and the appropriate bits are lowered when something
+// changes.
+// ------------------------------------------------------------------------
+//
+CDRMConsume::CDRMConsume( CDRMDbSession& aSession ):
+ CTimer( EPriorityHigh ),
+ iSession( aSession ),
+ iIntent( ContentAccess::EUnknown ),
+ iURI( NULL ),
+ iParentId( NULL ),
+ iTimedCounts( 0xf ),
+ iCounters( 0xf ),
+ iCountConstraintActive( EFalse ),
+ iExpired( EFalse ),
+ iCumulativeDelayTop( 0 ),
+ iCumulativeDelayChild( 0 ),
+ iTotalCumulativeTime( 0 ),
+ iUsingTimedCount( 0 )
+ {
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::ConstructL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ConstructL( const TDesC8& aURI,
+ const TDesC8* aParentId )
+ {
+ DRMLOG( _L( "CDRMConsume::ConstructL" ) );
+ CTimer::ConstructL();
+ iURI = aURI.AllocL();
+ if( aParentId )
+ {
+ iParentId = aParentId->AllocL();
+ }
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::HandleL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::HandleL( ContentAccess::TIntent aIntent )
+ {
+ DRMLOG( _L( "CDRMConsume::HandleL" ) );
+
+ TTime time;
+ TBool secure( SECURETIME( time ) );
+ InitializeL( aIntent, secure, time );
+
+ DRMLOG( _L( "CDRMConsume::HandleL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: Pause
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::Pause()
+ {
+ DRMLOG( _L( "CDRMConsume::Pause" ) );
+
+ Cancel();
+
+ DRMLOG( _L( "CDRMConsume::Pause ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: ContinueL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ContinueL()
+ {
+ DRMLOG( _L( "CDRMConsume::ContinueL" ) );
+
+ Cancel();
+
+ TInt error = KErrNone;
+ TUint32 reason = 0;
+
+ CDRMPermission* child = NULL;
+ HBufC8* parent = NULL;
+
+ // This got removed by Pause()
+ if( iCountConstraintActive )
+ {
+ SERVER->AddActiveCountConstraintL( *iURI );
+ DoContinueL();
+ return;
+ }
+
+ /* Fetch the RO again in order to manage a situation when another
+ instance has used the same RO (content has been consumed) while the
+ other instance has not been used (player is paused) but will be
+ used again (content consumption is to be continued). */
+ error = iSession.FindRightsObject( iIntent, *iURI, child, parent, reason );
+
+ /* Check if the RO found from the database matches with the one that was used
+ in the original consumption of the content. If the ROs match, use the
+ (possibly updated) one from the database. */
+ if ( !error && child && iChild &&
+ ( iChild->iUniqueID == child->iUniqueID ) &&
+ ( iChild->iOriginalInsertTime == child->iOriginalInsertTime ) )
+ {
+ if ( iParentId )
+ {
+ delete iParentId;
+ iParentId = parent;
+ }
+
+ delete iChild;
+ iChild = child;
+ }
+ else
+ {
+ /* The original RO was not found. Delete temporary objects and also
+ delete the iChild and iCombined because the RO is no longer valid and
+ need to be re-fetched using InitializeL method (in DoContinueL).
+ (in DoContinueL). */
+ if ( iChild )
+ {
+ delete iChild;
+ iChild = NULL;
+ }
+
+ if ( iCombined )
+ {
+ delete iCombined;
+ iCombined = NULL;
+ }
+
+ if ( child )
+ {
+ delete child;
+ child = NULL;
+ }
+ if ( parent )
+ {
+ delete parent;
+ parent = NULL;
+ }
+ }
+
+ DoContinueL();
+
+ //HandleL( iIntent );
+
+ DRMLOG( _L( "CDRMConsume::ContinueL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: Stop
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::Stop()
+ {
+ DRMLOG( _L( "CDRMConsume::Stop" ) );
+
+ Cancel();
+
+ DRMLOG( _L( "CDRMConsume::Stop ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: ActivateL
+//
+// Calculate the smallest end time based on interval, end time,
+// accumulated time & timed count.
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ActivateL( TBool aSecureTime,
+ const TTime& aTrustedTime )
+ {
+ DRMLOG( _L( "CDRMConsume::ActivateL" ) );
+
+ __ASSERT_DEBUG( iChild && iCombined, User::Invariant() );
+ TTime endTime( Time::MaxTTime() );
+ TTimeIntervalSeconds timed( KMaxTInt32 );
+ TBool timeUsed( EFalse );
+ TBool endTimeUsed( EFalse );
+
+ iCurrentDelay = 0;
+
+ if ( iCombined->iActiveConstraints & EConstraintTimedCounter )
+ {
+ // Take this, even if timed counts have been updated.
+ // This might cause unnecessary RunL's to be called, but it
+ // ensures both child & parent will be consumed when needed.
+ // If e.g. it would be checked that iTimedCounts == 0xf,
+ // either one (child or parent) might not get updated in case of
+ // "Child expired, but parent didn't -> find new child".
+ PickSmaller( timed, iCombined->iTimedInterval );
+ timeUsed = ETrue;
+ }
+
+ if ( iCombined->iActiveConstraints & EConstraintAccumulated )
+ {
+ PickSmaller( timed, iCombined->iAccumulatedTime );
+ timeUsed = ETrue;
+ }
+
+ if ( iCombined->iActiveConstraints & EConstraintInterval )
+ {
+ if ( iCombined->iIntervalStart != Time::NullTTime() )
+ {
+ endTime = iCombined->iIntervalStart;
+ endTime += iCombined->iInterval;
+ endTimeUsed = ETrue;
+ }
+ else
+ {
+ TInt64 tmp( iCombined->iInterval.Int() );
+
+ PickSmaller( timed, tmp );
+ timeUsed = ETrue;
+ }
+ }
+
+ if ( iCombined->iActiveConstraints & EConstraintEndTime )
+ {
+ PickSmaller( endTime, iCombined->iEndTime );
+ endTimeUsed = ETrue;
+ }
+
+ // Put the "smallest time" information to "endTime".
+ if ( timeUsed )
+ {
+ TTime current( aTrustedTime );
+
+ current += timed;
+
+ PickSmaller( endTime, current );
+ endTimeUsed = ETrue;
+ }
+
+ // Interval gets initialised immediately, and so do count constraints.
+ // Timed/accumulated won't: those are consumed after the
+ // interval if secure time exists.
+ Consume( ETrue, ETrue, EFalse, 0,
+ aSecureTime,
+ aTrustedTime );
+
+ // In case something was modified, update the db also.
+ UpdateDBL();
+
+ if ( endTimeUsed )
+ {
+ // Something exists.
+ TTimeIntervalSeconds secs( 0 );
+ TTime current( aTrustedTime );
+ TInt err( KErrNone );
+
+ // SecondsFrom returns an error if the difference is too great.
+ err = endTime.SecondsFrom( current, secs );
+ if ( err )
+ {
+ iCurrentDelay = KConsumeDefaultTimer;
+ }
+ else if ( secs.Int() < 0 )
+ {
+ iCurrentDelay = 0; // Already expired.
+ }
+ else if ( secs.Int() < KConsumeDefaultTimer )
+ {
+ iCurrentDelay = secs.Int();
+ }
+ else
+ {
+ iCurrentDelay = KConsumeDefaultTimer;
+ }
+
+ if ( !IsAdded() )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+ DRMLOG2( _L( "CDRMConsume::ActivateL: using interval %d" ),
+ ( TInt )iCurrentDelay );
+
+ // secs -> microsecs. The method sets the AO active.
+ After( TTimeIntervalMicroSeconds32( iCurrentDelay * 1000000 ) );
+
+ iTime = current;
+
+ // If we see timed things here, we also have secure time.
+ //SETBIT( iMask, KConsumeHasSecureTime );
+ }
+ else // For metering we always need to have this:
+ {
+ iCurrentDelay = KConsumeDefaultTimer;
+ iTime = aTrustedTime;
+
+ if ( !IsAdded() )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+ DRMLOG2( _L( "CDRMConsume::ActivateL: using interval %d" ),
+ ( TInt )iCurrentDelay );
+
+ // secs -> microsecs. The method sets the AO active.
+ After( TTimeIntervalMicroSeconds32( iCurrentDelay * 1000000 ) );
+ }
+
+ // If we see timed things here, we also have secure time.
+ if( aTrustedTime != Time::NullTTime())
+ {
+ SETBIT( iMask, KConsumeHasSecureTime );
+ }
+ DRMLOG( _L( "CDRMConsume::ActivateL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume:: Consume
+//
+// Consume child & parent. Whether to consume parent's explicit
+// usage permission: the information is returned earlier by
+// FindRightsObjectL.
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::Consume( TBool aUpdateCounter,
+ TBool aInitInterval,
+ TBool aUpdateTimedCount,
+ const TTimeIntervalSeconds& aElapsedTime,
+ TBool aSecureTime,
+ const TTime& aTrustedTime )
+ {
+ DRMLOG( _L( "CDRMConsume::Consume" ) );
+
+ __ASSERT_DEBUG( iChild && iCombined, User::Invariant() );
+
+ // Decrease timed counters & regular counters only once.
+ // In the beginning the bitmasks are both 0xF.
+ if ( iChild->TopLevelConstraint() )
+ {
+ if ( ConsumeConstraint( *( iChild->TopLevelConstraint() ),
+ ( aUpdateCounter &&
+ ISSET( iCounters, KChildToplevelCount ) ),
+ aInitInterval,
+ ( aUpdateTimedCount &&
+ ISSET( iTimedCounts,
+ KChildToplevelCount ) ),
+ aElapsedTime,
+ aSecureTime,
+ aTrustedTime,
+ iCumulativeDelayTop ) )
+ {
+ SETBIT( iMask, KConsumeChildModified );
+ if ( aUpdateTimedCount )
+ {
+ CLRBIT( iTimedCounts, KChildToplevelCount );
+ }
+ if ( aUpdateCounter )
+ {
+ CLRBIT( iCounters, KChildToplevelCount );
+ }
+ }
+ }
+
+ if ( ConsumeConstraint( *( iChild->ConstraintForIntent( iIntent ) ),
+ ( aUpdateCounter &&
+ ISSET( iCounters, KChildPermCount ) ),
+ aInitInterval,
+ ( aUpdateTimedCount &&
+ ISSET( iTimedCounts, KChildPermCount ) ),
+ aElapsedTime,
+ aSecureTime,
+ aTrustedTime,
+ iCumulativeDelayChild ) )
+ {
+ SETBIT( iMask, KConsumeChildModified );
+ if ( aUpdateTimedCount )
+ {
+ CLRBIT( iTimedCounts, KChildPermCount );
+ }
+ if ( aUpdateCounter )
+ {
+ CLRBIT( iCounters, KChildPermCount );
+ }
+ }
+
+ DRMLOG( _L( "CDRMConsume::Consume ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::RunL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::RunL()
+ {
+ DRMLOG2( _L( "CDRMConsume::RunL with %d" ), iStatus.Int() );
+
+ switch ( iStatus.Int() )
+ {
+ case KErrNone:
+ // Normal completition.
+
+ case KErrUnderflow:
+ // Time already passed.
+
+ case KErrAbort:
+ // System time changed ==> consume.
+ DoContinueL();
+ break;
+
+ default:
+ // Some other (real) error.
+ // Handled in RunError.
+ User::Leave( iStatus.Int() );
+ };
+
+ DRMLOG( _L( "CDRMConsume::RunL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::RunError
+// ------------------------------------------------------------------------
+//
+#if defined( _DEBUG ) || defined( _LOGGING )
+TInt CDRMConsume::RunError( TInt aError )
+#else
+TInt CDRMConsume::RunError( TInt /* aError */ )
+#endif
+ {
+ DRMLOG2( _L( "CDRMConsume::RunError: %d" ), aError );
+
+ Deque();
+
+ DRMLOG( _L( "CDRMConsume::RunError ok" ) );
+ return 0;
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::DoCancel
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::DoCancel()
+ {
+ DRMLOG( _L( "CDRMConsume::DoCancel" ) );
+
+ TInt error( KErrNone );
+ TRAP( error, DoCancelL() );
+
+ DRMLOG2( _L( "CDRMConsume::DoCancel: %d" ), error );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::DoCancelL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::DoCancelL()
+ {
+ DRMLOG( _L( "CDRMConsume::DoCancelL" ) );
+
+ if ( iCurrentDelay )
+ {
+ TTimeIntervalSeconds secs;
+ TTime trustedTime;
+ TBool secureTime;
+
+ CTimer::DoCancel();
+
+ secureTime = SECURETIME( trustedTime );
+ trustedTime.SecondsFrom( iTime, secs );
+
+ #ifdef RD_DRM_METERING
+ // Update total cumulative time for content metering purposes
+ iTotalCumulativeTime = iTotalCumulativeTime.Int() + secs.Int();
+ #endif
+
+ // If the top level timed counter has not been activated yet
+ // increment the counter
+ if( ISSET( iTimedCounts, KChildToplevelCount ) )
+ {
+ iCumulativeDelayTop = iCumulativeDelayTop.Int() + secs.Int();
+ }
+
+ // If the child timed counter has not been activated yet
+ // increment the counter
+ if( ISSET( iTimedCounts, KChildPermCount ) )
+ {
+ iCumulativeDelayChild = iCumulativeDelayChild.Int() + secs.Int();
+ }
+
+ // Always >= 0.
+ ConsumeTimedItemsL( secs,
+ secureTime,
+ trustedTime );
+ iCurrentDelay = 0;
+ }
+
+ UpdateDBL();
+
+ if ( SERVER->HasActiveCountConstraint( *iURI ) )
+ {
+ SERVER->RemoveActiveCountConstraint( *iURI );
+ }
+
+ DRMLOG( _L( "CDRMConsume::DoCancel ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::CombinePermissionsL
+//
+// Combine iChild's & iParent's top level constraints, and merge the usage
+// intention constraint (either one of them).
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::CombinePermissionsL()
+ {
+ DRMLOG( _L( "CDRMConsume::CombinePermissions" ) );
+
+ __ASSERT_DEBUG( iChild, User::Invariant() );
+
+ // Reset
+ delete iCombined; iCombined = NULL;
+ iCombined = CDRMConstraint::NewL();
+
+ if ( iChild->TopLevelConstraint() )
+ {
+ iCombined->Merge( *( iChild->TopLevelConstraint() ) );
+ }
+
+ iCombined->Merge( *( iChild->ConstraintForIntent( iIntent ) ) );
+
+ DRMLOG( _L( "CDRMConsume::CombinePermissions ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::UpdateDBL
+//
+// Update the DB if something was changed.
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::UpdateDBL()
+ {
+ DRMLOG( _L( "CDRMConsume::UpdateDBL" ) );
+ // __ASSERT_DEBUG( iChild, User::Invariant() );
+
+ CDRMEventModify* event = NULL;
+ TRequestStatus status;
+
+ if( ISSET( iMask, KConsumeChildModified ) )
+ {
+ event = CDRMEventModify::NewL();
+ }
+ CleanupStack::PushL( event );
+
+ if ( ISSET( iMask, KConsumeChildModified ) )
+ {
+ DRMLOG( _L( "CDRMConsume: commiting child to DB" ) );
+
+ if( iParentId )
+ {
+ DB.UpdateDBEntryL( *iParentId, *iChild );
+ // Notify
+ event->SetContentIDL(*iParentId);
+ event->SetUniqueID(iChild->iUniqueID);
+ }
+ else
+ {
+ DB.UpdateDBEntryL( *iURI, *iChild );
+ // Notify
+ event->SetContentIDL(*iURI);
+ event->SetUniqueID(iChild->iUniqueID);
+ }
+
+ // Notify
+ event->SetContentIDL(*iURI);
+ event->SetUniqueID(iChild->iUniqueID);
+
+ NOTIFIER.SendEventL(*event,status);
+ User::WaitForRequest(status);
+
+ CLRBIT( iMask, KConsumeChildModified );
+ }
+
+ CleanupStack::PopAndDestroy();
+ DRMLOG( _L( "CDRMConsume::UpdateDBL ok" ) );
+ }
+// ------------------------------------------------------------------------
+// CDRMConsume::ConsumeConstraint
+//
+// Consume child & parent. Whether to consume parent's explicit
+// usage permission: the information is returned earlier by
+// FindRightsObjectL.
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::ConsumeConstraint( CDRMConstraint& aConstraint,
+ TBool aUpdateCounter,
+ TBool aInitInterval,
+ TBool aUpdateTimedCount,
+ const TTimeIntervalSeconds& aElapsedTime,
+ TBool aSecureTime,
+ const TTime& aTrustedTime,
+ TTimeIntervalSeconds& aCumulativeTime )
+ {
+ DRMLOG( _L( "CDRMConsume::ConsumeConstraints" ) );
+
+ TBool res( EFalse );
+
+ if ( aUpdateCounter &&
+ ( aConstraint.iActiveConstraints & EConstraintCounter ) )
+ {
+ --( aConstraint.iCounter);
+ res = ETrue;
+ iCountConstraintActive = ETrue;
+ TRAP_IGNORE( SERVER->AddActiveCountConstraintL( *iURI ) );
+ }
+
+ if ( aInitInterval &&
+ ( aConstraint.iActiveConstraints & EConstraintInterval ) &&
+ aSecureTime &&
+ aConstraint.iIntervalStart == Time::NullTTime() )
+ {
+ aConstraint.iIntervalStart = aTrustedTime;
+ res = ETrue;
+ }
+
+ /* change to timed counter, we don't check the latest time, we check the
+ cumulated time */
+
+ if ( aUpdateTimedCount &&
+ ( aConstraint.iActiveConstraints & EConstraintTimedCounter &&
+ ( aCumulativeTime >= aConstraint.iTimedInterval ||
+ aElapsedTime >= aConstraint.iTimedInterval ) ) )
+ {
+ --( aConstraint.iTimedCounter );
+ res = ETrue;
+ iCountConstraintActive = ETrue;
+ TRAP_IGNORE( SERVER->AddActiveCountConstraintL( *iURI ) );
+ aCumulativeTime = TTimeIntervalSeconds( 0 );
+ }
+ else if ( aUpdateTimedCount &&
+ ( aConstraint.iActiveConstraints & EConstraintTimedCounter ) )
+ {
+ iUsingTimedCount = ETrue;
+ }
+
+
+ if ( aElapsedTime.Int() != 0 &&
+ ( aConstraint.iActiveConstraints & EConstraintAccumulated ) )
+ {
+ __ASSERT_DEBUG( aElapsedTime.Int() > 0, User::Invariant() );
+
+ if ( aConstraint.iAccumulatedTime < aElapsedTime )
+ {
+ aConstraint.iAccumulatedTime = 0;
+ }
+ else
+ {
+ aConstraint.iAccumulatedTime = aConstraint.iAccumulatedTime.Int() -
+ aElapsedTime.Int();
+ }
+
+ res = ETrue;
+ }
+
+ if ( !iCountConstraintActive && aConstraint.Expired( aTrustedTime ) )
+ {
+ iExpired = ETrue;
+ }
+ else
+ {
+ iExpired = EFalse;
+ }
+
+ DRMLOG2(
+ _L( "CDRMConsume::ConsumeConstraints ok, returning %d" ),
+ ( TInt )res );
+
+ return res;
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::ConsumeTimedItemsL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::ConsumeTimedItemsL( TTimeIntervalSeconds aDelay,
+ TBool aSecureTime,
+ const TTime& aTrustedTime )
+ {
+ DRMLOG( _L( "CDRMConsume::ConsumeTimedItemsL" ) );
+
+ // Update accumulated constraints & timed count.
+ Consume( EFalse,
+ ETrue,
+ ETrue,
+ aDelay,
+ aSecureTime,
+ aTrustedTime );
+
+ DRMLOG( _L( "CDRMConsume::ConsumeTimedItems ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::DoContinueL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::DoContinueL()
+ {
+ DRMLOG( _L( "CDRMConsume::DoContinueL" ) );
+
+ TTime time;
+ TBool secureTime( EFalse );
+ secureTime = SECURETIME( time );
+
+ if ( !iChild || !iCombined )
+ {
+ InitializeL( iIntent, secureTime, time );
+ // User::Leave( KErrCANoRights );
+ return;
+ }
+
+ ConsumeTimedItemsL( iCurrentDelay, secureTime, time );
+ UpdateDBL();
+ iCurrentDelay = 0;
+
+ CombinePermissionsL();
+
+ // If the content has expired, find new permissions, unless the expired
+ // constraint was a timed count. In that case, the constraint
+ // did not really expire.
+ if ( SecurityLevelChanged( secureTime ) ||
+ ( iCombined->Expired( time ) &&
+ !SERVER->HasActiveCountConstraint( *iURI ) ) )
+ {
+ InitializeL( iIntent, secureTime, time );
+ }
+ else
+ {
+ ActivateL( secureTime, time );
+ }
+
+ DRMLOG( _L( "CDRMConsume::DoContinueL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::SecurityLevelChanged
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::SecurityLevelChanged( TBool aSecureTime ) const
+ {
+ DRMLOG( _L( "CDRMConsume::SecurityLevelChanged" ) );
+
+ if ( ( ISSET( iMask, KConsumeHasSecureTime ) && aSecureTime ) ||
+ !( ISSET( iMask, KConsumeHasSecureTime ) || aSecureTime ) )
+ {
+ return EFalse;
+ }
+
+ return ETrue;
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::InitializeL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::InitializeL( ContentAccess::TIntent aIntent,
+ TBool aSecureTime,
+ const TTime& aTrustedTime )
+ {
+ DRMLOG( _L( "CDRMConsume::InitializeL" ) );
+
+ // aIntent is either EPlay, EView, EExecute or EPrint.
+ // Store the old consumption information in case this is
+ // called in case of "ran out of permissions, find new ones"
+ CDRMPermission* child( iChild );
+ TUint8 timedCounts( iTimedCounts );
+ TUint8 counters( iCounters );
+ TUint32 reason = 0;
+
+ // Reset.
+ iTimedCounts = 0xf;
+ iCounters = 0xf;
+ iMask = 0x0;
+ iCurrentDelay = 0;
+
+ iExpired = ETrue;
+
+ delete iCombined; iCombined = NULL;
+
+ // Previous child & parent need to be stored in case the internal
+ // counter states need to be restored.
+ if ( child )
+ {
+ CleanupStack::PushL( child );
+ iChild = NULL;
+ }
+
+ // If the next call won't leave, we have permissions.
+ User::LeaveIfError( iSession.FindRightsObject( aIntent,
+ *iURI,
+ iChild,
+ iParentId,
+ reason ) );
+
+ User::LeaveIfError( iSession.VerifyCredentials( iURI, iChild, aIntent ) );
+
+ iExpired = EFalse;
+
+ // Check whether to restore the internal state.
+ if ( iIntent == aIntent )
+ {
+ if ( child &&
+ ( child->iUniqueID == iChild->iUniqueID ) )
+ {
+ DRMLOG( _L( "CDRMConsume: using the previous child" ) );
+
+ CLRBIT( iTimedCounts,
+ ( KChildToplevelCount | KChildPermCount ) & ~timedCounts );
+
+ CLRBIT( iCounters,
+ ( KChildToplevelCount | KChildPermCount ) & ~counters );
+ }
+ }
+
+ if ( child )
+ {
+ CleanupStack::PopAndDestroy();
+ }
+
+ iIntent = aIntent;
+
+ CombinePermissionsL();
+ ActivateL( aSecureTime, aTrustedTime );
+
+ DRMLOG( _L( "CDRMConsume::InitializeL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::CountConstraintActive
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::CountConstraintActive()
+ {
+ return iCountConstraintActive || SERVER->HasActiveCountConstraint( *iURI );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::IsExpired
+// ------------------------------------------------------------------------
+//
+TBool CDRMConsume::IsExpired()
+ {
+ return iExpired;
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::GetChild
+// ------------------------------------------------------------------------
+//
+CDRMPermission& CDRMConsume::GetChild()
+ {
+ return *iChild;
+ }
+
+#ifdef RD_DRM_METERING
+
+// ------------------------------------------------------------------------
+// CDRMConsume::UpdateMeteringDbL
+// ------------------------------------------------------------------------
+//
+void CDRMConsume::UpdateMeteringDbL()
+ {
+ DRMLOG( _L( "CDRMConsume::UpdateMeteringDbL" ) );
+ TTimeIntervalSeconds graceTime = 0;
+ CDRMConstraint* constraint = NULL;
+
+ if ( iChild )
+ {
+ constraint = iChild->ConstraintForIntent( iIntent );
+ if ( constraint && constraint->iDrmMeteringInfo )
+ {
+
+ graceTime = constraint->iDrmMeteringInfo->iGraceTime;
+
+ // Grace time exceeded, increase metering count and metering
+ // accumulated time
+ if ( iTotalCumulativeTime >= graceTime )
+ {
+ // Check Rights Issuer rights from Roap storage
+ if ( !CheckRiContextRightsL( iChild->iRiId ) )
+ {
+ return;
+ }
+
+ // Update database only if Rights Issuer Id is available
+ if ( ( iChild->iRiId.Length() > 0 ) &&
+ ( iChild->iRiId.Length() <= KRiIdSize ) )
+ {
+
+ if ( iURI )
+ {
+ CDrmMeteringDbData* meteringData =
+ CDrmMeteringDbData::NewLC();
+ meteringData->iContentId = iURI->AllocL();
+ meteringData->iRiId = iChild->iRiId;
+ if( iUsingTimedCount && !iCountConstraintActive )
+ {
+ meteringData->iCount = 0;
+ }
+ else
+ {
+ meteringData->iCount = 1;
+ }
+
+ meteringData->iAccumulatedTime = iTotalCumulativeTime;
+
+ if ( iParentId )
+ {
+ meteringData->iParentUid = iParentId->AllocL();
+ }
+
+ METERINGDB.AddL( meteringData );
+ CleanupStack::PopAndDestroy(); // meteringData
+ }
+ }
+ }
+ }
+ }
+ DRMLOG( _L( "CDRMConsume::UpdateMeteringDbL ok" ) );
+ }
+
+// ------------------------------------------------------------------------
+// CDRMConsume::CheckRiContextRightsL
+// ------------------------------------------------------------------------
+//
+
+TBool CDRMConsume::CheckRiContextRightsL( const TDesC8& aRiId )
+ {
+
+ DRMLOG( _L( "CDRMConsume::CheckRiContextRightsL" ) );
+
+ CDRMRIContext* riContext = NULL;
+ TBool haveRights = EFalse;
+
+ // Connect to the storage of the registered Rights Issuers
+
+ if( iSession.ConnectRoapClient() == KErrNone )
+ {
+ riContext = iSession.RoapClient().GetRIContextL( aRiId );
+
+ if ( riContext == NULL )
+ {
+ DRMLOG( _L ( "RI not registered" ) );
+ User::Leave( KErrRightsServerRiNotRegistered );
+ }
+
+ // Check (via the Rights Issuer context) whether Rights Issuer
+ // is allowed to use metering or not
+ if ( riContext->IsMeteringAllowed() )
+ {
+ haveRights = ETrue;
+ }
+
+ if ( riContext )
+ {
+ delete riContext;
+ riContext = NULL;
+ }
+ }
+
+ return haveRights;
+
+ }
+
+#endif
+
+// EOF