diff -r 000000000000 -r ba25891c3a9e appinstaller/AppMngr2/src/appmngr2model.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/appinstaller/AppMngr2/src/appmngr2model.cpp Thu Dec 17 08:51:10 2009 +0200 @@ -0,0 +1,839 @@ +/* +* Copyright (c) 2008-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: Model implementation +* +*/ + + +#include "appmngr2model.h" // CAppMngr2Model +#include "appmngr2modelobserver.h" // CAppMngr2ModelObserver +#include "appmngr2infomaker.h" // CAppMngr2InfoMaker +#include "appmngr2appinfomaker.h" // CAppMngr2AppInfoMaker +#include "appmngr2packageinfomaker.h" // CAppMngr2PackageInfoMaker +#include "appmngr2appinfoarray.h" // CAppMngr2AppInfoArray +#include "appmngr2packageinfoarray.h" // CAppMngr2PackageInfoArray +#include "appmngr2scanner.h" // CAppMngr2Scanner +#include "appmngr2pluginholder.h" // CAppMngr2PluginHolder +#include // CAppMngr2Runtime +#include // CAppMngrInfoBase +#include // CAppMngr2AppInfo +#include // CAppMngr2PackageInfo +#include // CAppMngr2RecognizedFile +#include // CleanupResetAndDestroyPushL +#include // TAppMngr2DriveUtils +#include // generic command ids +#include // CImplementationInformation +#include // REComSession +#include // CAknIconArray +#include // CGulIcon +#include // DriveInfo +#include // Pathinfo +#include // CRepository +#include // KCRUidSWInstallerLV +#include // AknsUtils +#include // icon IDs + +_LIT( KAppMngr2BitmapFile, "appmngr2.mif" ); +_LIT( KDriveSpec, "%c:" ); + + +// ======== LOCAL FUNCTIONS ========= + +// --------------------------------------------------------------------------- +// FindDataType() +// --------------------------------------------------------------------------- +// +TBool FindDataType( const TDataType& aDataType, CDataTypeArray& aArray ) + { + TInt count = aArray.Count(); + for( TInt index = 0; index < count; index++ ) + { + if( aArray[ index ] == aDataType ) + { + return ETrue; + } + } + return EFalse; + } + + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// CAppMngr2Model::NewL() +// --------------------------------------------------------------------------- +// +CAppMngr2Model* CAppMngr2Model::NewL( RFs& aFsSession, + MAppMngr2ModelObserver& aObserver ) + { + CAppMngr2Model* self = new (ELeave) CAppMngr2Model( aFsSession, aObserver ); + CleanupStack::PushL( self ); + self->ConstructL(); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::~CAppMngr2Model() +// --------------------------------------------------------------------------- +// +CAppMngr2Model::~CAppMngr2Model() + { + FLOG( "CAppMngr2Model::~CAppMngr2Model" ); + iClosing = ETrue; // to disable notifications + + Cancel(); + delete iApaAppListNotifier; + iInfoMakers.ResetAndDestroy(); + delete iScanner; + delete iInstalledApps; + delete iInstallationFiles; + iPlugins.ResetAndDestroy(); // unloads plugin DLLs + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::AppInfoCount() +// --------------------------------------------------------------------------- +// +TInt CAppMngr2Model::AppInfoCount() const + { + return iInstalledApps->Count(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::AppInfo() +// --------------------------------------------------------------------------- +// +CAppMngr2AppInfo& CAppMngr2Model::AppInfo( TInt aIndex ) const + { + return *( reinterpret_cast< CAppMngr2AppInfo* >( iInstalledApps->At( aIndex ) ) ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::PackageInfoCount() +// --------------------------------------------------------------------------- +// +TInt CAppMngr2Model::PackageInfoCount() const + { + return iInstallationFiles->Count(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::PackageInfo() +// --------------------------------------------------------------------------- +// +CAppMngr2PackageInfo& CAppMngr2Model::PackageInfo( TInt aIndex ) const + { + return *( reinterpret_cast< CAppMngr2PackageInfo* >( iInstallationFiles->At( aIndex ) ) ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::LoadIconsL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::LoadIconsL( CAknIconArray& aIconArray ) + { + LoadDefaultIconsL( aIconArray ); + + TInt pluginCount = iPlugins.Count(); + for( TInt index = 0; index < pluginCount; index++ ) + { + iPlugins[ index ]->LoadIconsL( aIconArray ); + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::GetIconIndexesL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::GetIconIndexesL( TUid aUid, TInt& aIconIndexBase, TInt& aIconIndexMax ) const + { + TInt pluginCount = iPlugins.Count(); + for( TInt index = 0; index < pluginCount; index++ ) + { + if( iPlugins[ index ]->Runtime().RuntimeUid() == aUid ) + { + aIconIndexBase = iPlugins[ index ]->IconIndexBase(); + aIconIndexMax = iPlugins[ index ]->IconIndexMax(); + return; + } + } + User::Leave( KErrNotFound ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::HandleCommandL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::HandleCommandL( CAppMngr2InfoBase& aInfo, TInt aCommand ) + { + FLOG( "CAppMngr2Model::HandleCommandL( %d ), IsActive() = %d", aCommand, IsActive() ); + + if( !IsActive() ) + { + // About to start plugin specific command. Note that when the command completes + // we need to call CAppMngr2InfoBase::CommandComplete() function. For this (and + // to indicate that there is a plugin specific command on-going) we take the + // address of CAppMngr2InfoBase item into iActiveItem. Because plugin specific + // command (like delete or uninstall) may trigger new scanning, it is necessary + // to disable iInstalledApps and iInstallationFiles array refreshing temporarily. + // When refreshing is disabled, the item which address is stored in iActiveItem + // is maintained in arrays and we can call iActiveItem->CommandComplete() when + // the command is complete. If arrays could be refreshed during plugin specific + // command, then calling iActiveItem->CommandComplete() would panic. + if( iObs.InstalledAppsDisplayed() ) + { + iInstalledApps->DisableRefreshNotificationsL(); + } + if( iObs.InstallationFilesDisplayed() ) + { + iInstallationFiles->DisableRefreshNotificationsL(); + } + + iActiveItem = &aInfo; + iActiveCommand = aCommand; + FLOG( "CAppMngr2Model::HandleCommandL, iActiveItem = 0x%08x '%S'", + iActiveItem, &( iActiveItem->Name() ) ); + TRAPD( err, iActiveItem->HandleCommandL( aCommand, iStatus ) ); + FLOG( "CAppMngr2Model::HandleCommandL, command started, err = %d", err ); + SetActive(); + if( err ) + { + TRequestStatus* statusPtr = &iStatus; + User::RequestComplete( statusPtr, err ); + } + } + // Ignore the command silently if already active. This may happen when user + // cancels previous installation command. Because cancelling installation can + // take long time, user may be able to issue new commands while model is still + // active (i.e. previous installation command is being cancalled). + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::StartFetchingInstallationFilesL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::StartFetchingInstallationFilesL() + { + FLOG( "CAppMngr2Model::StartFetchingInstallationFilesL" ); + FLOG_PERF_START( FetchInstallationFiles ) + + // Installation files cache must be enabled until scanner has completed. + // This ensures that scanner has time to call GetInstallationFilesL() for + // each plugin and for each directory before the first call completes. + // If the first call completes before scanner has made all these requets, + // cache will be turned off and partial results are displayed. + iInstallationFiles->IncrementCacheUseStartingNewRoundL(); + + iScanner->StartScanningL(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::StartFetchingInstalledAppsL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::StartFetchingInstalledAppsL() + { + FLOG( "CAppMngr2Model::StartFetchingInstalledAppsL" ); + FLOG_PERF_START( FetchInstalledApps ) + + // Additional cache increment to ensure that iInstalledApps cache is + // used until GetInstalledAppsL() function is called for each plugin. + // Without this, the fastest plugin might get it's list complete before + // other IncrementCacheUseL() calls and iInstalledApps would display + // partial list. + iInstalledApps->IncrementCacheUseStartingNewRoundL(); + + TInt pluginCount = iPlugins.Count(); + for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ ) + { + CAppMngr2AppInfoMaker* appInfoMaker = CAppMngr2AppInfoMaker::NewLC( + iPlugins[ pluginIndex ]->Runtime(), *this, iFs ); + + TRAPD( err, appInfoMaker->StartGettingInstalledAppsL() ); + FLOG( "CAppMngr2Model::StartFetchingInstalledAppsL, plugin 0x%08x, err = %d", + iPlugins[ pluginIndex ]->Runtime().RuntimeUid().iUid, err ); + if( err == KErrNone ) + { + iInfoMakers.AppendL( appInfoMaker ); + CleanupStack::Pop( appInfoMaker ); + iInstalledApps->IncrementCacheUseL(); + } + else + { + CleanupStack::PopAndDestroy( appInfoMaker ); + } + } + + // All GetInstalledAppsL() requests have been issued + iInstalledApps->DecrementCacheUse(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::DoCancel() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::DoCancel() + { + FLOG( "CAppMngr2Model::DoCancel, iActiveItem = 0x%08x", iActiveItem ); + + if( iActiveItem ) + { + iActiveItem->CancelCommand(); + iActiveItem = NULL; + if( !iClosing ) + { + TRAP_IGNORE( iInstalledApps->EnableRefreshNotificationsL() ); + TRAP_IGNORE( iInstallationFiles->EnableRefreshNotificationsL() ); + } + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::RunL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::RunL() + { + FLOG( "CAppMngr2Model::RunL, iActiveItem = 0x%08x, iStatus = %d", + iActiveItem, iStatus.Int() ); + + if( iActiveItem ) + { + TInt completionCode = iStatus.Int(); + TRAPD( err, iActiveItem->HandleCommandResultL( completionCode ) ); + FLOG( "CAppMngr2Model::RunL, HandleCommandResultL err = %d", err ); + CAppMngr2InfoBase* itemToDelete = iActiveItem; + iActiveItem = NULL; + + // Enable refresh notifications. No need to check which view is active + // because notifications can be enabled even if they were not disabled. + iInstalledApps->EnableRefreshNotificationsL(); + iInstallationFiles->EnableRefreshNotificationsL(); + + // Leave on error. This displays error note (if error notes are enabled). + User::LeaveIfError( err ); + + // If the command is EAppMngr2CmdUninstall or EAppMngr2CmdRemove, and it + // completed without errors, then we remove the current item immediatelty + // from the displayed list. Otherwise it may take quite long time until + // the item is removed from the UI, and in worst case it may not be removed + // at all. + // For example when an installation file is deleted, scanner notices change + // in directories and re-scans everything. UI is updated when the scanning + // completes. Delay between delete command and UI update (deleted item is + // removed from UI) depends on how quickly scanning completes. + if( completionCode == KErrNone ) + { + if( iActiveCommand == EAppMngr2CmdUninstall && iObs.InstalledAppsDisplayed() ) + { + iInstalledApps->ImmediateDelete( itemToDelete ); + } + if( iActiveCommand == EAppMngr2CmdRemove && iObs.InstallationFilesDisplayed() ) + { + iInstallationFiles->ImmediateDelete( itemToDelete ); + } + } + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::RefreshInstalledApps() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::RefreshInstalledApps() + { + FLOG( "CAppMngr2Model::RefreshInstalledApps" ); + + TRAP_IGNORE( StartFetchingInstalledAppsL() ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::RefreshInstallationFiles() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::RefreshInstallationFiles() + { + FLOG( "CAppMngr2Model::RefreshInstallationFiles" ); + + TRAP_IGNORE( StartFetchingInstallationFilesL() ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::ScanningResultL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::ScanningResultL( RPointerArray& aResult ) + { + FLOG( "CAppMngr2Model::ScanningResultL, begin: aResult.Count() = %d", aResult.Count() ); + + // Split recognition result array into smaller (plugin specific) arrays. Plugin + // specific arrays are maintained by CAppMngr2PackageInfoMaker objects, so one + // CAppMngr2PackageInfoMaker object is needed for each plugin that has recognized + // files. + TInt pluginCount = iPlugins.Count(); + for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ ) + { + CAppMngr2PackageInfoMaker* packageInfoMaker = CAppMngr2PackageInfoMaker::NewLC( + iPlugins[ pluginIndex ]->Runtime(), *this, iFs ); + + TInt fileCount = 0; + TInt resultCount = aResult.Count(); + for( TInt resultIndex = resultCount - 1; resultIndex >= 0; resultIndex-- ) + { + CAppMngr2RecognizedFile* recFile = aResult[ resultIndex ]; + if( FindDataType( recFile->DataType(), iPlugins[ pluginIndex ]->DataTypes() ) ) + { + packageInfoMaker->AddFileL( recFile ); // takes ownership + aResult.Remove( resultIndex ); + fileCount++; + } + } + + FLOG( "CAppMngr2Model::ScanningResultL, plugin 0x%08x: fileCount = %d", + iPlugins[ pluginIndex ]->Runtime().RuntimeUid().iUid, fileCount ); + if( fileCount > 0 ) + { + packageInfoMaker->StartGettingInstallationFilesL(); + iInfoMakers.AppendL( packageInfoMaker ); + CleanupStack::Pop( packageInfoMaker ); + iInstallationFiles->IncrementCacheUseL(); + } + else + { + CleanupStack::PopAndDestroy( packageInfoMaker ); + } + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::ScanningComplete() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::ScanningComplete() + { + FLOG( "CAppMngr2Model::ScanningComplete" ); + + iInstallationFiles->DecrementCacheUse(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::DirectoryChangedL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::DirectoryChangedL( const TDesC& /*aChangedDir*/ ) + { + FLOG( "CAppMngr2Model::DirectoryChangedL" ); + + // This might be improved by scanning the changed directory only. Model + // could record which items are got from which directory, so that it could + // remove those items that were created from the changed directory and + // re-scan only the changed directory. Scanner should also support + // scanning one directory only. Now, we just scan all again. + StartFetchingInstallationFilesL(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::HandleAppListEvent() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::HandleAppListEvent( TInt /*aEvent*/ ) + { + FLOG( "CAppMngr2Model::HandleAppListEvent" ); + + TRAP_IGNORE( StartFetchingInstalledAppsL() ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::NewAppsCreatedL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::NewAppsCreatedL( const CAppMngr2InfoMaker& aMaker, + RPointerArray& aAppInfos ) + { + FLOG( "CAppMngr2Model::NewAppsCreatedL, plugin 0x%08x: packageCount = %d", + aMaker.RuntimeUid().iUid, aAppInfos.Count() ); + + iInstalledApps->AddItemsInOrderL( aAppInfos ); + iInstalledApps->DecrementCacheUse(); + CloseInfoMaker( aMaker ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::ErrorInCreatingAppsL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::ErrorInCreatingAppsL( const CAppMngr2InfoMaker& aMaker, +#ifdef FLOG_DEBUG_TRACES + TInt aError ) +#else + TInt /*aError*/ ) +#endif + { + FLOG( "CAppMngr2Model::ErrorInCreatingAppsL, plugin 0x%08x: error = %d", + aMaker.RuntimeUid().iUid, aError ); + + iInstalledApps->DecrementCacheUse(); + CloseInfoMaker( aMaker ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::NewPackagesCreatedL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::NewPackagesCreatedL( const CAppMngr2InfoMaker& aMaker, + RPointerArray& aPackageInfos ) + { + FLOG( "CAppMngr2Model::NewPackagesCreatedL, plugin 0x%08x: packageCount = %d", + aMaker.RuntimeUid().iUid, aPackageInfos.Count() ); + + iInstallationFiles->AddItemsInOrderL( aPackageInfos ); + iInstallationFiles->DecrementCacheUse(); + CloseInfoMaker( aMaker ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::ErrorInCreatingPackagesL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::ErrorInCreatingPackagesL( const CAppMngr2InfoMaker& aMaker, +#ifdef FLOG_DEBUG_TRACES + TInt aError ) +#else + TInt /*aError*/ ) +#endif + { + FLOG( "CAppMngr2Model::ErrorInCreatingPackagesL, plugin 0x%08x: error = %d", + aMaker.RuntimeUid().iUid, aError ); + + iInstallationFiles->DecrementCacheUse(); + CloseInfoMaker( aMaker ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::ArrayContentChanged() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::ArrayContentChanged( CAppMngr2InfoArray* aArray, + TInt aMoreRefreshesExpected ) + { + if( aArray == iInstalledApps ) + { + FLOG_PERF_STOP( FetchInstalledApps ) + FLOG_PERF_PRINT( FetchInstalledApps ) + iObs.InstalledAppsChanged( aMoreRefreshesExpected ); + } + if( aArray == iInstallationFiles ) + { + FLOG_PERF_STOP( FetchInstallationFiles ) + FLOG_PERF_PRINT( FetchInstallationFiles ) + iObs.InstallationFilesChanged( aMoreRefreshesExpected ); + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::CAppMngr2Model() +// --------------------------------------------------------------------------- +// +CAppMngr2Model::CAppMngr2Model( RFs& aFsSession, MAppMngr2ModelObserver& aObserver ) + : CActive( CActive::EPriorityStandard ), iFs( aFsSession ), iObs( aObserver ) + { + CActiveScheduler::Add( this ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::ConstructL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::ConstructL() + { + FLOG( "CAppMngr2Model::ConstructL" ); + iClosing = EFalse; + + iInstalledApps = CAppMngr2AppInfoArray::NewL( *this ); + iInstallationFiles = CAppMngr2PackageInfoArray::NewL( *this ); + + FLOG_PERF_STATIC_BEGIN( LoadPluginsL ) + LoadPluginsL(); + FLOG_PERF_STATIC_END( LoadPluginsL ) + FLOG_PERF_STATIC_BEGIN( CreateScannerL ) + CreateScannerL(); + FLOG_PERF_STATIC_END( CreateScannerL ) + FLOG_PERF_STATIC_BEGIN( FetchDataTypesL ) + FetchDataTypesL(); + FLOG_PERF_STATIC_END( FetchDataTypesL ) + + // start monitoring changes in applications list + iApaAppListNotifier = CApaAppListNotifier::NewL( this, CActive::EPriorityStandard ); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::LoadDefaultIconsL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::LoadDefaultIconsL( CAknIconArray& aIconArray ) + { + FLOG( "CAppMngr2Model::LoadDefaultIconsL" ); + + MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance(); + HBufC* bitmapFile = TAppMngr2DriveUtils::FullBitmapFileNameLC( KAppMngr2BitmapFile, iFs ); + CFbsBitmap* bitmap = NULL; + CFbsBitmap* mask = NULL; + CGulIcon* icon = NULL; + + // Note that icons can be graphically-skinned (icon graphic defined in theme) + // or color-skinned (icon colors change depending on background color defined + // in theme). Normal icons are graphically-skinned and indicator icons are + // color-skinned. AknsUtils::CreateGulIconL() creates graphically-skinned icons, + // and AknsUtils::CreateColorIconL() creates color-skinned icons. Hence both + // of these functions are used below. + + // Icon 0: EAppMngr2IconIndex_QgnIndiAmInstMmcAdd + // Indicator icon for items stored/installed in memory card + AknsUtils::CreateColorIconLC( skinInstance, + KAknsIIDQgnIndiMmcAdd, KAknsIIDQsnIconColors, EAknsCIQsnIconColorsCG13, + bitmap, mask, *bitmapFile, + EMbmAppmngr2Qgn_indi_mmc_add, + EMbmAppmngr2Qgn_indi_mmc_add_mask, + KRgbBlack ); + icon = CGulIcon::NewL( bitmap, mask ); + icon->SetBitmapsOwnedExternally( EFalse ); + CleanupStack::Pop( 2 ); // bitmap and mask, order is varying + CleanupStack::PushL( icon ); + aIconArray.AppendL( icon ); + CleanupStack::Pop( icon ); + + // Icon 1: EAppMngr2IconIndex_QgnIndiFmgrMsAdd + // Indicator icon for items stored/installed in mass memory + AknsUtils::CreateColorIconLC( skinInstance, + KAknsIIDQgnIndiFmgrMsAdd, KAknsIIDQsnIconColors, EAknsCIQsnIconColorsCG13, + bitmap, mask, *bitmapFile, + EMbmAppmngr2Qgn_indi_fmgr_ms_add, + EMbmAppmngr2Qgn_indi_fmgr_ms_add_mask, + KRgbBlack ); + icon = CGulIcon::NewL( bitmap, mask ); + icon->SetBitmapsOwnedExternally( EFalse ); + CleanupStack::Pop( 2 ); // bitmap and mask, order may vary + CleanupStack::PushL( icon ); + aIconArray.AppendL( icon ); + CleanupStack::Pop( icon ); + + // Icon 2: EAppMngr2IconIndex_QgnPropUnknown + // List icon for items that are not known + icon = AknsUtils::CreateGulIconL( skinInstance, + KAknsIIDQgnPropUnknown, *bitmapFile, + EMbmAppmngr2Qgn_prop_unknown, + EMbmAppmngr2Qgn_prop_unknown_mask ); + CleanupStack::PushL( icon ); + aIconArray.AppendL( icon ); + CleanupStack::Pop( icon ); + + CleanupStack::PopAndDestroy( bitmapFile ); + + // Additionally some unknown indicator icon could be defined. + // Now, if some plugin gives incorrect index fox indicator icon, + // then no indicator icon is displayed. + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::LoadPluginsL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::LoadPluginsL() + { + FLOG( "CAppMngr2Model::LoadPluginsL" ); + + RImplInfoPtrArray implInfoArray; + CleanupResetAndDestroyPushL( implInfoArray ); + REComSession::ListImplementationsL( KAppMngr2PluginInterface, implInfoArray ); + + CAppMngr2PluginHolder* pluginHolder = NULL; + CImplementationInformation* implInfo; + TInt count = implInfoArray.Count(); + for( TInt index = 0; index < count; index++ ) + { + implInfo = implInfoArray[ index ]; + FLOG( "CAppMngr2Model::LoadPluginsL, loading %S", &( implInfo->DisplayName() ) ); + FLOG_PERF_STATIC_BEGIN( DoLoadPluginL ); + TRAPD( err, pluginHolder = DoLoadPluginL( implInfo->ImplementationUid() ) ); + FLOG_PERF_STATIC_END( DoLoadPluginL ); + FLOG( "CAppMngr2Model::DoLoadPluginL( 0x%08x ), err = %d", + implInfo->ImplementationUid().iUid, err ); + if( err == KErrNone ) + { + CleanupStack::PushL( pluginHolder ); + iPlugins.AppendL( pluginHolder ); + CleanupStack::Pop( pluginHolder ); + } + } + + CleanupStack::PopAndDestroy( &implInfoArray ); + REComSession::FinalClose(); + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::DoLoadPluginL() +// --------------------------------------------------------------------------- +// +CAppMngr2PluginHolder* CAppMngr2Model::DoLoadPluginL( TUid aUid ) + { + CAppMngr2Runtime* plugin = CAppMngr2Runtime::NewL( aUid, *this ); + CleanupStack::PushL( plugin ); + CAppMngr2PluginHolder* holder = new (ELeave) CAppMngr2PluginHolder( plugin ); + CleanupStack::Pop( plugin ); + return holder; + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::CreateScannerL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::CreateScannerL() + { + iScanner = CAppMngr2Scanner::NewL( *this ); + + TDriveList driveList; + TInt driveCount = 0; + TInt err = DriveInfo::GetUserVisibleDrives( iFs, driveList, driveCount ); + User::LeaveIfError( err ); + + // Default directories + TFileName path; + TInt driveListLength = driveList.Length(); + for( TInt driveNumber = 0; driveNumber < driveListLength; driveNumber++ ) + { + if( driveList[ driveNumber ] ) + { + TUint driveStatus = 0; + err = DriveInfo::GetDriveStatus( iFs, driveNumber, driveStatus ); + User::LeaveIfError( err ); + + if( !( driveStatus & DriveInfo::EDriveRemote ) ) + { + err = PathInfo::GetFullPath( path, driveNumber, PathInfo::EInstallsPath ); + User::LeaveIfError( err ); + iScanner->AddDirectoryL( path ); + } + } + } + + // Additional plug-in specific directories + TInt pluginCount = iPlugins.Count(); + for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ ) + { + RPointerArray dirsToScan; + CleanupResetAndDestroyPushL( dirsToScan ); + TRAPD( err, iPlugins[ pluginIndex ]->Runtime().GetAdditionalDirsToScanL( iFs, + dirsToScan ) ); + if( err == KErrNone ) + { + TInt dirCount = dirsToScan.Count(); + for( TInt dirIndex = 0; dirIndex < dirCount; dirIndex++ ) + { + TPtrC dirName = *( dirsToScan[ dirIndex ] ); + iScanner->AddDirectoryL( dirName ); + } + } + CleanupStack::PopAndDestroy( &dirsToScan ); + } + + // KSWInstallerPackageFolder directory if defined in CenRep + CRepository* cenrep = CRepository::NewLC( KCRUidSWInstallerLV ); + err = cenrep->Get( KSWInstallerPackageFolder, path ); + CleanupStack::PopAndDestroy( cenrep ); + if( err == KErrNone ) + { + TParsePtr parse( path ); + if( parse.DrivePresent() ) + { + iScanner->AddDirectoryL( path ); + } + else if( parse.PathPresent() ) + { + TDriveList driveList; + TInt driveCount = 0; + err = DriveInfo::GetUserVisibleDrives( iFs, driveList, driveCount ); + if( err == KErrNone ) + { + TInt driveListLength = driveList.Length(); + for( TInt driveNumber = 0; driveNumber < driveListLength; driveNumber++ ) + { + if( driveList[ driveNumber ] ) + { + TUint driveStatus = 0; + err = DriveInfo::GetDriveStatus( iFs, driveNumber, driveStatus ); + if( err == KErrNone && !( driveStatus & DriveInfo::EDriveRemote ) ) + { + TChar driveLetter; + if( RFs::DriveToChar( driveNumber, driveLetter ) == KErrNone ) + { + TFileName fullPath; + fullPath.Format( KDriveSpec, static_cast( driveLetter ) ); + fullPath.Append( path ); + iScanner->AddDirectoryL( fullPath ); + } + } + } + } + } + } + else + { + // ignore empty values, and values that does not contain valid path + } + } + else + { + if( err != KErrNotFound ) + { + User::Leave( err ); + } + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::FetchDataTypesL() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::FetchDataTypesL() + { + FLOG( "CAppMngr2Model::FetchDataTypesL" ); + + TInt pluginCount = iPlugins.Count(); + for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ ) + { + FLOG( "CAppMngr2Model::FetchDataTypesL: pluginIndex = %d", pluginIndex ); + TRAP_IGNORE( iPlugins[ pluginIndex ]->FetchDataTypesL() ); + } + } + +// --------------------------------------------------------------------------- +// CAppMngr2Model::CloseInfoMaker() +// --------------------------------------------------------------------------- +// +void CAppMngr2Model::CloseInfoMaker( const CAppMngr2InfoMaker& aMaker ) + { + const CAppMngr2InfoMaker* makerToClose = &aMaker; + for( TInt index = iInfoMakers.Count() - 1; index >= 0; index-- ) + { + CAppMngr2InfoMaker* maker = iInfoMakers[ index ]; + if( maker == makerToClose ) + { + iInfoMakers.Remove( index ); + delete maker; + break; + } + } + } +