commondrm/drmrightsmanagerui/src/DRMRightsMgrAppUi.cpp
changeset 29 3bdc3b853094
parent 23 493788a4a8a4
child 49 69d8e75812b7
--- a/commondrm/drmrightsmanagerui/src/DRMRightsMgrAppUi.cpp	Fri Apr 16 15:14:55 2010 +0300
+++ b/commondrm/drmrightsmanagerui/src/DRMRightsMgrAppUi.cpp	Mon May 03 12:46:34 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<HBufC8> individuals;
+    
     RPointerArray<CDRMRights>* 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<HBufC8> 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<CDRMPermission> permissionList;
+    RPointerArray<CDRMPermission> permissionTempList;
+    RPointerArray<HBufC8> parentUidList;
+    RPointerArray<HBufC8> 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<CDRMPermission>& 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