phonebookui/Phonebook2/CommonUI/src/CPbk2DrmManager.cpp
changeset 0 e686773b3f54
child 68 9da50d567e3c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/phonebookui/Phonebook2/CommonUI/src/CPbk2DrmManager.cpp	Tue Feb 02 10:12:17 2010 +0200
@@ -0,0 +1,607 @@
+/*
+* Copyright (c) 2002-2007 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: 
+*           Phonebook 2 DRM manager.
+*
+*/
+
+
+// INCLUDE FILES
+#include "CPbk2DrmManager.h"
+
+// Phonebook 2
+#include <Pbk2CommonUi.rsg>
+
+// System includes
+#include <featmgr.h>
+#include <DRMCommon.h>
+#include <StringLoader.h>
+#include <aknnotewrappers.h>
+#include <apgcli.h>                     // RApaLsSession
+#include <musicplayerdomaincrkeys.h>    // KCRUidMusicPlayerFeatures
+#include <centralrepository.h>
+#include <DRMHelper.h>
+#include <coemain.h>
+
+#ifdef RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM
+#include <drmutility.h>
+#include <drmagents.h>
+#endif
+
+/// Unnamed namespace for local definitions
+namespace {
+
+_LIT(KSpaceTxt, " ");
+
+} /// namespace
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::CPbk2DrmManager
+// --------------------------------------------------------------------------
+//
+CPbk2DrmManager::CPbk2DrmManager() :
+        iDrmEnabled( EFalse )
+    {
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::~CPbk2DrmManager
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2DrmManager::~CPbk2DrmManager()
+    {
+    if ( iDrmClient )
+        {
+        iDrmClient->Disconnect();
+        }
+    delete iDrmClient;
+    delete iDrmHelper;
+    delete iMusicPlayerFeatures;
+    
+    FeatureManager::UnInitializeLib();
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CPbk2DrmManager* CPbk2DrmManager::NewL()
+    {
+    CPbk2DrmManager* self = new ( ELeave ) CPbk2DrmManager;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::ConstructL
+// --------------------------------------------------------------------------
+//
+void CPbk2DrmManager::ConstructL()
+    {
+    // Sets up TLS, must be done before FeatureManager is used
+    FeatureManager::InitializeLibL();
+
+    iDrmHelper = CDRMHelper::NewL();
+    iDrmClient = DRMCommon::NewL();
+    if ( iDrmClient->Connect() == DRMCommon::EOk )
+        {
+        // If unable to connect, DRM protection is always on
+        iDrmEnabled = ETrue;
+        }
+    
+    iMusicPlayerFeatures = CRepository::NewLC( KCRUidMusicPlayerFeatures );
+    CleanupStack::Pop(); // iMusicPlayerFeatures
+    }
+
+#ifndef RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM
+
+// Some magic constants
+static const TInt KMinContentLength( 16 );
+_LIT8( KContentProtectionType, "DRM" );
+_LIT8( KASFHeaderObject, "75B22630668E11CFA6D900AA0062CE6C" );
+
+
+// -----------------------------------------------------------------------------
+// FormatGUID
+// -----------------------------------------------------------------------------
+//
+LOCAL_C void FormatGUID( TDes8& aGUID )
+    {
+    TBuf8<16> copyGUID( aGUID );
+    TInt i;
+    for( i = 0; i < 4; i++ )
+        {
+        copyGUID[i] = aGUID[3-i];
+        }
+    for( i = 4; i < 6; i++ )
+        {
+        copyGUID[i] = aGUID[9 - i];
+        }
+    for( i = 6; i < 8; i++ )
+        {
+        copyGUID[i] = aGUID[13 - i];
+        }
+    for( i = 8; i < 16 ; i++ )
+        {
+        copyGUID[i] = aGUID[i];
+        }
+    aGUID.Delete( 0, 32 );
+    for( i = 0; i <16; i++ )
+        {
+        aGUID.AppendNumFixedWidthUC( copyGUID[i], EHex, 2 );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// ConvertToInt64
+// -----------------------------------------------------------------------------
+//
+LOCAL_C TInt64 ConvertToInt64( TDesC8& aDes )
+    {
+    TInt64 num = 0;
+    TInt i;
+    for( i = 7 ; i >= 0; i-- )
+        {
+        num <<= 8;
+        num |= aDes[i];
+        }
+    return num;
+    }
+
+
+// -----------------------------------------------------------------------------
+// IsProtectedWmDrmL
+// returns ETrue, if file is protected WMDRM file
+//         EFalse if file is not protected WMDRM file
+// Leaves with KErrUnderflow if file has too little data to decide
+//         whether WmDrm or not
+//         may also leave with other system wide error code
+// -----------------------------------------------------------------------------
+//
+LOCAL_C TBool IsProtectedWmDrmL( RFile& aFileHandle )
+    {
+    TInt r( KErrNone );
+    HBufC8* buffer( NULL );
+    TInt pos( 0 );
+    RFile file;
+    TBuf8< 32 > header;
+
+    TInt64 headerSize( 0 );
+    TBool isProtectedWmDrm( EFalse );
+    TPtr8 headerPtr( NULL, 0 );
+
+    // Leave if given handle is invalid
+    if( !aFileHandle.SubSessionHandle() )
+        {
+        User::Leave( KErrBadHandle );
+        }
+
+    file.Duplicate( aFileHandle );
+    CleanupClosePushL( file );
+
+    User::LeaveIfError( file.Seek( ESeekStart, pos ) );
+
+    // Check if the file is an ASF file
+    // TODO: Check on runtime wether WM DRM is supporeted or not
+    //       Take Implementation from DRM::CDrmUtility::GetDrmInfoL,
+    //       which is not yet available
+
+    User::LeaveIfError( file.Read( 0, header, KMinContentLength ) );
+    if( header.Length() < KMinContentLength )
+        {
+        User::Leave( KErrUnderflow );
+        }
+
+    FormatGUID( header );
+
+    if( header == KASFHeaderObject )
+        {
+        // It's ASF, check still whether it's WM DRM protected or not
+        file.Read( header,8 );
+        headerSize = ConvertToInt64( header );
+        if( headerSize <= 30 )
+            {
+            User::Leave( KErrUnderflow );
+            }
+        if ( headerSize > KMaxTInt16 )
+            {
+            User::Leave( KErrOverflow );
+            }
+        buffer = HBufC8::NewLC( headerSize );
+
+        headerPtr.Set( buffer->Des() );
+        User::LeaveIfError( file.Read( headerPtr, headerSize - 24 ) );
+
+        r = headerPtr.Find( KContentProtectionType );
+        if ( KErrNotFound != r )
+            {
+            isProtectedWmDrm = ETrue;
+            }
+        CleanupStack::PopAndDestroy( buffer ); // buffer
+        }
+        CleanupStack::PopAndDestroy(); // file
+
+    return isProtectedWmDrm;
+    }
+
+#endif // RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM
+
+// -----------------------------------------------------------------------------
+// CPbk2DrmManager::IsFileWMDRMProtectedL
+// -----------------------------------------------------------------------------
+//
+TBool CPbk2DrmManager::IsFileWMDRMProtectedL( const TDesC& aFileName,
+											TBool& aIsProtected  ) const
+	{
+	TBool res = EFalse;
+	RFs& fsSession( CCoeEnv::Static()->FsSession() );
+	RFile hFile;
+
+	TInt err = hFile.Open( fsSession, aFileName, 
+						EFileRead | EFileStream | EFileShareReadersOnly );
+	if( err == KErrInUse )
+		{
+		err = hFile.Open( fsSession, aFileName, 
+						EFileRead | EFileStream | EFileShareAny );
+		}
+	if( err != KErrNone )
+		{
+		User::Leave( err );
+		}
+	CleanupClosePushL( hFile );
+
+#ifdef RD_DRM_COMMON_INTERFACE_FOR_OMA_AND_WMDRM
+	TPtrC agent( KNullDesC );
+	DRM::CDrmUtility* drmUtil( DRM::CDrmUtility::NewLC() );
+	drmUtil->GetAgentL( hFile, agent );
+	if( agent.Compare( DRM::KDrmWMAgentName ) == 0 )
+		{
+		res = ETrue;
+		}
+	else
+		{
+		res = iDrmClient->IsProtectedFile( aFileName, aIsProtected );	
+		}	
+	CleanupStack::PopAndDestroy( drmUtil );
+#else
+	res = IsProtectedWmDrmL( hFile );
+	aIsProtected = EFalse;
+#endif
+
+	CleanupStack::PopAndDestroy( &hFile );
+	return res;
+	}
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::IsProtectedFile
+// --------------------------------------------------------------------------
+//
+
+EXPORT_C TInt CPbk2DrmManager::IsProtectedFile(
+        const TDesC& aFileName,
+        TBool& aIsProtected )
+    {
+    aIsProtected = ETrue;
+        
+    const TBool drmSupported =
+        ( FeatureManager::FeatureSupported( KFeatureIdDrm )||
+          FeatureManager::FeatureSupported( KFeatureIdDrmFull ) );
+
+    TInt drmErrorCode( KErrNone );
+    if ( !drmSupported )
+        {
+        // No DRM support, file retrieval always ok
+        aIsProtected = EFalse;
+        }
+    else if ( iDrmEnabled )
+        {
+        // Check is the file protected
+		drmErrorCode = IsFileWMDRMProtectedL( aFileName,aIsProtected );
+        }
+    return drmErrorCode;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::IsRingingToneForbidden
+// --------------------------------------------------------------------------
+//
+EXPORT_C TInt CPbk2DrmManager::IsRingingToneForbidden( 
+        const TDesC& aFileName,
+        TBool& aIsProtected )
+    {
+    aIsProtected = ETrue;
+    TInt error( KErrNone );
+    const TBool drmSupported =
+        ( FeatureManager::FeatureSupported( KFeatureIdDrm ) ||
+          FeatureManager::FeatureSupported( KFeatureIdDrmFull ) );
+
+    if ( !drmSupported )
+        {
+        // No DRM support, file retrieval always ok
+        aIsProtected = EFalse;
+        }
+    else
+        {
+        // DRM is enabled. File must be checked
+        error = IsProtectedFile( aFileName, aIsProtected );
+        if ( error == KErrNone )
+            {
+            if ( aIsProtected )
+                {
+                TRAP( error, CheckProtectedFileL( aFileName, aIsProtected ) );
+                }
+            else
+                {
+                TRAP( error, CheckUnprotectedFileL( aFileName, aIsProtected ) );
+                }
+            }
+         else
+         	{
+         	error = 0;
+         	TRAP_IGNORE( ShowErrorNoteL( R_QTN_PHOB_PROTECTED_TONE ) );
+         	}           
+        }
+    return error;       
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::IsThumbnailForbidden
+// --------------------------------------------------------------------------
+//
+EXPORT_C TInt CPbk2DrmManager::IsThumbnailForbidden( 
+        const TDesC& aFileName,
+        TBool& aIsProtected )
+    {
+    aIsProtected = ETrue;
+    TInt error = IsProtectedFile( aFileName, aIsProtected );
+    
+    // Thumbnails with any DRM protection are not allowed
+    if ( error == KErrNone && aIsProtected )
+        {
+        TRAP_IGNORE( ShowErrorNoteL( R_PBK2_QTN_DRM_NOT_ALLOWED ) );
+        }
+    
+    return error;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::ShowErrorNoteL
+// --------------------------------------------------------------------------
+//
+void CPbk2DrmManager::ShowErrorNoteL( TInt aResource )
+    {
+    CEikonEnv* env = CEikonEnv::Static();
+    HBufC* noteText = StringLoader::LoadLC( aResource, env );
+
+    // DRM notifications are shown as waiting information notes
+    CAknInformationNote* note = new ( ELeave ) CAknInformationNote( ETrue );
+    note->ExecuteLD( *noteText );
+
+    CleanupStack::PopAndDestroy( noteText ); //noteText
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::IsDrmRequiredForPlaybackL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2DrmManager::IsDrmRequiredForPlaybackL()
+    {
+    // It is possible to disable support for non-DRM protected rich audio
+    // formats    
+    TInt value( 0 );
+    User::LeaveIfError(
+        iMusicPlayerFeatures->Get( KRequireDRMInPlayback, value ) );    
+    return static_cast<TBool>( value );
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::IsBlockedMimeTypeL
+// --------------------------------------------------------------------------
+//
+TBool CPbk2DrmManager::IsBlockedMimeTypeL( const TDesC& aMimeType )
+    {
+    TBool ret = EFalse;    
+    TBuf<1> tmp; // Magic: 1 char to get length of actual value
+    TInt realLen = 0;
+    TInt err = iMusicPlayerFeatures->Get(
+        KPlaybackRestrictedMimeTypes, tmp, realLen );
+    if ( err == KErrOverflow )
+        {
+        // Prepare list of blocked MIME types
+        HBufC* listBuf = HBufC::NewLC( realLen + KSpaceTxt().Length() );
+        TPtr list = listBuf->Des();
+        User::LeaveIfError(
+            iMusicPlayerFeatures->Get
+                ( KPlaybackRestrictedMimeTypes, list ) );
+        list.Append( KSpaceTxt );
+
+        // Prepare buffer for aMimeType
+        HBufC* mimeBuf = HBufC::NewLC( aMimeType.Length() +
+                                       KSpaceTxt().Length() );
+        TPtr mime = mimeBuf->Des();
+        mime = aMimeType;
+        // FindF() would find "audio/3gpp" in "audio/3gpp2" without
+        // the added space
+        mime.Append( KSpaceTxt );
+
+        // If result is not KErrNotFound, this MIME-type is indeed blocked
+        ret = ( list.FindF( mime ) >= 0 );
+
+        CleanupStack::PopAndDestroy(2); // listBuf, mimeBuf
+        }
+    else
+        {
+        User::LeaveIfError( err );
+        }    
+    return ret;
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::CheckProtectedFileL
+// --------------------------------------------------------------------------
+//
+void CPbk2DrmManager::CheckProtectedFileL( 
+        const TDesC& aFileName,
+        TBool& aProtected )
+    {
+    aProtected = ETrue;
+    TBool automatedOk(EFalse);
+
+    // Check that file can be set as automated content.
+    TInt err = iDrmHelper->CanSetAutomated( aFileName, automatedOk );
+    if ( err==KErrNone )
+        {
+        if ( !automatedOk )
+            {
+            ShowErrorNoteL(R_QTN_PHOB_DRM_PREV_RIGHTS_SET);
+            }
+        else
+            {
+            DRMCommon::TContentProtection protection;
+            HBufC8* mimeType = NULL; // ignored
+            HBufC8* contentUri = NULL;
+            TUint dataLength; // ignored
+            err = iDrmClient->GetFileInfo( 
+                    aFileName, protection, mimeType, contentUri, dataLength );
+            delete mimeType;
+            mimeType = NULL;
+            if( err )
+                {
+                delete contentUri;
+                User::Leave( err );
+                }
+
+            CDRMRights* rights = NULL;
+            err = iDrmClient->GetActiveRights( 
+                    *contentUri, DRMCommon::EPlay, rights );
+
+            switch ( err )
+                {
+                case CDRMRights::EFullRights: // Fall through
+                case CDRMRights::ERestrictedRights:
+                    {
+                    CDRMRights::TRestriction restriction; // ignore
+                    CDRMRights::TExpiration expiration;
+                    TUint32 constType;
+
+                    // Ignore return value
+                    rights->GetRightsInfo( 
+                        DRMCommon::EPlay, restriction, expiration, constType );
+
+                    // This is CFM protected file, ringingtone is set to "no"
+                    if ( ( rights->GetPermission().iInfoBits & ENoRingingTone )
+                        // This is normal DRM protected tone
+                        || ( constType & ( CDRMRights::ECountBased |
+                                           CDRMRights::ETimeIsAccumulatedTime ) ) )
+                        {
+                        ShowErrorNoteL( R_QTN_PHOB_DRM_PREV_RIGHTS_SET );
+                        }
+                    else
+                        {
+                        switch ( expiration )
+                            {
+                            case CDRMRights::EValidRights:
+                                {
+                                aProtected = EFalse;
+                                break;
+                                }
+                            case CDRMRights::EFutureRights:
+                                {
+                                iDrmHelper->HandleErrorL( 
+                                    DRMCommon::ENoRights, aFileName );
+                                break;
+                                }
+                            case CDRMRights::EExpiredRights:
+                                {
+                                iDrmHelper->HandleErrorL( 
+                                    DRMCommon::ERightsExpired, aFileName );
+                                break;
+                                }
+                            default:
+                                {
+                                // Do nothing
+                                break;
+                                }
+                            }
+                        }
+                    break;
+                    }
+                case CDRMRights::EPreviewRights:
+                    {
+                    ShowErrorNoteL( R_QTN_PHOB_DRM_PREV_RIGHTS_SET );
+                    break;
+                    }
+                case DRMCommon::ENoRights:
+                    {
+                    iDrmHelper->HandleErrorL( DRMCommon::ENoRights, aFileName );
+                    break;
+                    }
+                default:
+                    {
+                    // Do nothing
+                    break;
+                    }
+                }
+
+            delete rights;
+            delete contentUri;
+            }
+        }
+    else
+        {
+        // Locked file case is handled separately.
+        if ( err==KErrInUse )
+            {
+            CCoeEnv::Static()->HandleError( KErrInUse );
+            }
+        else
+            {
+            // Leave if DrmHelper not handle the error
+            User::LeaveIfError( iDrmHelper->HandleErrorL(err,aFileName) );
+            }
+        }
+    }
+
+// --------------------------------------------------------------------------
+// CPbk2DrmManager::CheckUnprotectedFileL
+// --------------------------------------------------------------------------
+//
+void CPbk2DrmManager::CheckUnprotectedFileL( 
+        const TDesC& aFileName, 
+        TBool& aProtected )
+    {
+    aProtected = ETrue;    
+    RApaLsSession apaLs;
+    User::LeaveIfError( apaLs.Connect() );
+    TUid appUidNotUsed = KNullUid;
+    TDataType dataType;
+    TInt err = apaLs.AppForDocument( aFileName, appUidNotUsed, dataType );
+    apaLs.Close();
+    User::LeaveIfError( err );
+
+    // Check if this unprotected MIME type should be blocked
+    if ( IsDrmRequiredForPlaybackL() &&
+         IsBlockedMimeTypeL( dataType.Des() ) )
+        {
+        ShowErrorNoteL( R_QTN_PHOB_UNPROTECTED_TONE );
+        }
+    else
+        {
+        aProtected = EFalse;
+        }
+    }
+
+//  End of File