diff -r 000000000000 -r 6a9f87576119 filemanager/GFLM/src/CGflmFileRecognizer.cpp --- /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 +#include +#include +#include + + +// 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