diff -r 000000000000 -r c53acadfccc6 clfwrapper/ClientSrc/CCLFServerProxy.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clfwrapper/ClientSrc/CCLFServerProxy.cpp Mon Jan 18 20:34:07 2010 +0200 @@ -0,0 +1,1291 @@ +/* +* Copyright (c) 2002-2009 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: +* +*/ + + +// INCLUDE FILES +#include +#include +#include +#include +#include +#include +#include +#include "CLFConsts.h" +#include "CLFPanics.h" +#include "CCLFServerProxy.h" +#include "mdsutils.h" + +// CONSTANTS +const TInt KCLFDefaultBufferLength( 64 ); +const TInt KCLFDefaultArrayGranularity( 4 ); +const TInt KCLFExtensionArrayGranularity( 49 ); + +_LIT( KCLFDriveLetterFormatString, ":\\" ); +const TInt KCLFDriveC( 'C' ); + +const TInt KDelayNotityCLFGetUpdateEventMaxTimes = 30; +const TInt KCLFWrapperHarvesterEventInterval = 60; + +_LIT( KExtensionMp3, "mp3" ); +_LIT( KExtensionAac, "aac" ); +_LIT( KExtensionAmr, "amr" ); +_LIT( KExtensionAwb, "awb" ); +_LIT( KExtensionMid, "mid" ); +_LIT( KExtensionMidi, "midi" ); +_LIT( KExtensionSpMid, "spmid" ); +_LIT( KExtensionRng, "rng" ); +_LIT( KExtensionMxmf, "mxmf" ); +_LIT( KExtensionWav, "wav" ); +_LIT( KExtensionAu, "au" ); +_LIT( KExtensionWma, "wma" ); +_LIT( KExtensionNrt, "nrt" ); +_LIT( KExtensionRa, "ra" ); + +_LIT( KExtJpg, "JPG" ); +_LIT( KExtJpeg, "JPEG" ); +_LIT( KExtJp2, "JP2" ); +_LIT( KExtJ2k, "J2K" ); +_LIT( KExtJpx, "JPX" ); +_LIT( KExtJpf, "JPF" ); +_LIT( KExtMbm, "MBM" ); +_LIT( KExtPng, "PNG" ); +_LIT( KExtGif, "GIF" ); +_LIT( KExtBmp, "BMP" ); +_LIT( KExtTif, "TIF" ); +_LIT( KExtTiff, "TIFF" ); +_LIT( KExtOta, "OTA" ); +_LIT( KExtWbmp, "WBMP" ); +_LIT( KExtWmf, "WMF" ); +_LIT( KExtOtb, "OTB" ); + +_LIT(KExtOma1, "dcf"); +_LIT(KExtOma2, "odf"); +_LIT(KExtOma3, "dm"); +_LIT(KExtOma4, "o4a"); +_LIT(KExtOma5, "o4v"); + +_LIT( KExtensionMp4, "mp4" ); +_LIT( KExtensionMpg4, "mpg4" ); +_LIT( KExtensionMpeg4, "mpeg4" ); +_LIT( KExtensionM4v, "m4v" ); +_LIT( KExtensionM4a, "m4a" ); +_LIT( KExtension3gp, "3gp" ); +_LIT( KExtension3gpp, "3gpp" ); +_LIT( KExtension3g2, "3g2" ); +_LIT( KExtensionRm, "rm" ); +_LIT( KExtensionRmvb, "rmvb" ); +_LIT( KExtensionRam, "ram" ); +_LIT( KExtensionRv, "rv" ); +_LIT( KExtensionWmv, "wmv" ); +_LIT( KExtensionAvi, "avi" ); + +// ======== MEMBER FUNCTIONS ======== + +// ----------------------------------------------------------------------------- +// CItemsDeletedHandler::CUpdateItemsHandler +// ----------------------------------------------------------------------------- +// +inline CUpdateItemsHandler::CUpdateItemsHandler() + : iWasNotificationHandled( EFalse ), iParentObserver( NULL ), + iParentPresentObserver( NULL ), iRemoveObserver( EFalse ) + { + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::Start +// ----------------------------------------------------------------------------- +// +void CUpdateItemsHandler::StartScheduler() + { + if( !iScheduler.IsStarted() ) + { + iScheduler.Start(); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::AsyncStop +// ----------------------------------------------------------------------------- +// +void CUpdateItemsHandler::AsyncStopScheduler() + { + iScheduler.AsyncStop(); + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::WasNotificationHandled +// ----------------------------------------------------------------------------- +// +TBool CUpdateItemsHandler::WasNotificationHandled() const + { + return iWasNotificationHandled; + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::WasNotificationHandled +// ----------------------------------------------------------------------------- +// +void CUpdateItemsHandler::SetRemoveObserverFlag( TBool aRemove ) + { + iRemoveObserver = aRemove; + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::NewL +// ----------------------------------------------------------------------------- +// +CUpdateIDsHandler* CUpdateIDsHandler::NewL( const TArray< TCLFItemId >& aItemIDArray ) + { + CUpdateIDsHandler* self = new( ELeave ) CUpdateIDsHandler( aItemIDArray ); + + return self; + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::~CUpdateIDsHandler +// ----------------------------------------------------------------------------- +// +CUpdateIDsHandler::~CUpdateIDsHandler() + { + iIdsPendingUpdate.Reset(); + + if ( iScheduler.IsStarted() ) + { + iScheduler.AsyncStop(); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::~CUpdateFoldersHandler +// ----------------------------------------------------------------------------- +// +void CUpdateIDsHandler::StartHandlingL() + { + // Pass through. + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::HandleObjectNotification +// ----------------------------------------------------------------------------- +// +void CUpdateIDsHandler::HandleObjectNotification( const TItemId aId, TObserverNotificationType /* aType */ ) + { + iWasNotificationHandled = EFalse; + + TInt index = iIdsPendingUpdate.Find( aId ); + if ( index != KErrNotFound ) + { + iWasNotificationHandled = ETrue; + iIdsPendingUpdate.Remove( index ); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::AllDone +// ----------------------------------------------------------------------------- +// +TBool CUpdateIDsHandler::AllDone() const + { + return iIdsPendingUpdate.Count() == 0 ? ETrue : EFalse; + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::CUpdateIDsHandler +// ----------------------------------------------------------------------------- +// +inline CUpdateIDsHandler::CUpdateIDsHandler( const TArray< TCLFItemId >& aItemIDArray ) + { + const TInt idCount( aItemIDArray.Count() ); + for ( TInt i = 0; i < idCount; ++i ) + { + if ( iIdsPendingUpdate.Find( aItemIDArray[ i ] ) == KErrNotFound ) + { + iIdsPendingUpdate.Append( aItemIDArray[ i ] ); + } + } + } + +// ----------------------------------------------------------------------------- +// CItemsDeletedHandler::NewL +// ----------------------------------------------------------------------------- +// +CItemsDeletedHandler* CItemsDeletedHandler::NewL( CMdESession& aMdESession, + const CDesCArray& aUriArray, + MMdEObjectObserver* aParentObserver, + MMdEObjectPresentObserver* aParentPresentObserver ) + { + CItemsDeletedHandler* self = new( ELeave ) CItemsDeletedHandler( aMdESession ); + CleanupStack::PushL( self ); + self->ConstructL( aUriArray, aParentObserver, aParentPresentObserver ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CItemsDeletedHandler::~CUpdateItemsHandlerWithIDs +// ----------------------------------------------------------------------------- +// +CItemsDeletedHandler::~CItemsDeletedHandler() + { + if( iRemoveObserver ) + { + TRAP_IGNORE( iMdESession.RemoveObjectObserverL( *iParentObserver ) ); + TRAP_IGNORE( iMdESession.RemoveObjectPresentObserverL( *iParentPresentObserver ) ); + } + iIdsPendingRemoval.Reset(); + iObjectsPendingRemoval.ResetAndDestroy(); + + if ( iScheduler.IsStarted() ) + { + iScheduler.AsyncStop(); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::StartHandlingL +// ----------------------------------------------------------------------------- +// +void CItemsDeletedHandler::StartHandlingL() + { + const TInt count( iObjectsPendingRemoval.Count() ); + for ( TInt i = 0; i < count; ++i ) + { + // If object for URI to be removed is in MDS, then remove it from MDS. Obviates + // the need to rely on unreliable filemonitorplugin. + const TItemId id = iMdESession.RemoveObjectL( iObjectsPendingRemoval[ i ]->Id() ); + + if ( id != KNoId ) + { + iIdsPendingRemoval.Append( id ); + } + } + iObjectsPendingRemoval.ResetAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// CItemsDeletedHandler::HandleObjectNotification +// ----------------------------------------------------------------------------- +// +void CItemsDeletedHandler::HandleObjectNotification( const TItemId aId, TObserverNotificationType aType ) + { + iWasNotificationHandled = EFalse; + + if ( aType == ENotifyRemove ) + { + TInt index = iIdsPendingRemoval.Find( aId ); + if ( index != KErrNotFound ) + { + iWasNotificationHandled = ETrue; + iIdsPendingRemoval.Remove( index ); + } + } + } + +// ----------------------------------------------------------------------------- +// CUpdateIDsHandler::AllDone +// ----------------------------------------------------------------------------- +// +TBool CItemsDeletedHandler::AllDone() const + { + return iIdsPendingRemoval.Count() == 0 ? ETrue : EFalse; + } + +// ----------------------------------------------------------------------------- +// CItemsDeletedHandler::CItemsDeletedHandler +// ----------------------------------------------------------------------------- +// +inline CItemsDeletedHandler::CItemsDeletedHandler( CMdESession& aMdESession ) + : iMdESession( aMdESession ) + { + } + +// ----------------------------------------------------------------------------- +// CItemsDeletedHandler::ConstructL +// ----------------------------------------------------------------------------- +// +inline void CItemsDeletedHandler::ConstructL( const CDesCArray& aUriArray, + MMdEObjectObserver* aParentObserver, + MMdEObjectPresentObserver* aParentPresentObserver) + { + iParentObserver = aParentObserver; + iParentPresentObserver = aParentPresentObserver; + // This leave is needed, if the handler was deleted earlier and the parent observer was removed + TRAP_IGNORE( iMdESession.AddObjectObserverL( *iParentObserver ) ); + TRAP_IGNORE( iMdESession.AddObjectPresentObserverL( *iParentPresentObserver ) ); + const TInt uriCount( aUriArray.Count() ); + for ( TInt i = 0; i < uriCount; ++i ) + { + CMdEObject* object = NULL; + + object = iMdESession.GetObjectL( aUriArray.MdcaPoint( i )); + CleanupStack::PushL( object ); + if ( object ) + { + iObjectsPendingRemoval.AppendL( object ); + } + CleanupStack::Pop( object ); + } + iRemoveObserver = ETrue; + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::NewL +// ----------------------------------------------------------------------------- +// +CUpdateFoldersHandler* CUpdateFoldersHandler::NewL( CMdESession& aMdESession, const CDesCArray& aUriArray, + MMdEObjectObserver* aParentObserver, + MMdEObjectPresentObserver* aParentPresentObserver, + RFs& aFs, + RHarvesterClient& aHarvester, + CDesCArray* aSupportedTypes ) + { + CUpdateFoldersHandler* self = new( ELeave ) CUpdateFoldersHandler( aMdESession, + aFs, aHarvester, aSupportedTypes ); + CleanupStack::PushL( self ); + self->ConstructL( aUriArray, aParentObserver, aParentPresentObserver ); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::~CUpdateFoldersHandler +// ----------------------------------------------------------------------------- +// +CUpdateFoldersHandler::~CUpdateFoldersHandler() + { + if( iRemoveObserver ) + { + TRAP_IGNORE( iMdESession.RemoveObjectObserverL( *iParentObserver ) ); + TRAP_IGNORE( iMdESession.RemoveObjectPresentObserverL( *iParentPresentObserver ) ); + } + iUrisFound.Reset(); + iFoldersFound.Reset(); + iIdsPendingRemoval.Reset(); + iIdsPendingUpdate.Reset(); + iIdsHandled.Reset(); + + if ( iScheduler.IsStarted() ) + { + iScheduler.AsyncStop(); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::StartHandlingL +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::StartHandlingL() + { + CMdEObjectQuery* query = NULL; + + iIdsPendingRemoval.Reset(); + iIdsPendingUpdate.Reset(); + iIdsHandled.Reset(); + + iStartingHandling = ETrue; + DoQueryL( query, iFoldersFound ); + CleanupStack::PushL( query ); + if( !iScheduler.IsStarted() ) + { + iScheduler.Start(); + } + TRAP_IGNORE( DetermineIdsToRemoveL( *query ) ); + TRAP_IGNORE( DetermineIdsToUpdateL( iUrisFound ) ); + CleanupStack::PopAndDestroy( query ); + iStartingHandling = EFalse; + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::HandleObjectNotification +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::HandleObjectNotification( const TItemId aId, TObserverNotificationType aType ) + { + iWasNotificationHandled = EFalse; + + if ( aType == ENotifyRemove ) + { + const TInt index = iIdsPendingRemoval.Find( aId ); + + if ( index != KErrNotFound ) + { + iIdsPendingRemoval.Remove( index ); + iWasNotificationHandled = ETrue; + } + } + else if ( aType == ENotifyAdd || aType == ENotifyModify ) + { + const TInt index = iIdsPendingUpdate.Find( aId ); + + if ( index != KErrNotFound ) + { + iIdsPendingUpdate.Remove( index ); + const TInt handledIndex = iIdsHandled.Find( aId ); + if( handledIndex != KErrNotFound ) + { + iIdsHandled.Remove( handledIndex ); + } + iWasNotificationHandled = ETrue; + } + else if( iHarvestingOngoing ) + { + iIdsHandled.Append( aId ); + iWasNotificationHandled = ETrue; + } + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::AllDone +// ----------------------------------------------------------------------------- +// +TBool CUpdateFoldersHandler::AllDone() const + { + return ( iIdsPendingRemoval.Count() == 0 && + iIdsPendingUpdate.Count() == 0 && + !iStartingHandling ) ? ETrue : EFalse; + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::HandleQueryNewResults +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::HandleQueryNewResults( CMdEQuery& /* aQuery */, TInt /* aFirstNewItemIndex */, TInt /* aNewItemCount */ ) + { + // Pass through. + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::HandleQueryCompleted +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::HandleQueryCompleted( CMdEQuery& /* aQuery */, TInt /* aError */ ) + { + iScheduler.AsyncStop(); + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::CUpdateFoldersHandler +// ----------------------------------------------------------------------------- +// +inline CUpdateFoldersHandler::CUpdateFoldersHandler( CMdESession& aMdESession, + RFs& aFs, + RHarvesterClient& aHarvester, + CDesCArray* aSupportedTypes ) + : iFs( aFs ), + iUrisFound( KCLFDefaultArrayGranularity ), + iFoldersFound( KCLFDefaultArrayGranularity ), + iMdESession( aMdESession ), + iHarvester( aHarvester ), + iHarvestError( KErrNone ), + iStartingHandling( EFalse ), + iExtensionArray( aSupportedTypes ), + iHarvestingOngoing( EFalse ) + { + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::ConstructL +// ----------------------------------------------------------------------------- +// +inline void CUpdateFoldersHandler::ConstructL( const CDesCArray& aUriArray, + MMdEObjectObserver* aParentObserver, + MMdEObjectPresentObserver* aParentPresentObserver ) + { + iParentObserver = aParentObserver; + iParentPresentObserver = aParentPresentObserver; + // This leave is needed, if the handler was deleted earlier and the parent observer was removed + TRAP_IGNORE( iMdESession.AddObjectObserverL( *iParentObserver ) ); + TRAP_IGNORE( iMdESession.AddObjectPresentObserverL( *iParentPresentObserver ) ); + + for ( TInt i = 0; i < aUriArray.MdcaCount(); ++i ) + { + ScanNodeForUrisL( aUriArray.MdcaPoint( i ), iUrisFound, iFoldersFound ); + } + + iRemoveObserver = ETrue ; + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::ScanNodeForUrisL +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::ScanNodeForUrisL( const TDesC16& aNodeName, CDesCArray& aUriArray, CDesCArray& aFolderArray ) + { + TBool isFolder = EFalse; + + BaflUtils::IsFolder( iFs, aNodeName, isFolder ); + if ( isFolder ) + { + if ( !BaflUtils::FolderExists( iFs, aNodeName ) ) + { + return; + } + CDirScan* dirscan = CDirScan::NewL( iFs ); + CDir* dir = NULL; + + CleanupStack::PushL( dirscan ); + dirscan->SetScanDataL( aNodeName, KEntryAttNormal, EDirsAnyOrder ); + + for ( dirscan->NextL( dir ); dir; dirscan->NextL( dir ) ) + { + CleanupStack::PushL( dir ); + + for ( TInt i = 0 ; i < dir->Count() ; ++i ) + { + const TEntry& entry = ( *dir )[ i ]; + const TInt totalLength = entry.iName.Length() + dirscan->FullPath().Length() + 1; + + if (( !entry.IsDir() ) && ( totalLength <= KMaxFileName )) + { + TFileName currentPath( dirscan->FullPath() ); + currentPath.Append( ( *dir )[ i ].iName ); + aUriArray.AppendL( currentPath ); + } + } + CleanupStack::PopAndDestroy( dir ); + + } + aFolderArray.AppendL( aNodeName ); + + CleanupStack::PopAndDestroy( dirscan ); + } + else + { + aUriArray.AppendL( aNodeName ); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::DetermineIdsToRemove +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::DetermineIdsToRemoveL ( const CMdEObjectQuery& aQuery ) + { + RProcess process( KCurrentProcessHandle ); + process.Id().Id(); + if( process.HasCapability( ECapabilityWriteDeviceData ) ) + { + const TInt queryCount( aQuery.Count() ); + for ( TInt i = 0; i < queryCount; ++i ) + { + CMdEObject& object = aQuery.Result( i ); + TEntry entry; + const TInt err = iFs.Entry( object.Uri(), entry ); + + if ( err == KErrNotFound ) + { + // Queried metadata object has a URI that does not match a filesystem URI. + // It must therefore be removed. + TItemId id( KNoId ); + id = iMdESession.RemoveObjectL( object.Id() ); + if ( id != KNoId ) + { + iIdsPendingRemoval.Append( id ); + } + } + } + } + process.Close(); + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::DetermineIdsToRemove +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::DetermineIdsToUpdateL ( const CDesCArray& aUriArray ) + { + const TInt uriCount( aUriArray.Count() ); + for ( TInt i = 0; i < uriCount; ++i ) + { + CMdEObject* object = NULL; + const TDesC& uri = aUriArray.MdcaPoint( i ); + TPtrC ext; + const TBool exists( MdsUtils::GetExt( uri, ext ) ); + if( !exists || !IsSupportedType( ext ) ) + { + return; + } + + object = iMdESession.GetObjectL( uri ); + CleanupStack::PushL( object ); + + if ( !object ) + { + // If object for given URI is not in MDS, then determine if an ENotifyAdd + // or ENotifyModify is pending by attempting to harvest the file associated + // with the URI. + DoHarvestL( uri ); + } + CleanupStack::PopAndDestroy( object ); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::DoQueryL +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::DoQueryL( CMdEObjectQuery*& aQuery, const CDesCArray& aFolderArray ) + { + CMdENamespaceDef& defaultNamespaceDef = iMdESession.GetDefaultNamespaceDefL(); + CMdEObjectDef& objDef = defaultNamespaceDef.GetObjectDefL( MdeConstants::Object::KBaseObject ); + aQuery = iMdESession.NewObjectQueryL( iMdESession.GetDefaultNamespaceDefL(), objDef, this ); + CleanupStack::PushL( aQuery ); + CMdELogicCondition& uriLogicCond = aQuery->Conditions().AddLogicConditionL( ELogicConditionOperatorOr ); + + const TInt folderCount( aFolderArray.Count() ); + for ( TInt i = 0; i < folderCount; ++i ) + { + uriLogicCond.AddObjectConditionL( EObjectConditionCompareUriBeginsWith, aFolderArray.MdcaPoint( i ) ); + } + aQuery->FindL(); + + CleanupStack::Pop( aQuery ); // Caller takes ownership. + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::DoHarvest +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::DoHarvestL( const TDesC& aUri ) + { + RArray< TItemId > albumIds; + + TUid uid( KNullUid ); + iHarvester.SetObserver( this ); + iHarvestingFile = TFileName( aUri ); + iHarvestingOngoing = ETrue; + iHarvester.HarvestFileWithUID( aUri, albumIds, EFalse, uid ); + if( !iScheduler.IsStarted() ) + { + iScheduler.Start(); + } + + albumIds.Close(); + + // Wait until harvest complete before trying again. + iHarvester.RemoveObserver( this ); + if ( iHarvestError == KErrNone ) + { + CMdEObject* object = NULL; + + object = iMdESession.GetObjectL( aUri ); + if( object ) + { + const TInt index = iIdsHandled.Find( object->Id() ); + if( index != KErrNotFound ) + { + iIdsHandled.Remove( index ); + } + else + { + iIdsPendingUpdate.Append( object->Id() ); + } + } + } + + iHarvestError = KErrNone; + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::HarvestingComplete +// Callback from harvester client after harvesting +// ----------------------------------------------------------------------------- +// +void CUpdateFoldersHandler::HarvestingComplete( TDesC& aURI, const TInt aError ) + { + const TFileName uri( aURI ); + TBool match( EFalse ); + TCollationMethod m = *Mem::CollationMethodByIndex( 0 ); + + iHarvestError = aError; + m.iFlags = ( TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase ); + + if ( uri.CompareC( iHarvestingFile, 3, &m ) == 0 ) + { + match = ETrue; + iHarvestingOngoing = EFalse; + } + if ( iScheduler.IsStarted() && match ) + { + iScheduler.AsyncStop(); + } + } + +// ----------------------------------------------------------------------------- +// CUpdateFoldersHandler::IsSupportedType +// ----------------------------------------------------------------------------- +// +TBool CUpdateFoldersHandler::IsSupportedType( const TDesC& aExtension ) + { + TCollationMethod m = *Mem::CollationMethodByIndex( 0 ); + m.iFlags = ( TCollationMethod::EIgnoreNone | TCollationMethod::EFoldCase ); + + for( TInt i( 0 ); i < iExtensionArray->Count(); i++ ) + { + const TDesC& ext = iExtensionArray->MdcaPoint( i ); + if ( ext.CompareC( aExtension, 3, &m ) == 0 ) + { + return ETrue; + } + } + return EFalse; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::~CCLFServerProxy +// Destructor. +// ----------------------------------------------------------------------------- +// +CCLFServerProxy::~CCLFServerProxy() + { + // Reset the arrays this class owns. + iStatusArray.Reset(); + iOpCodeArray.Reset(); + iUpdatedIds.Reset(); + TRAP_IGNORE( iMdESession.RemoveObjectObserverL( *this )); + TRAP_IGNORE( iMdESession.RemoveObjectPresentObserverL( *this )); + iUpdateItemsHandlerArray.ResetAndDestroy(); + delete iUriArray; + delete iExtensionArray; + iFs.Close(); + + iHC.RemoveHarvesterEventObserver( *this ); + iHC.Close(); + } + +// ----------------------------------------------------------------------------- +// CCLFDbItemProvider::NewL +// ----------------------------------------------------------------------------- +// +CCLFServerProxy* CCLFServerProxy::NewL( CMdESession& aMdESession ) + { + CCLFServerProxy* self = new( ELeave ) CCLFServerProxy( aMdESession ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::GetUpdateEndEvent +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::GetUpdateEndEvent( TRequestStatus& aRequestStatus ) + { + GetEvent( aRequestStatus, ECLFGetUpdateEvent ); + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::CancelEventGets +// ----------------------------------------------------------------------------- +// +TInt CCLFServerProxy::CancelGetEvent() + { + CancelGetEvent( ECLFGetUpdateEvent ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::GetUpdateStartEvent +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::GetUpdateStartEvent( TRequestStatus& aRequestStatus ) + { + GetEvent( aRequestStatus, ECLFProcessStartEvent ); + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::CancelGetUpdateStartEvent +// ----------------------------------------------------------------------------- +// +TInt CCLFServerProxy::CancelGetUpdateStartEvent() + { + CancelGetEvent( ECLFProcessStartEvent ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::FetchItemListData +// ----------------------------------------------------------------------------- +// +TInt CCLFServerProxy::FetchItemListData( RArray< TCLFItemId >& aItemIDArray ) + { + const TInt count( iUpdatedIds.Count() ); + for ( TInt i = 0; i < count; ++i ) + { + aItemIDArray.Append( iUpdatedIds[ i ] ); + } + + iUpdatedIds.Reset(); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::UpdateItems +// ----------------------------------------------------------------------------- +// +TInt CCLFServerProxy::UpdateItemsL( const TArray< TCLFItemId >& aItemIDArray ) + { + CUpdateItemsHandler* handler = CUpdateIDsHandler::NewL( aItemIDArray ); + + CleanupStack::PushL( handler ); + StartHandlingL( handler ); + CleanupStack::Pop( handler ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::UpdateItems +// ----------------------------------------------------------------------------- +// +TInt CCLFServerProxy::UpdateItemsL( const TInt aSemanticId, const TDesC8& aOpaqueData ) + { + CDesCArray* uriArray = new ( ELeave ) CDesCArraySeg( KCLFDefaultArrayGranularity ); + CleanupStack::PushL( uriArray ); + DeSerializeL( aOpaqueData, *uriArray ); + + if ( uriArray->Count() ) + { + CUpdateItemsHandler* handler = NULL; + + if ( aSemanticId == KCLFItemsDeletedSemanticId ) + { + handler = CItemsDeletedHandler::NewL( iMdESession, *uriArray, this, this ); + } + else if ( aSemanticId == KCLFUpdateFoldersSemanticId ) + { + handler = CUpdateFoldersHandler::NewL( iMdESession, *uriArray, this, this, + iFs, iHC, iExtensionArray ); + } + else if ( aSemanticId == KCLFUpdateCollectionsSemanticId ) + { + // Pass through; collections are not supported. + CleanupStack::PopAndDestroy( uriArray ); + return KErrNone; + } + + CleanupStack::PushL( handler ); + StartHandlingL( handler ); + CleanupStack::Pop( handler ); + } + CleanupStack::PopAndDestroy( uriArray ); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::UpdateAllItems +// ----------------------------------------------------------------------------- +// +TInt CCLFServerProxy::UpdateAllItemsL() + { + CUpdateItemsHandler* handler = CUpdateFoldersHandler::NewL( iMdESession, + *iUriArray, this, this, iFs, iHC, iExtensionArray ); + CleanupStack::PushL( handler ); + StartHandlingL( handler ); + CleanupStack::Pop( handler ); + + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Default constructor +// --------------------------------------------------------------------------- +// +inline CCLFServerProxy::CCLFServerProxy( CMdESession& aMdESession ) + : iMdESession( aMdESession ), + iUriArray( NULL ), + iExtensionArray( NULL ), + iHEStateFinished( ETrue ), + iNeedNotifyCLFGetUpdateEvent( EFalse ), + iDelayNotifyCLFGetUpdateEventCount( 0 ) + { + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::ConstructL +// ----------------------------------------------------------------------------- +// +inline void CCLFServerProxy::ConstructL() + { + iUriArray = new ( ELeave ) CDesCArraySeg( KCLFDefaultArrayGranularity ); + User::LeaveIfError( iFs.Connect() ); + + TDriveList driveList; + TChar driveLetter; + TInt numOfElements( 0 ); + User::LeaveIfError( DriveInfo::GetUserVisibleDrives( iFs, + driveList, + numOfElements, + KDriveAttExclude | KDriveAttRemote | KDriveAttRom ) ); + + for( TInt driveNumber = EDriveA ; driveNumber <= EDriveZ ; driveNumber++ ) + { + if ( driveList[driveNumber] ) + { + User::LeaveIfError( iFs.DriveToChar( driveNumber, driveLetter ) ); + HBufC* letter = HBufC::NewLC( KMaxPath ); + TPtr letterPtr( letter->Des() ); + + if( driveLetter == KCLFDriveC ) + { + letterPtr = PathInfo::PhoneMemoryRootPath(); + } + else + { + letterPtr.Append( driveLetter ); + letterPtr.Append( KCLFDriveLetterFormatString ); + } + + if( BaflUtils::PathExists( iFs, letterPtr ) ) + { + iUriArray->AppendL( letterPtr ); + } + CleanupStack::PopAndDestroy( letter ); + } + } + + PopulateSupportedExtensionL(); + + iMdESession.AddObjectObserverL( *this ); + iMdESession.AddObjectPresentObserverL( *this ); + + User::LeaveIfError( iHC.Connect() ); + iHC.AddHarvesterEventObserver( *this, EHEObserverTypeOverall, KCLFWrapperHarvesterEventInterval ); + + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::HarvestingUpdated +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::HarvestingUpdated( + HarvesterEventObserverType /*aHEObserverType*/, + HarvesterEventState aHarvesterEventState, + TInt /*aItemsLeft*/ ) + { + if( aHarvesterEventState == EHEStateFinished || + aHarvesterEventState == EHEStatePaused ) + { + iHEStateFinished = ETrue; + if ( iNeedNotifyCLFGetUpdateEvent ) + { + NotifyUpdateEvent( ECLFGetUpdateEvent ); + } + } + else + { + iHEStateFinished = EFalse; + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::StartHandlingL +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::StartHandlingL( CUpdateItemsHandler* aHandler ) + { + if ( aHandler ) + { + // Notify pending active objects about the event. + NotifyUpdateEvent( ECLFProcessStartEvent ); + + // Now wait until the update is over, then return. + iUpdateItemsHandlerArray.Append( aHandler ); + TRAPD( err, aHandler->StartHandlingL(); ); + if( err != KErrNone ) + { + // Remove aHandler, because it is in clean up stack. + iUpdateItemsHandlerArray.Remove( iUpdateItemsHandlerArray.Count() - 1 ); + User::LeaveIfError( err ); + } + if ( aHandler->AllDone() ) + { + delete aHandler; + iUpdateItemsHandlerArray.Remove( iUpdateItemsHandlerArray.Count() - 1 ); + } + else + { + aHandler->StartScheduler(); + } + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::HandleObjectNotification +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::HandleObjectNotification( CMdESession& /*aSession*/, + TObserverNotificationType aType, + const RArray< TItemId >& aObjectIdArray ) + { + TBool unhandledIds = EFalse; + + const TInt objectCount( aObjectIdArray.Count() ); + for ( TInt i = 0; i < objectCount; ++i ) + { + TBool handled = EFalse; + + iUpdatedIds.Append( aObjectIdArray[ i ] ); + for ( TInt j = 0; j < iUpdateItemsHandlerArray.Count(); ++j ) + { + iUpdateItemsHandlerArray[ j ]->HandleObjectNotification( aObjectIdArray[ i ], aType ); + handled = handled ? ETrue : iUpdateItemsHandlerArray[ j ]->WasNotificationHandled(); + + if ( iUpdateItemsHandlerArray[ j ]->AllDone() ) + { + // If we have a pending update, we can now let it continue. + iDelayNotifyCLFGetUpdateEventCount = KDelayNotityCLFGetUpdateEventMaxTimes; + NotifyUpdateEvent( ECLFGetUpdateEvent ); + iUpdateItemsHandlerArray[ j ]->AsyncStopScheduler(); + iUpdateItemsHandlerArray[j]->SetRemoveObserverFlag( EFalse ); + delete iUpdateItemsHandlerArray[ j ]; + iUpdateItemsHandlerArray.Remove( j ); + j--; // Compensate for the removed handler + } + } + unhandledIds = ( unhandledIds || !handled ) ? ETrue : EFalse; + } + + if ( unhandledIds ) + { + // If we have an ID that doesn't match a pending update, we assume + // that the object notification was generated from outside the current + // application, and we therefore must simulate a process end event. + if( aType == ENotifyRemove ) + { + // Increase the update triggering value more rapidly to provide remove events faster + iDelayNotifyCLFGetUpdateEventCount += 12; + } + NotifyUpdateEvent( ECLFGetUpdateEvent ); + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::MMdEObjectPresentObserver +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::HandleObjectPresentNotification( CMdESession& /*aSession*/, + TBool /*aPresent*/, + const RArray< TItemId >& aObjectIdArray ) + { + TBool unhandledIds = EFalse; + + const TInt objectCount( aObjectIdArray.Count() ); + for ( TInt i = 0; i < objectCount; ++i ) + { + TBool handled = EFalse; + + iUpdatedIds.Append( aObjectIdArray[ i ] ); + for ( TInt j = 0; j < iUpdateItemsHandlerArray.Count(); ++j ) + { + iUpdateItemsHandlerArray[ j ]->HandleObjectNotification( aObjectIdArray[ i ], ENotifyModify ); + handled = handled ? ETrue : iUpdateItemsHandlerArray[ j ]->WasNotificationHandled(); + + if ( iUpdateItemsHandlerArray[ j ]->AllDone() ) + { + // If we have a pending update, we can now let it continue. + NotifyUpdateEvent( ECLFGetUpdateEvent ); + iUpdateItemsHandlerArray[ j ]->AsyncStopScheduler(); + iUpdateItemsHandlerArray[j]->SetRemoveObserverFlag( EFalse ); + delete iUpdateItemsHandlerArray[ j ]; + iUpdateItemsHandlerArray.Remove( j ); + j--; // Compensate for the removed handler + } + } + unhandledIds = ( unhandledIds || !handled ) ? ETrue : EFalse; + } + + if ( unhandledIds ) + { + // If we have an ID that doesn't match a pending update, we assume + // that the object notification was generated from outside the current + // application, and we therefore must simulate a process end event. + NotifyUpdateEvent( ECLFGetUpdateEvent ); + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::NotifyUpdateEvent +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::NotifyUpdateEvent( const TCLFServerOpCodes aOpCode ) + { + + if ( ECLFGetUpdateEvent == aOpCode + && !iHEStateFinished + && iDelayNotifyCLFGetUpdateEventCount < KDelayNotityCLFGetUpdateEventMaxTimes ) + { + iNeedNotifyCLFGetUpdateEvent = ETrue; + iDelayNotifyCLFGetUpdateEventCount++; + return; + } + + for ( TInt i = 0; i < iOpCodeArray.Count(); ++i ) + { + if ( iOpCodeArray[ i ] == aOpCode ) + { + User::RequestComplete( iStatusArray[ i ], KErrNone ); + iStatusArray.Remove( i ); + iOpCodeArray.Remove( i ); + } + } + + if ( ECLFGetUpdateEvent == aOpCode ) + { + iNeedNotifyCLFGetUpdateEvent = EFalse; + iDelayNotifyCLFGetUpdateEventCount = 0; + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::DeSerializeL +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::DeSerializeL( const TDesC8& aData, CDesCArray& aDataArray ) + { + // Check if KNullDesC + if ( aData.Length() > 0 ) + { + RDesReadStream readStream( aData ); + CleanupClosePushL( readStream ); + const TInt count( readStream.ReadInt32L() ); + + HBufC* buffer = HBufC::NewLC( KCLFDefaultBufferLength ); + TPtr ptr( buffer->Des() ); + for ( TInt i = 0 ; i < count ; ++i ) + { + const TInt length( readStream.ReadInt32L() ); + const TUint uintLength( length ); + const TInt maxLength( KMaxTInt / 2 ); + if (( length < 0 ) || ( uintLength > maxLength )) + { + User::Leave( KErrNotSupported ); + } + else if ( length > ptr.MaxLength() ) + { + // create new buffer + CleanupStack::PopAndDestroy( buffer ); + buffer = HBufC::NewLC( length ); + ptr.Set( buffer->Des() ); + } + else + { + ptr.Zero(); + } + readStream.ReadL( ptr, length ); + aDataArray.AppendL( ptr ); + } + CleanupStack::PopAndDestroy( 2, &readStream ); + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::GetEvent +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::GetEvent( TRequestStatus& aRequestStatus, TCLFServerOpCodes aOpcode ) + { + iStatusArray.Append( &aRequestStatus ); + iOpCodeArray.Append( aOpcode ); + aRequestStatus = KRequestPending; + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::CancelGetEvent +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::CancelGetEvent( TCLFServerOpCodes aOpcode ) + { + for ( TInt i = 0; i < iStatusArray.Count(); ++i ) + { + if ( iOpCodeArray[ i ] == aOpcode ) + { + User::RequestComplete( iStatusArray[ i ], KErrCancel ); + iStatusArray.Remove( i ); + iOpCodeArray.Remove( i ); + } + } + } + +// ----------------------------------------------------------------------------- +// CCLFServerProxy::PopulateSupportedExtensionL +// ----------------------------------------------------------------------------- +// +void CCLFServerProxy::PopulateSupportedExtensionL() + { + iExtensionArray = new ( ELeave ) CDesCArraySeg( KCLFExtensionArrayGranularity ); + iExtensionArray->AppendL( KExtensionMp3 ); + iExtensionArray->AppendL( KExtensionAac ); + iExtensionArray->AppendL( KExtensionAmr ); + iExtensionArray->AppendL( KExtensionAwb ); + iExtensionArray->AppendL( KExtensionMid ); + iExtensionArray->AppendL( KExtensionMidi ); + iExtensionArray->AppendL( KExtensionSpMid ); + iExtensionArray->AppendL( KExtensionRng ); + iExtensionArray->AppendL( KExtensionMxmf ); + iExtensionArray->AppendL( KExtensionWav ); + iExtensionArray->AppendL( KExtensionAu ); + iExtensionArray->AppendL( KExtensionNrt ); + iExtensionArray->AppendL( KExtensionWma ); + iExtensionArray->AppendL( KExtensionRa ); + + iExtensionArray->AppendL( KExtJpg ); + iExtensionArray->AppendL( KExtJpeg ); + iExtensionArray->AppendL( KExtJp2 ); + iExtensionArray->AppendL( KExtJ2k ); + iExtensionArray->AppendL( KExtJpx ); + iExtensionArray->AppendL( KExtJpf ); + iExtensionArray->AppendL( KExtMbm ); + iExtensionArray->AppendL( KExtPng ); + iExtensionArray->AppendL( KExtGif ); + iExtensionArray->AppendL( KExtBmp ); + iExtensionArray->AppendL( KExtTif ); + iExtensionArray->AppendL( KExtTiff ); + iExtensionArray->AppendL( KExtOta ); + iExtensionArray->AppendL( KExtWbmp ); + iExtensionArray->AppendL( KExtWmf ); + iExtensionArray->AppendL( KExtOtb ); + + iExtensionArray->AppendL( KExtOma1 ); + iExtensionArray->AppendL( KExtOma2 ); + iExtensionArray->AppendL( KExtOma3 ); + iExtensionArray->AppendL( KExtOma4 ); + iExtensionArray->AppendL( KExtOma5 ); + + iExtensionArray->AppendL( KExtensionMp4 ); + iExtensionArray->AppendL( KExtensionMpg4 ); + iExtensionArray->AppendL( KExtensionMpeg4 ); + iExtensionArray->AppendL( KExtensionM4v ); + iExtensionArray->AppendL( KExtensionM4a ); + iExtensionArray->AppendL( KExtension3gp ); + iExtensionArray->AppendL( KExtension3gpp ); + iExtensionArray->AppendL( KExtension3g2 ); + iExtensionArray->AppendL( KExtensionRm ); + iExtensionArray->AppendL( KExtensionRmvb ); + iExtensionArray->AppendL( KExtensionRam ); + iExtensionArray->AppendL( KExtensionRv ); + iExtensionArray->AppendL( KExtensionWmv ); + iExtensionArray->AppendL( KExtensionAvi ); + } + +// End of File