diff -r 8cdda00a45da -r 04da681812a9 commondrm/drmrightsmanagerui/src/DRMRightsMgrAppUi.cpp --- a/commondrm/drmrightsmanagerui/src/DRMRightsMgrAppUi.cpp Wed Apr 14 16:15:06 2010 +0300 +++ b/commondrm/drmrightsmanagerui/src/DRMRightsMgrAppUi.cpp Tue Apr 27 16:56:11 2010 +0300 @@ -58,7 +58,70 @@ _LIT8( Kflk, "flk:" ); _LIT8( Kldf, "ldf:" ); -// ================= MEMBER FUNCTIONS ======================= +// ============================= LOCAL FUNCTIONS =============================== + +// ---------------------------------------------------------------------------- +// DoResetAndDestroy +// Does RPointerArray< >->ResetAndDestroy() for the given array aPtr. +// ---------------------------------------------------------------------------- +// +LOCAL_C void DoResetAndDestroyPermission( TAny* aPtr ) + { + ( reinterpret_cast< RPointerArray< CDRMPermission >* >( aPtr ) )-> + ResetAndDestroy(); + } + +// ---------------------------------------------------------------------------- +// PrepareRightsObjectL +// Creates rights object based on the given permission. +// ---------------------------------------------------------------------------- +// +LOCAL_C void PrepareRightsObjectL( CDRMRights*& aRights, + CDRMPermission* aPermission ) + { + CDRMAsset* asset( NULL ); + + if ( !aPermission ) + { + User::Leave( KErrArgument ); + } + + aRights = CDRMRights::NewL(); + CleanupStack::PushL( aRights ); + aRights->SetPermissionL( *aPermission ); + + asset = CDRMAsset::NewLC(); + aRights->SetAssetL( *asset ); + CleanupStack::PopAndDestroy( asset ); + CleanupStack::Pop( aRights ); + + // Content URI and Local Id are not set + } + +// ---------------------------------------------------------------------------- +// EndTime +// Calculate the true end time: pick the smaller one of aTime1 & aTime2, +// but ignore Time::NullTTime anyhow. +// ---------------------------------------------------------------------------- +// +LOCAL_C TTime EndTime( const TTime& aTime1, const TTime& aTime2 ) + { + TTime nullTime = Time::NullTTime(); + + if ( aTime1 == nullTime ) + { + return aTime2; + } + + if ( aTime2 == nullTime ) + { + return aTime1; + } + + return Min( aTime1, aTime2 ); + } + +// ================= MEMBER FUNCTIONS ========================================== // // ----------------------------------------------------------------------------- // CDRMRightsMgrAppUi::CDRMRightsMgrAppUi @@ -92,6 +155,7 @@ EAknEnableMSK | EAknSingleClickCompatible ); User::LeaveIfError( iRightsClient.Connect() ); + User::LeaveIfError( iClockClient.Connect() ); iDRMCommon = DRMCommon::NewL(); if ( !iDRMCommon ) { @@ -129,6 +193,8 @@ delete iDRMCommon; iRightsClient.Close(); + + iClockClient.Close(); if ( iStartEmbedded && iDoorObserver ) { @@ -557,8 +623,8 @@ // from the background to the foreground. if ( iForegroundHasBeenActive && iContentURI ) { - StartOnlyForDetailsL( iContentURI->Des(), iLocalID, - iStartEmbedded, iDrmScheme ); + TRAP_IGNORE( StartOnlyForDetailsL( iContentURI->Des(), iLocalID, + iStartEmbedded, iDrmScheme ) ); } } @@ -739,7 +805,10 @@ { TBool listable( EFalse ), sendable( EFalse ); TBool individualConstraint( EFalse ), usageAllowed( EFalse ); + TInt err( KErrNone ); + + aStatus = KErrNone; CDcfRep* dcfRep = CDcfRep::NewL(); CleanupStack::PushL( dcfRep ); @@ -798,23 +867,32 @@ { aStatus = iDRMCommon->GetSingleRightsObject( aContentURI, aLocalID, aRights ); - if ( aStatus ) - { - aRights = NULL; - } + CheckIndividualConstraint( aContentURI, individualConstraint, usageAllowed ); + SetSelectedIndividualConstraint( individualConstraint ); + SetSelectedUsageAllowed( usageAllowed ); } else { - aStatus = iDRMCommon->GetActiveRights( aContentURI, 0, aRights ); + SetSelectedIndividualConstraint( EFalse ); + SetSelectedUsageAllowed( ETrue ); + + // Get active rights if available + err = iDRMCommon->GetActiveRights( aContentURI, 0, aRights ); + + if ( err < 0 ) + { + // Find out the best composition of rights that should be shown in the + // details view. Checks also individual constraint. + TRAP( aStatus, FindBestCompositionRightsL( aContentURI, aRights ) ); + } + } + + if ( aStatus ) + { + aRights = NULL; } - CheckIndividualConstraint( aContentURI, individualConstraint, usageAllowed ); - SetSelectedIndividualConstraint( individualConstraint ); - SetSelectedUsageAllowed( usageAllowed ); - CleanupStack::PopAndDestroy( dcfRep ); - - // Do not show the note, show license information in the details view. } // --------------------------------------------------------- @@ -880,23 +958,18 @@ TBool& aIndividualConstraint, TBool& aUsageAllowed ) { + + TTime time; + RPointerArray individuals; + RPointerArray* uriList = NULL; TInt r = KErrNone; TUint32 retval(0); + TInt timeZone(0); DRMClock::ESecurityLevel secLevel = DRMClock::KInsecure; CDRMRightsConstraints* constraint = NULL; - RDRMClockClient client; - RDRMRightsClient rclient; - TTime time; - RPointerArray individuals; - - r = client.Connect(); - if ( r == KErrNone ) - { - TTime time; - TInt timeZone(0); - client.GetSecureTime(time, timeZone, secLevel); - } + + iClockClient.GetSecureTime(time, timeZone, secLevel); r = iDRMCommon->GetDetailedContentRights(aContentURI, uriList); if ( r ) @@ -909,19 +982,13 @@ if ( !uriList || !uriList->Count() ) { // no rights found - client.Close(); delete uriList; uriList = NULL; } else { // supported IMSI information is provided by rights client - r = rclient.Connect(); - if( r == KErrNone) - { - TRAP( r, r = rclient.GetSupportedIndividualsL( individuals ) ); - rclient.Close(); - } + TRAP( r, r = iRightsClient.GetSupportedIndividualsL( individuals ) ); // Check only the first entry in the list. This is to be expanded to check // all the entries in the list. @@ -959,7 +1026,6 @@ constraint = NULL; } - client.Close(); uriList->ResetAndDestroy(); delete uriList; @@ -969,4 +1035,498 @@ } } +// --------------------------------------------------------- +// CDRMRightsMgrAppUi::FindBestCompositionRightsL +// --------------------------------------------------------- +// +void CDRMRightsMgrAppUi::FindBestCompositionRightsL( const TDesC8& aContentURI, + CDRMRights*& aRights ) + { + TInt i, j, k; + RPointerArray permissionList; + RPointerArray permissionTempList; + RPointerArray parentUidList; + RPointerArray individuals; + + TInt count( 0 ); + TInt status( KErrNone ); + TTime time( Time::NullTTime() ); + TInt err( KErrNone ); + TUint32 reason( EConstraintNone ); + TBool individualConstraintFound( EFalse ); + + // Composition object of best rights to be shown in the + // details view + CDRMPermission* perm( NULL ); + + TCleanupItem cleanupPerm( DoResetAndDestroyPermission, &permissionList ); + CleanupStack::PushL( cleanupPerm ); + + TCleanupItem cleanupPerm2( DoResetAndDestroyPermission, + &permissionTempList ); + CleanupStack::PushL( cleanupPerm2 ); + + CleanupClosePushL( parentUidList ); + + // First get list of child ROs with the given Content URI + iRightsClient.GetDBEntriesL( aContentURI, permissionList ); + + if ( permissionList.Count() > 0 ) + { + // Check the UIDs of the possible parent rights objects + // and store the found ones to another pointer array for evaluation + for ( i = 0; i < permissionList.Count(); i++ ) + { + if ( permissionList[i]->iParentUID ) + { + if ( i == 0 ) + { + // No need to check if the parent UID is a duplicate + parentUidList.Append( permissionList[i]->iParentUID ); + } + else + { + // Check parent UID list whether we have already stored the + // UID or not + for( j = 0; j < parentUidList.Count(); j++ ) + { + if ( parentUidList[j]->Des().Compare( + permissionList[i]->iParentUID->Des() ) != 0 ) + { + parentUidList.Append( + permissionList[i]->iParentUID ); + break; + } + } + } + } + } + + // Get the list of parent rights objects based on the parent UID + // and store the pointers from temporary array to the main list + for ( j = 0; j < parentUidList.Count(); j++ ) + { + // We do not want to leave if nothing is found from the database + TRAP( status, iRightsClient.GetDBEntriesL( parentUidList[j]->Des(), + permissionTempList ) ); + + if ( status ) + { + continue; + } + + for ( k = 0; k < permissionTempList.Count(); k++ ) + { + // Store the pointer to the main list of permissions + permissionList.Append( permissionTempList[k] ); + } + + // Close the temporary pointer array so that the referenced + // objects of it will not be deleted in the next round of the + // loop because the method for getting database entries deletes + // also the objects (by calling reset and destroy to the given + // pointer array) by default. + permissionTempList.Close(); + } + + parentUidList.Close(); + time.HomeTime(); + + // supported IMSI information is provided by rights client + TRAP( err, err = iRightsClient.GetSupportedIndividualsL( individuals ) ); + + // Filter expired parent and child rights from the list + // Index defines the index of the list to be operated (next) + for ( count = permissionList.Count() ; count > 0; count-- ) + { + if ( permissionList[count - 1]->Expired( time ) ) + { + permissionList.Remove( count - 1 ); + } + else if ( !( permissionList[count - 1]->Valid( + time, individuals, reason ) ) ) + { + if ( reason & EConstraintIndividual ) + { + individualConstraintFound = ETrue; + permissionList.Remove( count - 1 ); + } + } + } + + individuals.ResetAndDestroy(); + individuals.Close(); + + if ( permissionList.Count() == 0 ) + { + if ( individualConstraintFound ) + { + SetSelectedIndividualConstraint( ETrue ); + SetSelectedUsageAllowed( EFalse ); + } + User::Leave( KErrNotFound ); + } + else if ( permissionList.Count() == 1 ) + { + // Keep this permission because it is the only valid (left) + PrepareRightsObjectL( aRights, permissionList[0] ); + } + else if ( permissionList.Count() > 1 ) + { + // Compare constraints from successive items of the + // permission list and update the composition permission + // accordingly. + CheckBetterPermissionsAndStoreCompositionLC( perm, permissionList ); + + // Prepare the rights object with the composition permission + PrepareRightsObjectL( aRights, perm ); + CleanupStack::PopAndDestroy( perm ); + } + } + + CleanupStack::PopAndDestroy( 3, &permissionList ); // cleanupPerm, + // cleanupPerm2, + // parentUidList + } + +// ------------------------------------------------------------------- +// CDRMRightsMgrAppUi::CheckBetterPermissionsAndStoreCompositionLC +// ------------------------------------------------------------------- +// +void CDRMRightsMgrAppUi::CheckBetterPermissionsAndStoreCompositionLC( + CDRMPermission*& aCompositionPermission, + RPointerArray& aList ) + { + + TBool firstBetter( EFalse ); + TUint i, j; + + if ( aList.Count() <= 0 ) + { + User::Leave( KErrArgument ); + } + + // create permission if needed and set the first item + // in the permission list as the reference permission. + if ( !aCompositionPermission ) + { + aCompositionPermission = CDRMPermission::NewL(); + } + + CleanupStack::PushL( aCompositionPermission ); + aCompositionPermission->DuplicateL( *aList[0] ); + + // The double loop goes through the permissions and associated + // constraints beginning from the second entry in the permission list. + for ( i = 1; i < aList.Count(); i++ ) + { + // Enumeration for TIntent from Content Access Framework used + for ( j = EPlay; j < EPause; j++ ) + { + switch ( j ) + { + case EPlay: + { + // The constraint from the permission in the list + // is set to composition permission if it is better + // than the "old" best or reference permission. + firstBetter = BetterPermission( *aList[i]->iPlay, + *aCompositionPermission->iPlay ); + if ( firstBetter ) + { + aCompositionPermission->iPlay->DuplicateL( + *aList[i]->iPlay ); + } + break; + } + case EView: + { + firstBetter = BetterPermission( *aList[i]->iDisplay, + *aCompositionPermission->iDisplay ); + if ( firstBetter ) + { + aCompositionPermission->iDisplay->DuplicateL( + *aList[i]->iDisplay ); + } + break; + } + case EExecute: + { + firstBetter = BetterPermission( *aList[i]->iExecute, + *aCompositionPermission->iExecute ); + if ( firstBetter ) + { + aCompositionPermission->iExecute->DuplicateL( + *aList[i]->iExecute ); + } + break; + } + case EPrint: + { + firstBetter = BetterPermission( *aList[i]->iPrint, + *aCompositionPermission->iPrint ); + if ( firstBetter ) + { + aCompositionPermission->iPrint->DuplicateL( + *aList[i]->iPrint ); + } + break; + } + default: + { + User::Leave( KErrArgument ); + } + } + } + } + } + +// ----------------------------------------------------------------------------- +// CDrmRightsMgrAppUi::BetterPermission +// ----------------------------------------------------------------------------- +TBool CDRMRightsMgrAppUi::BetterPermission( const CDRMConstraint& aNewOne, + const CDRMConstraint& aOldOne ) + { + // Check Order: + // 1. Full + // 2. Start End, closest end time first + // 3. Interval, shortest first + // 4. Accumulated, shortest first + // 5. Timed Counter, least counters first, longest time first + // 6. Counter, least counters first or the first one found + + const TTime nullTime = Time::NullTTime(); + TTime oldTime = nullTime; + TTime newTime = nullTime; + TTime oldTimePos = nullTime; + TTime newTimePos = nullTime; + TTime trustedTime = nullTime; + + // 1. Full + // If the old or new one is the ultimate one, don't bother to + // check anything else. + if ( aOldOne.iActiveConstraints == EConstraintNone ) + { + return EFalse; + } + + if ( aNewOne.iActiveConstraints == EConstraintNone ) + { + return ETrue; + } + + // 2. Start & End Time + // Choose the one with the closest end time first + // All RO's to this check are already checked to be valid + // ActiveIntervals Also hit this spot + + trustedTime.HomeTime(); + + // First get the start and end times from the intervals if they are active or inactive: + if ( aOldOne.iActiveConstraints & EConstraintInterval ) + { + if( aOldOne.iIntervalStart == nullTime ) + { + oldTimePos = trustedTime; + oldTimePos += TTimeIntervalSeconds( aOldOne.iInterval ); + } + else + { + oldTime = aOldOne.iIntervalStart; + oldTime += TTimeIntervalSeconds( aOldOne.iInterval ); + } + } + + if( aNewOne.iActiveConstraints & EConstraintInterval ) + { + if( aNewOne.iIntervalStart == nullTime ) + { + newTimePos = trustedTime; + newTimePos += TTimeIntervalSeconds( aNewOne.iInterval ); + } + else + { + newTime = aNewOne.iIntervalStart; + newTime += TTimeIntervalSeconds( aNewOne.iInterval ); + } + } + + if ( aOldOne.iActiveConstraints & EConstraintEndTime || oldTime != nullTime ) + { + oldTime = EndTime( oldTime, aOldOne.iEndTime ); + + if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime ) + { + newTime = EndTime( newTime, aNewOne.iEndTime ); + + if( newTime != oldTime ) + { + return ( newTime < oldTime ); + } + } + else + { + return EFalse; + } + } + else if ( aNewOne.iActiveConstraints & EConstraintEndTime || newTime != nullTime ) + { + return ETrue; + } + + // 3. Inactive Intervals: + // Choose the one with the interval ending first: + // Continue here if the no SE's exist or SE's are the same + if( aOldOne.iActiveConstraints & EConstraintInterval ) + { + if( aNewOne.iActiveConstraints & EConstraintInterval ) + { + oldTimePos = EndTime( oldTime, oldTimePos ); + newTimePos = EndTime( newTime, newTimePos ); + + if( oldTimePos != newTimePos ) + { + return ( newTimePos < oldTimePos ); + } + } + else + { + if( aNewOne.iActiveConstraints & EConstraintAccumulated || + aNewOne.iActiveConstraints & EConstraintTimedCounter || + aNewOne.iActiveConstraints & EConstraintCounter ) + { + return EFalse; + } + else + { + return ETrue; + } + } + } + else if( aNewOne.iActiveConstraints & EConstraintInterval ) + { + if( aOldOne.iActiveConstraints & EConstraintAccumulated || + aOldOne.iActiveConstraints & EConstraintTimedCounter || + aOldOne.iActiveConstraints & EConstraintCounter ) + { + return ETrue; + } + else + { + return EFalse; + } + } + + // 4. Accumulated: + // Choose the shortest accumulated first + // Continue here if SE's or intervals do not exist or they are the same + if( aOldOne.iActiveConstraints & EConstraintAccumulated ) + { + if( aNewOne.iActiveConstraints & EConstraintAccumulated ) + { + if( aNewOne.iAccumulatedTime != aOldOne.iAccumulatedTime ) + { + return ( aNewOne.iAccumulatedTime < aOldOne.iAccumulatedTime ); + } + } + else + { + if( aNewOne.iActiveConstraints & EConstraintTimedCounter || + aNewOne.iActiveConstraints & EConstraintCounter ) + { + return EFalse; + } + else + { + return ETrue; + } + } + } + else if( aNewOne.iActiveConstraints & EConstraintAccumulated ) + { + if( aOldOne.iActiveConstraints & EConstraintTimedCounter || + aOldOne.iActiveConstraints & EConstraintCounter ) + { + return ETrue; + } + else + { + return EFalse; + } + } + + + // 5. Timed Counter + // Choose the one with least counters first. If there is an equal number of counters + // left, use the one with the longest time + // Continue here if SE's or intervals or accumulateds do not exist or they are the same + if( aOldOne.iActiveConstraints & EConstraintTimedCounter ) + { + if( aNewOne.iActiveConstraints & EConstraintTimedCounter ) + { + if( aNewOne.iTimedCounter == aOldOne.iTimedCounter ) + { + if( aNewOne.iTimedInterval != aOldOne.iTimedInterval ) + { + return ( aNewOne.iTimedInterval < aOldOne.iTimedInterval ); + } + else + { + if( aNewOne.iActiveConstraints & EConstraintCounter ) + { + + } + } + } + else + { + return ( aNewOne.iTimedCounter < aOldOne.iTimedCounter ); + } + + } + else + { + if( aNewOne.iActiveConstraints & EConstraintCounter ) + { + return EFalse; + } + else + { + return ETrue; + } + } + } + else if( aNewOne.iActiveConstraints & EConstraintTimedCounter ) + { + if( aOldOne.iActiveConstraints & EConstraintCounter ) + { + return ETrue; + } + else + { + return EFalse; + } + } + + // 6. Counter + // Choose the one with least counters: + // if they are the same choose the first one. + // Continue here if SE's or intervals or accumulateds or timed counters + // do not exist or they are the same + if( aOldOne.iActiveConstraints & EConstraintCounter ) + { + if( aNewOne.iActiveConstraints & EConstraintCounter ) + { + return ( aNewOne.iCounter < aOldOne.iCounter ); + } + else + { + return ETrue; + } + } + + // If all else fails use the old one: + return EFalse; + } + // End of File