filemanager/GFLM/src/CGflmFileRecognizer.cpp
changeset 0 6a9f87576119
child 13 5181328fad28
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/filemanager/GFLM/src/CGflmFileRecognizer.cpp	Mon Jan 18 20:09:41 2010 +0200
@@ -0,0 +1,436 @@
+/*
+* 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:  Recogniser wrapper
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "CGflmFileRecognizer.h"
+#include "CGflmDriveResolver.h"
+#include "CGflmDriveItem.h"
+#include "GflmUtils.h"
+#include "GFLMConsts.h"
+#include <e32svr.h>
+#include <barsread.h>
+#include <GflmFileExtensionMimeTypes.rsg>
+#include <data_caging_path_literals.hrh> 
+
+
+// CONSTANTS
+_LIT( KFileExtensionResourceFile, "gflmfileextensionmimetypes.rsc" );
+const TInt KMimeTypeGranularity = 10;
+const TUint KPerCentToDrop = 30;
+const TUint KHundredPerCent = 100;
+
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CGflmFileRecognizer
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CGflmFileRecognizer(
+        CGflmDriveResolver* aDriveResolver,
+        RFs& aFs ) :
+    iCache( _FOFF( CPathTypePair, iLink ) ),
+    iDriveResolver( aDriveResolver ),
+    iFs( aFs )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::ConstructL( TInt aMemoryConsumption )
+    {
+    User::LeaveIfError( iApaSession.Connect() );
+    iMimeTypes = new( ELeave ) CDesCArraySeg( KMimeTypeGranularity );
+    iCacheMaxMemoryUsage = aMemoryConsumption;
+
+    // Get resource drive from dll location
+    TFileName dllFileName;
+    Dll::FileName( dllFileName );
+    TParsePtrC dllParse( dllFileName );
+
+    TFileName resFileName;
+    resFileName.Copy( dllParse.Drive() );
+    resFileName.Append( KDC_RESOURCE_FILES_DIR );
+    GflmUtils::EnsureFinalBackslash( resFileName );
+    resFileName.Append( KFileExtensionResourceFile );
+
+    RResourceFile resFile;
+    resFile.OpenL( iFs, resFileName );
+    CleanupClosePushL( resFile );
+    resFile.ConfirmSignatureL();
+
+    ConstructExtMimePairsL( resFile, R_EXT_MIME_PAIRS, iExtMimePairs );
+    ConstructExtMimePairsL(
+        resFile, R_REMOTE_EXT_MIME_PAIRS, iRemoteExtMimePairs );
+
+    CleanupStack::PopAndDestroy( &resFile );
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::ConstructExtMimePairsL
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::ConstructExtMimePairsL(
+        RResourceFile& aResFile,
+        TInt aResId,
+        RPointerArray< CExtMimePair >& aPairs )
+    {
+    // read the pairs
+    HBufC8* resData = aResFile.AllocReadLC( aResId );
+    TResourceReader reader;
+    reader.SetBuffer( resData );
+    TInt count( reader.ReadInt16() );
+    aPairs.ReserveL( count );
+    for ( TInt i( 0 ); i < count; i++ )
+        {
+        TPtrC ext( reader.ReadTPtrC() );
+        TPtrC mime( reader.ReadTPtrC() );
+        CExtMimePair* pair = new (ELeave) CExtMimePair();
+        CleanupStack::PushL( pair );
+        pair->iExt = ext.AllocL();
+        pair->iMime = mime.AllocL();
+        aPairs.AppendL( pair );
+        CleanupStack::Pop( pair );
+        }
+    CleanupStack::PopAndDestroy( resData );
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::FindMimeFromExt
+//
+// -----------------------------------------------------------------------------
+//
+TPtrC CGflmFileRecognizer::FindMimeFromExt(
+        const TDesC& aExt,
+        RPointerArray< CExtMimePair >& aPairs )
+    {
+    TInt count( aPairs.Count() );
+
+    for( TInt i( 0 ); i < count; i++)
+        {
+        CExtMimePair* pair = aPairs[ i ];
+        if( !aExt.CompareF( *pair->iExt ) )
+            {
+            return TPtrC( *pair->iMime );
+            }
+        }
+    return TPtrC( KNullDesC );
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer* CGflmFileRecognizer::NewL(
+        RFs& aFs,
+        TInt aMemoryConsumption,
+        CGflmDriveResolver* aDriveResolver )
+    {
+    CGflmFileRecognizer* self =
+        new( ELeave ) CGflmFileRecognizer( aDriveResolver, aFs );
+
+    CleanupStack::PushL( self );
+    self->ConstructL( aMemoryConsumption );
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::~CGflmFileRecognizer
+//
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::~CGflmFileRecognizer()
+    {
+    iApaSession.Close();
+
+    FlushCache();
+
+    delete iMimeTypes;
+
+    iExtMimePairs.ResetAndDestroy();
+    iExtMimePairs.Close();
+
+    iRemoteExtMimePairs.ResetAndDestroy();
+    iRemoteExtMimePairs.Close();
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::RecognizeL( const TDesC& aFilename )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC CGflmFileRecognizer::RecognizeL( const TDesC& aFilename )
+    {
+    TPtrC mimeType;
+    TRAPD( err, mimeType.Set( DoRecognizeL( aFilename ) ) );
+    if ( err == KErrNoMemory )
+        {
+        FlushCache();
+        return DoRecognizeL( aFilename );
+        }
+    User::LeaveIfError( err );
+    return mimeType;
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename )
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TPtrC CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename )
+    {
+    // Search the cache for a hit
+    TInt cropPoint( aFilename.LocateReverse( KGFLMDot()[ 0 ] ) );
+    TBool isRemoteDrive( EFalse );
+
+    if ( iDriveResolver && iDriveResolver->IsRemoteDrive( aFilename ) )
+        {
+        isRemoteDrive = ETrue;
+        }
+
+    if( cropPoint != KErrNotFound )
+        {        
+        TPtrC ext( aFilename.Mid( cropPoint ) );
+        TPtrC mime( FindMimeFromExt( ext, iExtMimePairs ) );
+        if ( mime.Length() )
+            {
+            return mime;
+            }
+
+        // Use remote drive specific extension mime pairs and skip
+        // content recognition because it is so slow for remote drives.
+        // Mime types are resolved from extension by remote storage framework
+        // anyway.
+        if ( isRemoteDrive)
+            {
+            return FindMimeFromExt( ext, iRemoteExtMimePairs );
+            }
+        }
+    else if ( isRemoteDrive)
+        {
+        // Skip content recognition for remote drives because it is so slow
+        return TPtrC( KNullDesC );
+        }
+
+    TDblQueIter< CPathTypePair > pairIt( iCache );
+    pairIt.SetToFirst();
+    CPathTypePair* pair = NULL;
+    while ( ( pair = pairIt++ ) != NULL )
+        {
+        TPtrC ptr( *( pair->iFilename ) );
+        if( ptr.Length() == aFilename.Length() &&
+           !aFilename.CompareF( ptr ) )
+            {
+            // Cache hit
+            // Move item to the first position if not already.
+            // When clearing cache, oldest items can be dropped easily.
+            pair->iLink.Deque();
+            iCache.AddFirst( *pair );
+
+            if ( pair->iTypeIndex != KErrNotFound )
+                {
+                return iMimeTypes->MdcaPoint( pair->iTypeIndex );
+                }
+            return TPtrC( KNullDesC );
+            }
+        }
+
+        // Cache miss
+        TUid uid( KNullUid );
+        TDataType datatype;
+
+        TIMESTAMP( "GFLM AppForDocument started: " )
+
+        // Acquire the mime-type of the file
+        TInt err( iApaSession.AppForDocument( aFilename, uid, datatype ) );
+
+        TIMESTAMP( "GFLM AppForDocument ended: " )
+
+        if ( err != KErrNone )
+            {
+            // If recognition returns error, handle as unrecognized file
+            ERROR_LOG1(
+                "CGflmFileRecognizer::DoRecognizeL-AppForDocument=%d",
+                err )
+            return TPtrC( KNullDesC );
+            }
+
+        CPathTypePair* newPair = CPathTypePair::NewLC( aFilename );
+        TPtrC mimeType( datatype.Des() );
+
+        INFO_LOG2( "GFLM AppForDocument:file=%S,mime=%S", &aFilename, &mimeType )
+
+        // Run through the mime-type list to find the correct index
+        if ( mimeType.Length() )
+            {
+            TBool isMimeFound( EFalse );
+            TInt mimeCount( iMimeTypes->MdcaCount() );
+            for ( TInt j( 0 ); j < mimeCount; j++ )
+                {
+                if( !mimeType.CompareF( iMimeTypes->MdcaPoint( j ) ) )
+                    {
+                    newPair->iTypeIndex = j;
+                    isMimeFound = ETrue;
+                    break;
+                    }
+                }
+            // Add mime type to list if not already added
+            if ( !isMimeFound )
+                {
+                iMimeTypes->AppendL( mimeType );
+                newPair->iTypeIndex = mimeCount;
+                }
+            }
+
+        // Cleanup cache and add new pair
+        CleanupStack::Pop( newPair );
+        CleanupCache();
+        iCacheMemoryUsage += newPair->Size();
+        iCache.AddFirst( *newPair );
+
+        if ( newPair->iTypeIndex != KErrNotFound )
+            {
+            return iMimeTypes->MdcaPoint( newPair->iTypeIndex );
+            }
+        return TPtrC( KNullDesC );
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::FlushCache( )
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::FlushCache()
+    {
+    TDblQueIter< CPathTypePair > pairIt( iCache );
+    pairIt.SetToFirst();
+    CPathTypePair* pair = NULL;
+    while ( ( pair = pairIt++ ) != NULL )
+        {
+        pair->iLink.Deque();
+        delete pair;
+        }
+    iCacheMemoryUsage = 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CleanupCache( )
+//
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::CleanupCache( )
+    {
+    if( iCacheMemoryUsage > iCacheMaxMemoryUsage )
+        {
+        TInt dropThreshold = ( TInt ) ( ( ( ( TUint ) iCacheMaxMemoryUsage ) *
+            KPerCentToDrop ) / KHundredPerCent );
+        TInt droppedSize( 0 );
+
+        TDblQueIter< CPathTypePair > pairIt( iCache );
+        pairIt.SetToLast();
+        CPathTypePair* pair = NULL;
+        while ( ( pair = pairIt-- ) != NULL )
+            {
+            droppedSize += pair->Size();
+            pair->iLink.Deque();
+            delete pair;
+            if ( droppedSize >= dropThreshold )
+                {
+                break;
+                }
+            }
+        iCacheMemoryUsage -= droppedSize;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::NewLC()
+// 
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CPathTypePair*
+        CGflmFileRecognizer::CPathTypePair::NewLC( const TDesC& aFilename )
+    {
+    CPathTypePair* self = new ( ELeave ) CPathTypePair();
+    CleanupStack::PushL( self );
+    self->ConstructL( aFilename );
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::ConstructL()
+// 
+// -----------------------------------------------------------------------------
+//
+void CGflmFileRecognizer::CPathTypePair::ConstructL( const TDesC& aFilename )
+    {
+    iFilename = aFilename.AllocL();
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::CPathTypePair()
+// 
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CPathTypePair::CPathTypePair() :
+        iTypeIndex( KErrNotFound )
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::~CPathTypePair()
+// 
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CPathTypePair::~CPathTypePair()
+    {
+    delete iFilename;
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CPathTypePair::Size()
+// 
+// -----------------------------------------------------------------------------
+//
+TInt CGflmFileRecognizer::CPathTypePair::Size() const
+    {
+    return ( sizeof( TInt ) + iFilename->Size() + sizeof( TDblQueLink ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CGflmFileRecognizer::CExtMimePair::~CExtMimePair()
+// 
+// -----------------------------------------------------------------------------
+//
+CGflmFileRecognizer::CExtMimePair::~CExtMimePair()
+    {
+    delete iExt;
+    delete iMime;
+    }
+
+//  End of File