/*
* 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 <PathInfo.h>
#include <driveinfo.h>
#include <s32mem.h>
#include <bautils.h>
#include <mdeobjectquery.h>
#include <mdeconstants.h>
#include <collate.h>
#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