|         |      1 /* | 
|         |      2 * Copyright (c) 2002-2007 Nokia Corporation and/or its subsidiary(-ies). | 
|         |      3 * All rights reserved. | 
|         |      4 * This component and the accompanying materials are made available | 
|         |      5 * under the terms of "Eclipse Public License v1.0"" | 
|         |      6 * which accompanies this distribution, and is available | 
|         |      7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". | 
|         |      8 * | 
|         |      9 * Initial Contributors: | 
|         |     10 * Nokia Corporation - initial contribution. | 
|         |     11 * | 
|         |     12 * Contributors: | 
|         |     13 * | 
|         |     14 * Description:  Recogniser wrapper | 
|         |     15 * | 
|         |     16 */ | 
|         |     17  | 
|         |     18  | 
|         |     19  | 
|         |     20 // INCLUDE FILES | 
|         |     21 #include "CGflmFileRecognizer.h" | 
|         |     22 #include "CGflmDriveResolver.h" | 
|         |     23 #include "CGflmDriveItem.h" | 
|         |     24 #include "GflmUtils.h" | 
|         |     25 #include "GFLMConsts.h" | 
|         |     26 #include <e32svr.h> | 
|         |     27 #include <barsread.h> | 
|         |     28 #include <GflmFileExtensionMimeTypes.rsg> | 
|         |     29 #include <data_caging_path_literals.hrh>  | 
|         |     30  | 
|         |     31  | 
|         |     32 // CONSTANTS | 
|         |     33 _LIT( KFileExtensionResourceFile, "gflmfileextensionmimetypes.rsc" ); | 
|         |     34 const TInt KMimeTypeGranularity = 10; | 
|         |     35 const TUint KPerCentToDrop = 30; | 
|         |     36 const TUint KHundredPerCent = 100; | 
|         |     37  | 
|         |     38  | 
|         |     39 // ============================ MEMBER FUNCTIONS =============================== | 
|         |     40  | 
|         |     41 // ----------------------------------------------------------------------------- | 
|         |     42 // CGflmFileRecognizer::CGflmFileRecognizer | 
|         |     43 // C++ default constructor can NOT contain any code, that | 
|         |     44 // might leave. | 
|         |     45 // ----------------------------------------------------------------------------- | 
|         |     46 // | 
|         |     47 CGflmFileRecognizer::CGflmFileRecognizer( | 
|         |     48         CGflmDriveResolver* aDriveResolver, | 
|         |     49         RFs& aFs ) : | 
|         |     50     iCache( _FOFF( CPathTypePair, iLink ) ), | 
|         |     51     iDriveResolver( aDriveResolver ), | 
|         |     52     iFs( aFs ) | 
|         |     53     { | 
|         |     54     } | 
|         |     55  | 
|         |     56 // ----------------------------------------------------------------------------- | 
|         |     57 // CGflmFileRecognizer::ConstructL | 
|         |     58 // Symbian 2nd phase constructor can leave. | 
|         |     59 // ----------------------------------------------------------------------------- | 
|         |     60 // | 
|         |     61 void CGflmFileRecognizer::ConstructL( TInt aMemoryConsumption ) | 
|         |     62     { | 
|         |     63     User::LeaveIfError( iApaSession.Connect() ); | 
|         |     64     iMimeTypes = new( ELeave ) CDesCArraySeg( KMimeTypeGranularity ); | 
|         |     65     iCacheMaxMemoryUsage = aMemoryConsumption; | 
|         |     66  | 
|         |     67     // Get resource drive from dll location | 
|         |     68     TFileName dllFileName; | 
|         |     69     Dll::FileName( dllFileName ); | 
|         |     70     TParsePtrC dllParse( dllFileName ); | 
|         |     71  | 
|         |     72     TFileName resFileName; | 
|         |     73     resFileName.Copy( dllParse.Drive() ); | 
|         |     74     resFileName.Append( KDC_RESOURCE_FILES_DIR ); | 
|         |     75     GflmUtils::EnsureFinalBackslash( resFileName ); | 
|         |     76     resFileName.Append( KFileExtensionResourceFile ); | 
|         |     77  | 
|         |     78     RResourceFile resFile; | 
|         |     79     resFile.OpenL( iFs, resFileName ); | 
|         |     80     CleanupClosePushL( resFile ); | 
|         |     81     resFile.ConfirmSignatureL(); | 
|         |     82  | 
|         |     83     ConstructExtMimePairsL( resFile, R_EXT_MIME_PAIRS, iExtMimePairs ); | 
|         |     84     ConstructExtMimePairsL( | 
|         |     85         resFile, R_REMOTE_EXT_MIME_PAIRS, iRemoteExtMimePairs ); | 
|         |     86  | 
|         |     87     CleanupStack::PopAndDestroy( &resFile ); | 
|         |     88     } | 
|         |     89  | 
|         |     90 // ----------------------------------------------------------------------------- | 
|         |     91 // CGflmFileRecognizer::ConstructExtMimePairsL | 
|         |     92 // | 
|         |     93 // ----------------------------------------------------------------------------- | 
|         |     94 // | 
|         |     95 void CGflmFileRecognizer::ConstructExtMimePairsL( | 
|         |     96         RResourceFile& aResFile, | 
|         |     97         TInt aResId, | 
|         |     98         RPointerArray< CExtMimePair >& aPairs ) | 
|         |     99     { | 
|         |    100     // read the pairs | 
|         |    101     HBufC8* resData = aResFile.AllocReadLC( aResId ); | 
|         |    102     TResourceReader reader; | 
|         |    103     reader.SetBuffer( resData ); | 
|         |    104     TInt count( reader.ReadInt16() ); | 
|         |    105     aPairs.ReserveL( count ); | 
|         |    106     for ( TInt i( 0 ); i < count; i++ ) | 
|         |    107         { | 
|         |    108         TPtrC ext( reader.ReadTPtrC() ); | 
|         |    109         TPtrC mime( reader.ReadTPtrC() ); | 
|         |    110         CExtMimePair* pair = new (ELeave) CExtMimePair(); | 
|         |    111         CleanupStack::PushL( pair ); | 
|         |    112         pair->iExt = ext.AllocL(); | 
|         |    113         pair->iMime = mime.AllocL(); | 
|         |    114         aPairs.AppendL( pair ); | 
|         |    115         CleanupStack::Pop( pair ); | 
|         |    116         } | 
|         |    117     CleanupStack::PopAndDestroy( resData ); | 
|         |    118     } | 
|         |    119  | 
|         |    120 // ----------------------------------------------------------------------------- | 
|         |    121 // CGflmFileRecognizer::FindMimeFromExt | 
|         |    122 // | 
|         |    123 // ----------------------------------------------------------------------------- | 
|         |    124 // | 
|         |    125 TPtrC CGflmFileRecognizer::FindMimeFromExt( | 
|         |    126         const TDesC& aExt, | 
|         |    127         RPointerArray< CExtMimePair >& aPairs ) | 
|         |    128     { | 
|         |    129     TInt count( aPairs.Count() ); | 
|         |    130  | 
|         |    131     for( TInt i( 0 ); i < count; i++) | 
|         |    132         { | 
|         |    133         CExtMimePair* pair = aPairs[ i ]; | 
|         |    134         if( !aExt.CompareF( *pair->iExt ) ) | 
|         |    135             { | 
|         |    136             return TPtrC( *pair->iMime ); | 
|         |    137             } | 
|         |    138         } | 
|         |    139     return TPtrC( KNullDesC ); | 
|         |    140     } | 
|         |    141  | 
|         |    142 // ----------------------------------------------------------------------------- | 
|         |    143 // CGflmFileRecognizer::NewL | 
|         |    144 // Two-phased constructor. | 
|         |    145 // ----------------------------------------------------------------------------- | 
|         |    146 // | 
|         |    147 CGflmFileRecognizer* CGflmFileRecognizer::NewL( | 
|         |    148         RFs& aFs, | 
|         |    149         TInt aMemoryConsumption, | 
|         |    150         CGflmDriveResolver* aDriveResolver ) | 
|         |    151     { | 
|         |    152     CGflmFileRecognizer* self = | 
|         |    153         new( ELeave ) CGflmFileRecognizer( aDriveResolver, aFs ); | 
|         |    154  | 
|         |    155     CleanupStack::PushL( self ); | 
|         |    156     self->ConstructL( aMemoryConsumption ); | 
|         |    157     CleanupStack::Pop( self ); | 
|         |    158  | 
|         |    159     return self; | 
|         |    160     } | 
|         |    161  | 
|         |    162 // ----------------------------------------------------------------------------- | 
|         |    163 // CGflmFileRecognizer::~CGflmFileRecognizer | 
|         |    164 // | 
|         |    165 // ----------------------------------------------------------------------------- | 
|         |    166 // | 
|         |    167 CGflmFileRecognizer::~CGflmFileRecognizer() | 
|         |    168     { | 
|         |    169     iApaSession.Close(); | 
|         |    170  | 
|         |    171     FlushCache(); | 
|         |    172  | 
|         |    173     delete iMimeTypes; | 
|         |    174  | 
|         |    175     iExtMimePairs.ResetAndDestroy(); | 
|         |    176     iExtMimePairs.Close(); | 
|         |    177  | 
|         |    178     iRemoteExtMimePairs.ResetAndDestroy(); | 
|         |    179     iRemoteExtMimePairs.Close(); | 
|         |    180     } | 
|         |    181  | 
|         |    182 // ----------------------------------------------------------------------------- | 
|         |    183 // CGflmFileRecognizer::RecognizeL( const TDesC& aFilename ) | 
|         |    184 // (other items were commented in a header). | 
|         |    185 // ----------------------------------------------------------------------------- | 
|         |    186 // | 
|         |    187 TPtrC CGflmFileRecognizer::RecognizeL( const TDesC& aFilename ) | 
|         |    188     { | 
|         |    189     TPtrC mimeType; | 
|         |    190     TRAPD( err, mimeType.Set( DoRecognizeL( aFilename ) ) ); | 
|         |    191     if ( err == KErrNoMemory ) | 
|         |    192         { | 
|         |    193         FlushCache(); | 
|         |    194         return DoRecognizeL( aFilename ); | 
|         |    195         } | 
|         |    196     User::LeaveIfError( err ); | 
|         |    197     return mimeType; | 
|         |    198     } | 
|         |    199  | 
|         |    200 // ----------------------------------------------------------------------------- | 
|         |    201 // CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename ) | 
|         |    202 // (other items were commented in a header). | 
|         |    203 // ----------------------------------------------------------------------------- | 
|         |    204 // | 
|         |    205 TPtrC CGflmFileRecognizer::DoRecognizeL( const TDesC& aFilename ) | 
|         |    206     { | 
|         |    207     // Search the cache for a hit | 
|         |    208     TInt cropPoint( aFilename.LocateReverse( KGFLMDot()[ 0 ] ) ); | 
|         |    209     TBool isRemoteDrive( EFalse ); | 
|         |    210  | 
|         |    211     if ( iDriveResolver && iDriveResolver->IsRemoteDrive( aFilename ) ) | 
|         |    212         { | 
|         |    213         isRemoteDrive = ETrue; | 
|         |    214         } | 
|         |    215  | 
|         |    216     if( cropPoint != KErrNotFound ) | 
|         |    217         {         | 
|         |    218         TPtrC ext( aFilename.Mid( cropPoint ) ); | 
|         |    219         TPtrC mime( FindMimeFromExt( ext, iExtMimePairs ) ); | 
|         |    220         if ( mime.Length() ) | 
|         |    221             { | 
|         |    222             return mime; | 
|         |    223             } | 
|         |    224  | 
|         |    225         // Use remote drive specific extension mime pairs and skip | 
|         |    226         // content recognition because it is so slow for remote drives. | 
|         |    227         // Mime types are resolved from extension by remote storage framework | 
|         |    228         // anyway. | 
|         |    229         if ( isRemoteDrive) | 
|         |    230             { | 
|         |    231             return FindMimeFromExt( ext, iRemoteExtMimePairs ); | 
|         |    232             } | 
|         |    233         } | 
|         |    234     else if ( isRemoteDrive) | 
|         |    235         { | 
|         |    236         // Skip content recognition for remote drives because it is so slow | 
|         |    237         return TPtrC( KNullDesC ); | 
|         |    238         } | 
|         |    239  | 
|         |    240     TDblQueIter< CPathTypePair > pairIt( iCache ); | 
|         |    241     pairIt.SetToFirst(); | 
|         |    242     CPathTypePair* pair = NULL; | 
|         |    243     while ( ( pair = pairIt++ ) != NULL ) | 
|         |    244         { | 
|         |    245         TPtrC ptr( *( pair->iFilename ) ); | 
|         |    246         if( ptr.Length() == aFilename.Length() && | 
|         |    247            !aFilename.CompareF( ptr ) ) | 
|         |    248             { | 
|         |    249             // Cache hit | 
|         |    250             // Move item to the first position if not already. | 
|         |    251             // When clearing cache, oldest items can be dropped easily. | 
|         |    252             pair->iLink.Deque(); | 
|         |    253             iCache.AddFirst( *pair ); | 
|         |    254  | 
|         |    255             if ( pair->iTypeIndex != KErrNotFound ) | 
|         |    256                 { | 
|         |    257                 return iMimeTypes->MdcaPoint( pair->iTypeIndex ); | 
|         |    258                 } | 
|         |    259             return TPtrC( KNullDesC ); | 
|         |    260             } | 
|         |    261         } | 
|         |    262  | 
|         |    263         // Cache miss | 
|         |    264         TUid uid( KNullUid ); | 
|         |    265         TDataType datatype; | 
|         |    266  | 
|         |    267         TIMESTAMP( "GFLM AppForDocument started: " ) | 
|         |    268  | 
|         |    269         // Acquire the mime-type of the file | 
|         |    270         TInt err( iApaSession.AppForDocument( aFilename, uid, datatype ) ); | 
|         |    271  | 
|         |    272         TIMESTAMP( "GFLM AppForDocument ended: " ) | 
|         |    273  | 
|         |    274         if ( err != KErrNone ) | 
|         |    275             { | 
|         |    276             // If recognition returns error, handle as unrecognized file | 
|         |    277             ERROR_LOG1( | 
|         |    278                 "CGflmFileRecognizer::DoRecognizeL-AppForDocument=%d", | 
|         |    279                 err ) | 
|         |    280             return TPtrC( KNullDesC ); | 
|         |    281             } | 
|         |    282  | 
|         |    283         CPathTypePair* newPair = CPathTypePair::NewLC( aFilename ); | 
|         |    284         TPtrC mimeType( datatype.Des() ); | 
|         |    285  | 
|         |    286         INFO_LOG2( "GFLM AppForDocument:file=%S,mime=%S", &aFilename, &mimeType ) | 
|         |    287  | 
|         |    288         // Run through the mime-type list to find the correct index | 
|         |    289         if ( mimeType.Length() ) | 
|         |    290             { | 
|         |    291             TBool isMimeFound( EFalse ); | 
|         |    292             TInt mimeCount( iMimeTypes->MdcaCount() ); | 
|         |    293             for ( TInt j( 0 ); j < mimeCount; j++ ) | 
|         |    294                 { | 
|         |    295                 if( !mimeType.CompareF( iMimeTypes->MdcaPoint( j ) ) ) | 
|         |    296                     { | 
|         |    297                     newPair->iTypeIndex = j; | 
|         |    298                     isMimeFound = ETrue; | 
|         |    299                     break; | 
|         |    300                     } | 
|         |    301                 } | 
|         |    302             // Add mime type to list if not already added | 
|         |    303             if ( !isMimeFound ) | 
|         |    304                 { | 
|         |    305                 iMimeTypes->AppendL( mimeType ); | 
|         |    306                 newPair->iTypeIndex = mimeCount; | 
|         |    307                 } | 
|         |    308             } | 
|         |    309  | 
|         |    310         // Cleanup cache and add new pair | 
|         |    311         CleanupStack::Pop( newPair ); | 
|         |    312         CleanupCache(); | 
|         |    313         iCacheMemoryUsage += newPair->Size(); | 
|         |    314         iCache.AddFirst( *newPair ); | 
|         |    315  | 
|         |    316         if ( newPair->iTypeIndex != KErrNotFound ) | 
|         |    317             { | 
|         |    318             return iMimeTypes->MdcaPoint( newPair->iTypeIndex ); | 
|         |    319             } | 
|         |    320         return TPtrC( KNullDesC ); | 
|         |    321     } | 
|         |    322  | 
|         |    323 // ----------------------------------------------------------------------------- | 
|         |    324 // CGflmFileRecognizer::FlushCache( ) | 
|         |    325 // | 
|         |    326 // ----------------------------------------------------------------------------- | 
|         |    327 // | 
|         |    328 void CGflmFileRecognizer::FlushCache() | 
|         |    329     { | 
|         |    330     TDblQueIter< CPathTypePair > pairIt( iCache ); | 
|         |    331     pairIt.SetToFirst(); | 
|         |    332     CPathTypePair* pair = NULL; | 
|         |    333     while ( ( pair = pairIt++ ) != NULL ) | 
|         |    334         { | 
|         |    335         pair->iLink.Deque(); | 
|         |    336         delete pair; | 
|         |    337         } | 
|         |    338     iCacheMemoryUsage = 0; | 
|         |    339     } | 
|         |    340  | 
|         |    341 // ----------------------------------------------------------------------------- | 
|         |    342 // CGflmFileRecognizer::CleanupCache( ) | 
|         |    343 // | 
|         |    344 // ----------------------------------------------------------------------------- | 
|         |    345 // | 
|         |    346 void CGflmFileRecognizer::CleanupCache( ) | 
|         |    347     { | 
|         |    348     if( iCacheMemoryUsage > iCacheMaxMemoryUsage ) | 
|         |    349         { | 
|         |    350         TInt dropThreshold = ( TInt ) ( ( ( ( TUint ) iCacheMaxMemoryUsage ) * | 
|         |    351             KPerCentToDrop ) / KHundredPerCent ); | 
|         |    352         TInt droppedSize( 0 ); | 
|         |    353  | 
|         |    354         TDblQueIter< CPathTypePair > pairIt( iCache ); | 
|         |    355         pairIt.SetToLast(); | 
|         |    356         CPathTypePair* pair = NULL; | 
|         |    357         while ( ( pair = pairIt-- ) != NULL ) | 
|         |    358             { | 
|         |    359             droppedSize += pair->Size(); | 
|         |    360             pair->iLink.Deque(); | 
|         |    361             delete pair; | 
|         |    362             if ( droppedSize >= dropThreshold ) | 
|         |    363                 { | 
|         |    364                 break; | 
|         |    365                 } | 
|         |    366             } | 
|         |    367         iCacheMemoryUsage -= droppedSize; | 
|         |    368         } | 
|         |    369     } | 
|         |    370  | 
|         |    371 // ----------------------------------------------------------------------------- | 
|         |    372 // CGflmFileRecognizer::CPathTypePair::NewLC() | 
|         |    373 //  | 
|         |    374 // ----------------------------------------------------------------------------- | 
|         |    375 // | 
|         |    376 CGflmFileRecognizer::CPathTypePair* | 
|         |    377         CGflmFileRecognizer::CPathTypePair::NewLC( const TDesC& aFilename ) | 
|         |    378     { | 
|         |    379     CPathTypePair* self = new ( ELeave ) CPathTypePair(); | 
|         |    380     CleanupStack::PushL( self ); | 
|         |    381     self->ConstructL( aFilename ); | 
|         |    382     return self; | 
|         |    383     } | 
|         |    384  | 
|         |    385 // ----------------------------------------------------------------------------- | 
|         |    386 // CGflmFileRecognizer::CPathTypePair::ConstructL() | 
|         |    387 //  | 
|         |    388 // ----------------------------------------------------------------------------- | 
|         |    389 // | 
|         |    390 void CGflmFileRecognizer::CPathTypePair::ConstructL( const TDesC& aFilename ) | 
|         |    391     { | 
|         |    392     iFilename = aFilename.AllocL(); | 
|         |    393     } | 
|         |    394  | 
|         |    395 // ----------------------------------------------------------------------------- | 
|         |    396 // CGflmFileRecognizer::CPathTypePair::CPathTypePair() | 
|         |    397 //  | 
|         |    398 // ----------------------------------------------------------------------------- | 
|         |    399 // | 
|         |    400 CGflmFileRecognizer::CPathTypePair::CPathTypePair() : | 
|         |    401         iTypeIndex( KErrNotFound ) | 
|         |    402     { | 
|         |    403     } | 
|         |    404  | 
|         |    405 // ----------------------------------------------------------------------------- | 
|         |    406 // CGflmFileRecognizer::CPathTypePair::~CPathTypePair() | 
|         |    407 //  | 
|         |    408 // ----------------------------------------------------------------------------- | 
|         |    409 // | 
|         |    410 CGflmFileRecognizer::CPathTypePair::~CPathTypePair() | 
|         |    411     { | 
|         |    412     delete iFilename; | 
|         |    413     } | 
|         |    414  | 
|         |    415 // ----------------------------------------------------------------------------- | 
|         |    416 // CGflmFileRecognizer::CPathTypePair::Size() | 
|         |    417 //  | 
|         |    418 // ----------------------------------------------------------------------------- | 
|         |    419 // | 
|         |    420 TInt CGflmFileRecognizer::CPathTypePair::Size() const | 
|         |    421     { | 
|         |    422     return ( sizeof( TInt ) + iFilename->Size() + sizeof( TDblQueLink ) ); | 
|         |    423     } | 
|         |    424  | 
|         |    425 // ----------------------------------------------------------------------------- | 
|         |    426 // CGflmFileRecognizer::CExtMimePair::~CExtMimePair() | 
|         |    427 //  | 
|         |    428 // ----------------------------------------------------------------------------- | 
|         |    429 // | 
|         |    430 CGflmFileRecognizer::CExtMimePair::~CExtMimePair() | 
|         |    431     { | 
|         |    432     delete iExt; | 
|         |    433     delete iMime; | 
|         |    434     } | 
|         |    435  | 
|         |    436 //  End of File |