appinstaller/AppMngr2/src/appmngr2model.cpp
changeset 80 9dcba1ee99f7
parent 77 d1838696558c
equal deleted inserted replaced
77:d1838696558c 80:9dcba1ee99f7
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   Model implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "appmngr2model.h"              // CAppMngr2Model
       
    20 #include "appmngr2modelobserver.h"      // CAppMngr2ModelObserver
       
    21 #include "appmngr2infomaker.h"          // CAppMngr2InfoMaker
       
    22 #include "appmngr2appinfomaker.h"       // CAppMngr2AppInfoMaker
       
    23 #include "appmngr2packageinfomaker.h"   // CAppMngr2PackageInfoMaker
       
    24 #include "appmngr2appinfoarray.h"       // CAppMngr2AppInfoArray
       
    25 #include "appmngr2packageinfoarray.h"   // CAppMngr2PackageInfoArray
       
    26 #include "appmngr2scanner.h"            // CAppMngr2Scanner
       
    27 #include "appmngr2pluginholder.h"       // CAppMngr2PluginHolder
       
    28 #include <appmngr2runtime.h>            // CAppMngr2Runtime
       
    29 #include <appmngr2infobase.h>           // CAppMngrInfoBase
       
    30 #include <appmngr2appinfo.h>            // CAppMngr2AppInfo
       
    31 #include <appmngr2packageinfo.h>        // CAppMngr2PackageInfo
       
    32 #include <appmngr2recognizedfile.h>     // CAppMngr2RecognizedFile
       
    33 #include <appmngr2cleanuputils.h>       // CleanupResetAndDestroyPushL
       
    34 #include <appmngr2driveutils.h>         // TAppMngr2DriveUtils
       
    35 #include <appmngr2common.hrh>           // generic command ids
       
    36 #include <ecom/implementationinformation.h>  // CImplementationInformation
       
    37 #include <ecom/ecom.h>                  // REComSession
       
    38 #include <AknIconArray.h>               // CAknIconArray
       
    39 #include <gulicon.h>                    // CGulIcon
       
    40 #include <driveinfo.h>                  // DriveInfo
       
    41 #include <pathinfo.h>                   // Pathinfo
       
    42 #include <centralrepository.h>          // CRepository
       
    43 #include <SWInstallerInternalCRKeys.h>  // KCRUidSWInstallerLV
       
    44 #include <AknsUtils.h>                  // AknsUtils
       
    45 #include <appmngr2.mbg>                 // icon IDs
       
    46 
       
    47 _LIT( KAppMngr2BitmapFile, "appmngr2.mif" );
       
    48 _LIT( KDriveSpec, "%c:" );
       
    49 
       
    50 
       
    51 // ======== LOCAL FUNCTIONS =========
       
    52 
       
    53 // ---------------------------------------------------------------------------
       
    54 // FindDataType()
       
    55 // ---------------------------------------------------------------------------
       
    56 //
       
    57 TBool FindDataType( const TDataType& aDataType, CDataTypeArray& aArray )
       
    58     {
       
    59     TInt count = aArray.Count();
       
    60     for( TInt index = 0; index < count; index++ )
       
    61         {
       
    62         if( aArray[ index ] == aDataType )
       
    63             {
       
    64             return ETrue;
       
    65             }
       
    66         }
       
    67     return EFalse;
       
    68     }
       
    69 
       
    70 
       
    71 // ======== MEMBER FUNCTIONS ========
       
    72 
       
    73 // ---------------------------------------------------------------------------
       
    74 // CAppMngr2Model::NewL()
       
    75 // ---------------------------------------------------------------------------
       
    76 //
       
    77 CAppMngr2Model* CAppMngr2Model::NewL( RFs& aFsSession,
       
    78         MAppMngr2ModelObserver& aObserver )
       
    79     {
       
    80     CAppMngr2Model* self = new (ELeave) CAppMngr2Model( aFsSession, aObserver );
       
    81     CleanupStack::PushL( self );
       
    82     self->ConstructL();
       
    83     CleanupStack::Pop( self );
       
    84     return self;
       
    85     }
       
    86 
       
    87 // ---------------------------------------------------------------------------
       
    88 // CAppMngr2Model::~CAppMngr2Model()
       
    89 // ---------------------------------------------------------------------------
       
    90 //
       
    91 CAppMngr2Model::~CAppMngr2Model()
       
    92     {
       
    93     FLOG( "CAppMngr2Model::~CAppMngr2Model" );
       
    94     iClosing = ETrue;   // to disable notifications
       
    95 
       
    96     Cancel();
       
    97     delete iApaAppListNotifier;
       
    98     iInfoMakers.ResetAndDestroy();
       
    99     delete iScanner;
       
   100     delete iInstalledApps;
       
   101     delete iInstallationFiles;
       
   102     iPlugins.ResetAndDestroy();     // unloads plugin DLLs
       
   103     }
       
   104 
       
   105 // ---------------------------------------------------------------------------
       
   106 // CAppMngr2Model::AppInfoCount()
       
   107 // ---------------------------------------------------------------------------
       
   108 //
       
   109 TInt CAppMngr2Model::AppInfoCount() const
       
   110     {
       
   111     return iInstalledApps->Count();
       
   112     }
       
   113 
       
   114 // ---------------------------------------------------------------------------
       
   115 // CAppMngr2Model::AppInfo()
       
   116 // ---------------------------------------------------------------------------
       
   117 //
       
   118 CAppMngr2AppInfo& CAppMngr2Model::AppInfo( TInt aIndex ) const
       
   119     {
       
   120     return *( reinterpret_cast< CAppMngr2AppInfo* >( iInstalledApps->At( aIndex ) ) );
       
   121     }
       
   122 
       
   123 // ---------------------------------------------------------------------------
       
   124 // CAppMngr2Model::PackageInfoCount()
       
   125 // ---------------------------------------------------------------------------
       
   126 //
       
   127 TInt CAppMngr2Model::PackageInfoCount() const
       
   128     {
       
   129     return iInstallationFiles->Count();
       
   130     }
       
   131 
       
   132 // ---------------------------------------------------------------------------
       
   133 // CAppMngr2Model::PackageInfo()
       
   134 // ---------------------------------------------------------------------------
       
   135 //
       
   136 CAppMngr2PackageInfo& CAppMngr2Model::PackageInfo( TInt aIndex ) const 
       
   137     {
       
   138     return *( reinterpret_cast< CAppMngr2PackageInfo* >( iInstallationFiles->At( aIndex ) ) );
       
   139     }
       
   140 
       
   141 // ---------------------------------------------------------------------------
       
   142 // CAppMngr2Model::LoadIconsL()
       
   143 // ---------------------------------------------------------------------------
       
   144 //
       
   145 void CAppMngr2Model::LoadIconsL( CAknIconArray& aIconArray )
       
   146     {
       
   147     LoadDefaultIconsL( aIconArray );
       
   148     
       
   149     TInt pluginCount = iPlugins.Count();
       
   150     for( TInt index = 0; index < pluginCount; index++ )
       
   151         {
       
   152         iPlugins[ index ]->LoadIconsL( aIconArray );
       
   153         }
       
   154     }
       
   155 
       
   156 // ---------------------------------------------------------------------------
       
   157 // CAppMngr2Model::GetIconIndexesL()
       
   158 // ---------------------------------------------------------------------------
       
   159 //
       
   160 void CAppMngr2Model::GetIconIndexesL( TUid aUid, TInt& aIconIndexBase, TInt& aIconIndexMax ) const
       
   161     {
       
   162     TInt pluginCount = iPlugins.Count();
       
   163     for( TInt index = 0; index < pluginCount; index++ )
       
   164         {
       
   165         if( iPlugins[ index ]->Runtime().RuntimeUid() == aUid )
       
   166             {
       
   167             aIconIndexBase = iPlugins[ index ]->IconIndexBase();
       
   168             aIconIndexMax = iPlugins[ index ]->IconIndexMax();
       
   169             return;
       
   170             }
       
   171         }
       
   172     User::Leave( KErrNotFound );
       
   173     }
       
   174 
       
   175 // ---------------------------------------------------------------------------
       
   176 // CAppMngr2Model::HandleCommandL()
       
   177 // ---------------------------------------------------------------------------
       
   178 //
       
   179 void CAppMngr2Model::HandleCommandL( CAppMngr2InfoBase& aInfo, TInt aCommand )
       
   180     {
       
   181     FLOG( "CAppMngr2Model::HandleCommandL( %d ), IsActive() = %d", aCommand, IsActive() );
       
   182     
       
   183     if( !IsActive() )
       
   184         {
       
   185         // About to start plugin specific command. Note that when the command completes
       
   186         // we need to call CAppMngr2InfoBase::CommandComplete() function. For this (and
       
   187         // to indicate that there is a plugin specific command on-going) we take the
       
   188         // address of CAppMngr2InfoBase item into iActiveItem. Because plugin specific
       
   189         // command (like delete or uninstall) may trigger new scanning, it is necessary
       
   190         // to disable iInstalledApps and iInstallationFiles array refreshing temporarily.
       
   191         // When refreshing is disabled, the item which address is stored in iActiveItem
       
   192         // is maintained in arrays and we can call iActiveItem->CommandComplete() when
       
   193         // the command is complete. If arrays could be refreshed during plugin specific
       
   194         // command, then calling iActiveItem->CommandComplete() would panic.
       
   195         if( iObs.InstalledAppsDisplayed() )
       
   196             {
       
   197             iInstalledApps->DisableRefreshNotificationsL();
       
   198             }
       
   199         if( iObs.InstallationFilesDisplayed() )
       
   200             {
       
   201             iInstallationFiles->DisableRefreshNotificationsL();
       
   202             }
       
   203 
       
   204         iActiveItem = &aInfo;
       
   205         iActiveCommand = aCommand;
       
   206         FLOG( "CAppMngr2Model::HandleCommandL, iActiveItem = 0x%08x '%S'",
       
   207                 iActiveItem, &( iActiveItem->Name() ) ); 
       
   208         TRAPD( err, iActiveItem->HandleCommandL( aCommand, iStatus ) );
       
   209         FLOG( "CAppMngr2Model::HandleCommandL, command started, err = %d", err );
       
   210         SetActive();
       
   211         if( err )
       
   212             {
       
   213             TRequestStatus* statusPtr = &iStatus;
       
   214             User::RequestComplete( statusPtr, err );
       
   215             }
       
   216         }
       
   217     // Ignore the command silently if already active. This may happen when user
       
   218     // cancels previous installation command. Because cancelling installation can
       
   219     // take long time, user may be able to issue new commands while model is still
       
   220     // active (i.e. previous installation command is being cancalled).
       
   221     }
       
   222 
       
   223 // ---------------------------------------------------------------------------
       
   224 // CAppMngr2Model::StartFetchingInstallationFilesL()
       
   225 // ---------------------------------------------------------------------------
       
   226 //
       
   227 void CAppMngr2Model::StartFetchingInstallationFilesL()
       
   228     {
       
   229     FLOG( "CAppMngr2Model::StartFetchingInstallationFilesL" );
       
   230     FLOG_PERF_START( FetchInstallationFiles )
       
   231     
       
   232     // Installation files cache must be enabled until scanner has completed.
       
   233     // This ensures that scanner has time to call GetInstallationFilesL() for
       
   234     // each plugin and for each directory before the first call completes.
       
   235     // If the first call completes before scanner has made all these requets,
       
   236     // cache will be turned off and partial results are displayed.
       
   237     iInstallationFiles->IncrementCacheUseStartingNewRoundL();
       
   238 
       
   239     iScanner->StartScanningL();
       
   240     }
       
   241 
       
   242 // ---------------------------------------------------------------------------
       
   243 // CAppMngr2Model::StartFetchingInstalledAppsL()
       
   244 // ---------------------------------------------------------------------------
       
   245 //
       
   246 void CAppMngr2Model::StartFetchingInstalledAppsL()
       
   247     {
       
   248     FLOG( "CAppMngr2Model::StartFetchingInstalledAppsL" );
       
   249     FLOG_PERF_START( FetchInstalledApps )
       
   250 
       
   251     // Additional cache increment to ensure that iInstalledApps cache is
       
   252     // used until GetInstalledAppsL() function is called for each plugin.
       
   253     // Without this, the fastest plugin might get it's list complete before
       
   254     // other IncrementCacheUseL() calls and iInstalledApps would display
       
   255     // partial list.
       
   256     iInstalledApps->IncrementCacheUseStartingNewRoundL();
       
   257     
       
   258     TInt pluginCount = iPlugins.Count();
       
   259     for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ )
       
   260         {
       
   261         CAppMngr2AppInfoMaker* appInfoMaker = CAppMngr2AppInfoMaker::NewLC(
       
   262                 iPlugins[ pluginIndex ]->Runtime(), *this, iFs );
       
   263         
       
   264         TRAPD( err, appInfoMaker->StartGettingInstalledAppsL() );
       
   265         FLOG( "CAppMngr2Model::StartFetchingInstalledAppsL, plugin 0x%08x, err = %d",
       
   266                 iPlugins[ pluginIndex ]->Runtime().RuntimeUid().iUid, err );
       
   267         if( err == KErrNone )
       
   268             {
       
   269             iInfoMakers.AppendL( appInfoMaker );
       
   270             CleanupStack::Pop( appInfoMaker );
       
   271             iInstalledApps->IncrementCacheUseL();
       
   272             }
       
   273         else
       
   274             {
       
   275             CleanupStack::PopAndDestroy( appInfoMaker );
       
   276             }
       
   277         }
       
   278 
       
   279     // All GetInstalledAppsL() requests have been issued
       
   280     iInstalledApps->DecrementCacheUse();
       
   281     }
       
   282 
       
   283 // ---------------------------------------------------------------------------
       
   284 // CAppMngr2Model::DoCancel()
       
   285 // ---------------------------------------------------------------------------
       
   286 //
       
   287 void CAppMngr2Model::DoCancel()
       
   288     {
       
   289     FLOG( "CAppMngr2Model::DoCancel, iActiveItem = 0x%08x", iActiveItem );
       
   290     
       
   291     if( iActiveItem )
       
   292         {
       
   293         iActiveItem->CancelCommand();
       
   294         iActiveItem = NULL;
       
   295         if( !iClosing )
       
   296             {
       
   297             TRAP_IGNORE( iInstalledApps->EnableRefreshNotificationsL() );
       
   298             TRAP_IGNORE( iInstallationFiles->EnableRefreshNotificationsL() );
       
   299             }
       
   300         }
       
   301     }
       
   302 
       
   303 // ---------------------------------------------------------------------------
       
   304 // CAppMngr2Model::RunL()
       
   305 // ---------------------------------------------------------------------------
       
   306 //
       
   307 void CAppMngr2Model::RunL()
       
   308     {
       
   309     FLOG( "CAppMngr2Model::RunL, iActiveItem = 0x%08x, iStatus = %d",
       
   310             iActiveItem, iStatus.Int() );
       
   311 
       
   312     if( iActiveItem )
       
   313         {
       
   314         TInt completionCode = iStatus.Int();
       
   315         TRAPD( err, iActiveItem->HandleCommandResultL( completionCode ) );
       
   316         FLOG( "CAppMngr2Model::RunL, HandleCommandResultL err = %d", err );
       
   317         CAppMngr2InfoBase* itemToDelete = iActiveItem;
       
   318         iActiveItem = NULL;
       
   319 
       
   320         // Enable refresh notifications. No need to check which view is active
       
   321         // because notifications can be enabled even if they were not disabled.
       
   322         iInstalledApps->EnableRefreshNotificationsL();
       
   323         iInstallationFiles->EnableRefreshNotificationsL();
       
   324 
       
   325         // Leave on error. This displays error note (if error notes are enabled).
       
   326         User::LeaveIfError( err );
       
   327         
       
   328         // If the command is EAppMngr2CmdUninstall or EAppMngr2CmdRemove, and it
       
   329         // completed without errors, then we remove the current item immediatelty
       
   330         // from the displayed list. Otherwise it may take quite long time until
       
   331         // the item is removed from the UI, and in worst case it may not be removed
       
   332         // at all.
       
   333         // For example when an installation file is deleted, scanner notices change
       
   334         // in directories and re-scans everything. UI is updated when the scanning
       
   335         // completes. Delay between delete command and UI update (deleted item is
       
   336         // removed from UI) depends on how quickly scanning completes.
       
   337         if( completionCode == KErrNone )
       
   338             {
       
   339             if( iActiveCommand == EAppMngr2CmdUninstall && iObs.InstalledAppsDisplayed() )
       
   340                 {
       
   341                 iInstalledApps->ImmediateDelete( itemToDelete );
       
   342                 }
       
   343             if( iActiveCommand == EAppMngr2CmdRemove && iObs.InstallationFilesDisplayed() )
       
   344                 {
       
   345                 iInstallationFiles->ImmediateDelete( itemToDelete );
       
   346                 }
       
   347             }
       
   348         }
       
   349     }
       
   350 
       
   351 // ---------------------------------------------------------------------------
       
   352 // CAppMngr2Model::RefreshInstalledApps()
       
   353 // ---------------------------------------------------------------------------
       
   354 //
       
   355 void CAppMngr2Model::RefreshInstalledApps()
       
   356     {
       
   357     FLOG( "CAppMngr2Model::RefreshInstalledApps" );
       
   358     
       
   359     TRAP_IGNORE( StartFetchingInstalledAppsL() );
       
   360     }
       
   361 
       
   362 // ---------------------------------------------------------------------------
       
   363 // CAppMngr2Model::RefreshInstallationFiles()
       
   364 // ---------------------------------------------------------------------------
       
   365 //
       
   366 void CAppMngr2Model::RefreshInstallationFiles()
       
   367     {
       
   368     FLOG( "CAppMngr2Model::RefreshInstallationFiles" );
       
   369 
       
   370     TRAP_IGNORE( StartFetchingInstallationFilesL() );
       
   371     }
       
   372 
       
   373 // ---------------------------------------------------------------------------
       
   374 // CAppMngr2Model::ScanningResultL()
       
   375 // ---------------------------------------------------------------------------
       
   376 //
       
   377 void CAppMngr2Model::ScanningResultL( RPointerArray<CAppMngr2RecognizedFile>& aResult )
       
   378     {
       
   379     FLOG( "CAppMngr2Model::ScanningResultL, begin: aResult.Count() = %d", aResult.Count() );
       
   380     
       
   381     // Split recognition result array into smaller (plugin specific) arrays. Plugin
       
   382     // specific arrays are maintained by CAppMngr2PackageInfoMaker objects, so one
       
   383     // CAppMngr2PackageInfoMaker object is needed for each plugin that has recognized
       
   384     // files.
       
   385     TInt pluginCount = iPlugins.Count();
       
   386     for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ )
       
   387         {
       
   388         CAppMngr2PackageInfoMaker* packageInfoMaker = CAppMngr2PackageInfoMaker::NewLC(
       
   389                 iPlugins[ pluginIndex ]->Runtime(), *this, iFs );
       
   390 
       
   391         TInt fileCount = 0;
       
   392         TInt resultCount = aResult.Count();
       
   393         for( TInt resultIndex = resultCount - 1; resultIndex >= 0; resultIndex-- )
       
   394             {
       
   395             CAppMngr2RecognizedFile* recFile = aResult[ resultIndex ];
       
   396             if( FindDataType( recFile->DataType(), iPlugins[ pluginIndex ]->DataTypes() ) )
       
   397                 {
       
   398                 packageInfoMaker->AddFileL( recFile );  // takes ownership
       
   399                 aResult.Remove( resultIndex );
       
   400                 fileCount++;
       
   401                 }
       
   402             }
       
   403 
       
   404         FLOG( "CAppMngr2Model::ScanningResultL, plugin 0x%08x: fileCount = %d",
       
   405                 iPlugins[ pluginIndex ]->Runtime().RuntimeUid().iUid, fileCount );
       
   406         if( fileCount > 0 )
       
   407             {
       
   408             packageInfoMaker->StartGettingInstallationFilesL();
       
   409             iInfoMakers.AppendL( packageInfoMaker );
       
   410             CleanupStack::Pop( packageInfoMaker );
       
   411             iInstallationFiles->IncrementCacheUseL();
       
   412             }
       
   413         else
       
   414             {
       
   415             CleanupStack::PopAndDestroy( packageInfoMaker );
       
   416             }
       
   417         }
       
   418     }
       
   419 
       
   420 // ---------------------------------------------------------------------------
       
   421 // CAppMngr2Model::ScanningComplete()
       
   422 // ---------------------------------------------------------------------------
       
   423 //
       
   424 void CAppMngr2Model::ScanningComplete()
       
   425     {
       
   426     FLOG( "CAppMngr2Model::ScanningComplete" );
       
   427     
       
   428     iInstallationFiles->DecrementCacheUse();
       
   429     }
       
   430 
       
   431 // ---------------------------------------------------------------------------
       
   432 // CAppMngr2Model::DirectoryChangedL()
       
   433 // ---------------------------------------------------------------------------
       
   434 //
       
   435 void CAppMngr2Model::DirectoryChangedL( const TDesC& /*aChangedDir*/ )
       
   436     {
       
   437     FLOG( "CAppMngr2Model::DirectoryChangedL" );
       
   438     
       
   439     // This might be improved by scanning the changed directory only. Model
       
   440     // could record which items are got from which directory, so that it could
       
   441     // remove those items that were created from the changed directory and
       
   442     // re-scan only the changed directory. Scanner should also support
       
   443     // scanning one directory only. Now, we just scan all again.
       
   444     StartFetchingInstallationFilesL();
       
   445     }
       
   446 
       
   447 // ---------------------------------------------------------------------------
       
   448 // CAppMngr2Model::HandleAppListEvent()
       
   449 // ---------------------------------------------------------------------------
       
   450 //
       
   451 void CAppMngr2Model::HandleAppListEvent( TInt /*aEvent*/ )
       
   452     {
       
   453     FLOG( "CAppMngr2Model::HandleAppListEvent" );
       
   454     
       
   455     TRAP_IGNORE( StartFetchingInstalledAppsL() );
       
   456     }
       
   457 
       
   458 // ---------------------------------------------------------------------------
       
   459 // CAppMngr2Model::NewAppsCreatedL()
       
   460 // ---------------------------------------------------------------------------
       
   461 //
       
   462 void CAppMngr2Model::NewAppsCreatedL( const CAppMngr2InfoMaker& aMaker,
       
   463         RPointerArray<CAppMngr2AppInfo>& aAppInfos )
       
   464     {
       
   465     FLOG( "CAppMngr2Model::NewAppsCreatedL, plugin 0x%08x: packageCount = %d",
       
   466             aMaker.RuntimeUid().iUid, aAppInfos.Count() );
       
   467     
       
   468     iInstalledApps->AddItemsInOrderL( aAppInfos );
       
   469     iInstalledApps->DecrementCacheUse();
       
   470     CloseInfoMaker( aMaker );
       
   471     }
       
   472 
       
   473 // ---------------------------------------------------------------------------
       
   474 // CAppMngr2Model::ErrorInCreatingAppsL()
       
   475 // ---------------------------------------------------------------------------
       
   476 //
       
   477 void CAppMngr2Model::ErrorInCreatingAppsL( const CAppMngr2InfoMaker& aMaker,
       
   478 #ifdef FLOG_DEBUG_TRACES
       
   479         TInt aError )
       
   480 #else
       
   481         TInt /*aError*/ )
       
   482 #endif
       
   483     {
       
   484     FLOG( "CAppMngr2Model::ErrorInCreatingAppsL, plugin 0x%08x: error = %d",
       
   485             aMaker.RuntimeUid().iUid, aError );
       
   486     
       
   487     iInstalledApps->DecrementCacheUse();
       
   488     CloseInfoMaker( aMaker );
       
   489     }
       
   490 
       
   491 // ---------------------------------------------------------------------------
       
   492 // CAppMngr2Model::NewPackagesCreatedL()
       
   493 // ---------------------------------------------------------------------------
       
   494 //
       
   495 void CAppMngr2Model::NewPackagesCreatedL( const CAppMngr2InfoMaker& aMaker,
       
   496             RPointerArray<CAppMngr2PackageInfo>& aPackageInfos )
       
   497     {
       
   498     FLOG( "CAppMngr2Model::NewPackagesCreatedL, plugin 0x%08x: packageCount = %d",
       
   499             aMaker.RuntimeUid().iUid, aPackageInfos.Count() );
       
   500     
       
   501     iInstallationFiles->AddItemsInOrderL( aPackageInfos );
       
   502     iInstallationFiles->DecrementCacheUse();
       
   503     CloseInfoMaker( aMaker );
       
   504     }
       
   505 
       
   506 // ---------------------------------------------------------------------------
       
   507 // CAppMngr2Model::ErrorInCreatingPackagesL()
       
   508 // ---------------------------------------------------------------------------
       
   509 //
       
   510 void CAppMngr2Model::ErrorInCreatingPackagesL( const CAppMngr2InfoMaker& aMaker,
       
   511 #ifdef FLOG_DEBUG_TRACES
       
   512         TInt aError )
       
   513 #else
       
   514         TInt /*aError*/ )
       
   515 #endif
       
   516     {
       
   517     FLOG( "CAppMngr2Model::ErrorInCreatingPackagesL, plugin 0x%08x: error = %d",
       
   518             aMaker.RuntimeUid().iUid, aError );
       
   519     
       
   520     iInstallationFiles->DecrementCacheUse();
       
   521     CloseInfoMaker( aMaker );
       
   522     }
       
   523 
       
   524 // ---------------------------------------------------------------------------
       
   525 // CAppMngr2Model::ArrayContentChanged()
       
   526 // ---------------------------------------------------------------------------
       
   527 //
       
   528 void CAppMngr2Model::ArrayContentChanged( CAppMngr2InfoArray* aArray,
       
   529         TInt aMoreRefreshesExpected )
       
   530     {
       
   531     if( aArray == iInstalledApps )
       
   532         {
       
   533         FLOG_PERF_STOP( FetchInstalledApps )
       
   534         FLOG_PERF_PRINT( FetchInstalledApps )
       
   535         iObs.InstalledAppsChanged( aMoreRefreshesExpected );
       
   536         }
       
   537     if( aArray == iInstallationFiles )
       
   538         {
       
   539         FLOG_PERF_STOP( FetchInstallationFiles )
       
   540         FLOG_PERF_PRINT( FetchInstallationFiles )
       
   541         iObs.InstallationFilesChanged( aMoreRefreshesExpected );
       
   542         }
       
   543     }
       
   544 
       
   545 // ---------------------------------------------------------------------------
       
   546 // CAppMngr2Model::CAppMngr2Model()
       
   547 // ---------------------------------------------------------------------------
       
   548 //
       
   549 CAppMngr2Model::CAppMngr2Model( RFs& aFsSession, MAppMngr2ModelObserver& aObserver )
       
   550         : CActive( CActive::EPriorityStandard ), iFs( aFsSession ), iObs( aObserver )
       
   551     {
       
   552     CActiveScheduler::Add( this );
       
   553     }
       
   554 
       
   555 // ---------------------------------------------------------------------------
       
   556 // CAppMngr2Model::ConstructL()
       
   557 // ---------------------------------------------------------------------------
       
   558 //
       
   559 void CAppMngr2Model::ConstructL()
       
   560     {
       
   561     FLOG( "CAppMngr2Model::ConstructL" );
       
   562     iClosing = EFalse;
       
   563 
       
   564     iInstalledApps = CAppMngr2AppInfoArray::NewL( *this );
       
   565     iInstallationFiles = CAppMngr2PackageInfoArray::NewL( *this );
       
   566     
       
   567     FLOG_PERF_STATIC_BEGIN( LoadPluginsL )
       
   568     LoadPluginsL();
       
   569     FLOG_PERF_STATIC_END( LoadPluginsL )
       
   570     FLOG_PERF_STATIC_BEGIN( CreateScannerL )
       
   571     CreateScannerL();
       
   572     FLOG_PERF_STATIC_END( CreateScannerL )
       
   573     FLOG_PERF_STATIC_BEGIN( FetchDataTypesL )
       
   574     FetchDataTypesL();
       
   575     FLOG_PERF_STATIC_END( FetchDataTypesL )
       
   576 
       
   577     // start monitoring changes in applications list
       
   578     iApaAppListNotifier = CApaAppListNotifier::NewL( this, CActive::EPriorityStandard );
       
   579     }
       
   580 
       
   581 // ---------------------------------------------------------------------------
       
   582 // CAppMngr2Model::LoadDefaultIconsL()
       
   583 // ---------------------------------------------------------------------------
       
   584 //
       
   585 void CAppMngr2Model::LoadDefaultIconsL( CAknIconArray& aIconArray )
       
   586     {
       
   587     FLOG( "CAppMngr2Model::LoadDefaultIconsL" );
       
   588     
       
   589     MAknsSkinInstance* skinInstance = AknsUtils::SkinInstance();
       
   590     HBufC* bitmapFile = TAppMngr2DriveUtils::FullBitmapFileNameLC( KAppMngr2BitmapFile, iFs );
       
   591     CFbsBitmap* bitmap = NULL;
       
   592     CFbsBitmap* mask = NULL;
       
   593     CGulIcon* icon = NULL;
       
   594     
       
   595     // Note that icons can be graphically-skinned (icon graphic defined in theme)
       
   596     // or color-skinned (icon colors change depending on background color defined
       
   597     // in theme). Normal icons are graphically-skinned and indicator icons are
       
   598     // color-skinned. AknsUtils::CreateGulIconL() creates graphically-skinned icons,
       
   599     // and AknsUtils::CreateColorIconL() creates color-skinned icons. Hence both
       
   600     // of these functions are used below.
       
   601 
       
   602     // Icon 0: EAppMngr2IconIndex_QgnIndiAmInstMmcAdd
       
   603     // Indicator icon for items stored/installed in memory card
       
   604     AknsUtils::CreateColorIconLC( skinInstance, 
       
   605             KAknsIIDQgnIndiMmcAdd, KAknsIIDQsnIconColors, EAknsCIQsnIconColorsCG13,
       
   606             bitmap, mask, *bitmapFile, 
       
   607             EMbmAppmngr2Qgn_indi_mmc_add,
       
   608             EMbmAppmngr2Qgn_indi_mmc_add_mask,
       
   609             KRgbBlack );
       
   610     icon = CGulIcon::NewL( bitmap, mask );
       
   611     icon->SetBitmapsOwnedExternally( EFalse );
       
   612     CleanupStack::Pop( 2 );   // bitmap and mask, order is varying
       
   613     CleanupStack::PushL( icon );
       
   614     aIconArray.AppendL( icon );
       
   615     CleanupStack::Pop( icon );
       
   616 
       
   617     // Icon 1: EAppMngr2IconIndex_QgnIndiFmgrMsAdd
       
   618     // Indicator icon for items stored/installed in mass memory
       
   619     AknsUtils::CreateColorIconLC( skinInstance, 
       
   620             KAknsIIDQgnIndiFmgrMsAdd, KAknsIIDQsnIconColors, EAknsCIQsnIconColorsCG13,
       
   621             bitmap, mask, *bitmapFile, 
       
   622             EMbmAppmngr2Qgn_indi_fmgr_ms_add,
       
   623             EMbmAppmngr2Qgn_indi_fmgr_ms_add_mask,
       
   624             KRgbBlack );
       
   625     icon = CGulIcon::NewL( bitmap, mask );
       
   626     icon->SetBitmapsOwnedExternally( EFalse );
       
   627     CleanupStack::Pop( 2 );   // bitmap and mask, order may vary
       
   628     CleanupStack::PushL( icon );
       
   629     aIconArray.AppendL( icon );
       
   630     CleanupStack::Pop( icon );
       
   631 
       
   632     // Icon 2: EAppMngr2IconIndex_QgnPropUnknown
       
   633     // List icon for items that are not known
       
   634     icon = AknsUtils::CreateGulIconL( skinInstance,
       
   635             KAknsIIDQgnPropUnknown, *bitmapFile,
       
   636             EMbmAppmngr2Qgn_prop_unknown, 
       
   637             EMbmAppmngr2Qgn_prop_unknown_mask );
       
   638     CleanupStack::PushL( icon );
       
   639     aIconArray.AppendL( icon );
       
   640     CleanupStack::Pop( icon );
       
   641 
       
   642     CleanupStack::PopAndDestroy( bitmapFile );
       
   643     
       
   644     // Additionally some unknown indicator icon could be defined.
       
   645     // Now, if some plugin gives incorrect index fox indicator icon,
       
   646     // then no indicator icon is displayed.
       
   647     }
       
   648 
       
   649 // ---------------------------------------------------------------------------
       
   650 // CAppMngr2Model::LoadPluginsL()
       
   651 // ---------------------------------------------------------------------------
       
   652 //
       
   653 void CAppMngr2Model::LoadPluginsL()
       
   654     {
       
   655     FLOG( "CAppMngr2Model::LoadPluginsL" );
       
   656     
       
   657     RImplInfoPtrArray implInfoArray;
       
   658     CleanupResetAndDestroyPushL( implInfoArray  );
       
   659     REComSession::ListImplementationsL( KAppMngr2PluginInterface, implInfoArray );
       
   660 
       
   661     CAppMngr2PluginHolder* pluginHolder = NULL;
       
   662     CImplementationInformation* implInfo;
       
   663     TInt count = implInfoArray.Count();
       
   664     for( TInt index = 0; index < count; index++ )
       
   665         {
       
   666         implInfo = implInfoArray[ index ];
       
   667         FLOG( "CAppMngr2Model::LoadPluginsL, loading %S", &( implInfo->DisplayName() ) );
       
   668         FLOG_PERF_STATIC_BEGIN( DoLoadPluginL );
       
   669         TRAPD( err, pluginHolder = DoLoadPluginL( implInfo->ImplementationUid() ) );
       
   670         FLOG_PERF_STATIC_END( DoLoadPluginL );
       
   671         FLOG( "CAppMngr2Model::DoLoadPluginL( 0x%08x ), err = %d",
       
   672                 implInfo->ImplementationUid().iUid, err );
       
   673         if( err == KErrNone )
       
   674             {
       
   675             CleanupStack::PushL( pluginHolder );
       
   676             iPlugins.AppendL( pluginHolder );
       
   677             CleanupStack::Pop( pluginHolder );
       
   678             }
       
   679         }
       
   680 
       
   681     CleanupStack::PopAndDestroy( &implInfoArray );
       
   682     REComSession::FinalClose();
       
   683     }
       
   684 
       
   685 // ---------------------------------------------------------------------------
       
   686 // CAppMngr2Model::DoLoadPluginL()
       
   687 // ---------------------------------------------------------------------------
       
   688 //
       
   689 CAppMngr2PluginHolder* CAppMngr2Model::DoLoadPluginL( TUid aUid )
       
   690     {
       
   691     CAppMngr2Runtime* plugin = CAppMngr2Runtime::NewL( aUid, *this );
       
   692     CleanupStack::PushL( plugin );
       
   693     CAppMngr2PluginHolder* holder = new (ELeave) CAppMngr2PluginHolder( plugin );
       
   694     CleanupStack::Pop( plugin );
       
   695     return holder;
       
   696     }
       
   697 
       
   698 // ---------------------------------------------------------------------------
       
   699 // CAppMngr2Model::CreateScannerL()
       
   700 // ---------------------------------------------------------------------------
       
   701 //
       
   702 void CAppMngr2Model::CreateScannerL()
       
   703     {
       
   704     iScanner = CAppMngr2Scanner::NewL( *this );
       
   705 
       
   706     TDriveList driveList;
       
   707     TInt driveCount = 0;
       
   708     TInt err = DriveInfo::GetUserVisibleDrives( iFs, driveList, driveCount );
       
   709     User::LeaveIfError( err );
       
   710 
       
   711     // Default directories
       
   712     TFileName path;
       
   713     TInt driveListLength = driveList.Length();
       
   714     for( TInt driveNumber = 0; driveNumber < driveListLength; driveNumber++ )
       
   715         {
       
   716         if( driveList[ driveNumber ] )
       
   717             {
       
   718             TUint driveStatus = 0;
       
   719             err = DriveInfo::GetDriveStatus( iFs, driveNumber, driveStatus );
       
   720             User::LeaveIfError( err );
       
   721 
       
   722             if( !( driveStatus & DriveInfo::EDriveRemote ) )
       
   723                 {
       
   724                 err = PathInfo::GetFullPath( path, driveNumber, PathInfo::EInstallsPath );
       
   725                 User::LeaveIfError( err );
       
   726                 iScanner->AddDirectoryL( path );
       
   727                 }
       
   728             }
       
   729         }
       
   730 
       
   731     // Additional plug-in specific directories
       
   732     TInt pluginCount = iPlugins.Count();
       
   733     for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ )
       
   734         {
       
   735         RPointerArray<HBufC> dirsToScan;
       
   736         CleanupResetAndDestroyPushL( dirsToScan );
       
   737         TRAPD( err, iPlugins[ pluginIndex ]->Runtime().GetAdditionalDirsToScanL( iFs,
       
   738                 dirsToScan ) );
       
   739         if( err == KErrNone )
       
   740             {
       
   741             TInt dirCount = dirsToScan.Count();
       
   742             for( TInt dirIndex = 0; dirIndex < dirCount; dirIndex++ )
       
   743                 {
       
   744                 TPtrC dirName = *( dirsToScan[ dirIndex ] );
       
   745                 iScanner->AddDirectoryL( dirName );
       
   746                 }
       
   747             }
       
   748         CleanupStack::PopAndDestroy( &dirsToScan );
       
   749         }
       
   750     
       
   751     // KSWInstallerPackageFolder directory if defined in CenRep
       
   752     CRepository* cenrep = CRepository::NewLC( KCRUidSWInstallerLV );
       
   753     err = cenrep->Get( KSWInstallerPackageFolder, path );
       
   754     CleanupStack::PopAndDestroy( cenrep );
       
   755     if( err == KErrNone )
       
   756         {
       
   757         TParsePtr parse( path );
       
   758         if( parse.DrivePresent() )
       
   759             {
       
   760             iScanner->AddDirectoryL( path );
       
   761             }
       
   762         else if( parse.PathPresent() )
       
   763             {
       
   764             TDriveList driveList;
       
   765             TInt driveCount = 0;
       
   766             err = DriveInfo::GetUserVisibleDrives( iFs, driveList, driveCount );
       
   767             if( err == KErrNone )
       
   768                 {
       
   769                 TInt driveListLength = driveList.Length();
       
   770                 for( TInt driveNumber = 0; driveNumber < driveListLength; driveNumber++ )
       
   771                     {
       
   772                     if( driveList[ driveNumber ] )
       
   773                         {
       
   774                         TUint driveStatus = 0;
       
   775                         err = DriveInfo::GetDriveStatus( iFs, driveNumber, driveStatus );
       
   776                         if( err == KErrNone && !( driveStatus & DriveInfo::EDriveRemote ) )
       
   777                             {
       
   778                             TChar driveLetter;
       
   779                             if( RFs::DriveToChar( driveNumber, driveLetter ) == KErrNone )
       
   780                                 {
       
   781                                 TFileName fullPath;
       
   782                                 fullPath.Format( KDriveSpec, static_cast<TUint>( driveLetter ) );
       
   783                                 fullPath.Append( path ); 
       
   784                                 iScanner->AddDirectoryL( fullPath );
       
   785                                 }
       
   786                             }
       
   787                         }
       
   788                     }
       
   789                 }
       
   790             }
       
   791         else
       
   792             {
       
   793             // ignore empty values, and values that does not contain valid path
       
   794             }
       
   795         }
       
   796     else
       
   797         {
       
   798         if( err != KErrNotFound )
       
   799             {
       
   800             User::Leave( err );
       
   801             }
       
   802         }
       
   803     }
       
   804 
       
   805 // ---------------------------------------------------------------------------
       
   806 // CAppMngr2Model::FetchDataTypesL()
       
   807 // ---------------------------------------------------------------------------
       
   808 //
       
   809 void CAppMngr2Model::FetchDataTypesL()
       
   810     {
       
   811     FLOG( "CAppMngr2Model::FetchDataTypesL" );
       
   812     
       
   813     TInt pluginCount = iPlugins.Count();
       
   814     for( TInt pluginIndex = 0; pluginIndex < pluginCount; pluginIndex++ )
       
   815         {
       
   816         FLOG( "CAppMngr2Model::FetchDataTypesL: pluginIndex = %d", pluginIndex );
       
   817         TRAP_IGNORE( iPlugins[ pluginIndex ]->FetchDataTypesL() );
       
   818         }
       
   819     }
       
   820 
       
   821 // ---------------------------------------------------------------------------
       
   822 // CAppMngr2Model::CloseInfoMaker()
       
   823 // ---------------------------------------------------------------------------
       
   824 //
       
   825 void CAppMngr2Model::CloseInfoMaker( const CAppMngr2InfoMaker& aMaker )
       
   826     {
       
   827     const CAppMngr2InfoMaker* makerToClose = &aMaker;
       
   828     for( TInt index = iInfoMakers.Count() - 1; index >= 0; index-- )
       
   829         {
       
   830         CAppMngr2InfoMaker* maker = iInfoMakers[ index ]; 
       
   831         if( maker == makerToClose )
       
   832             {
       
   833             iInfoMakers.Remove( index );
       
   834             delete maker;
       
   835             break;
       
   836             }
       
   837         }
       
   838     }
       
   839