iaupdate/IAD/updater/src/iaupdatermngr.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/iaupdate/IAD/updater/src/iaupdatermngr.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,720 @@
+/*
+* Copyright (c) 2007-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:   Handels IAD self update and starting the IAD process 
+*                after self update.
+*
+*/
+
+
+
+#include <apgcli.h>     // RApaLsSession
+#include <apacmdln.h>   // CApaCommandLine
+#include <apgtask.h>
+#include <apgwgnam.h>
+#include <e32std.h>
+#include <ecom/ecom.h>
+#include <swi/sisregistrysession.h>
+#include <swi/sisregistryentry.h>
+#include <catalogsuids.h>
+
+#include "iaupdatermngr.h"
+#include "iaupdaterinstaller.h"
+#include "iaupdaterdialog.h"
+#include "iaupdaterdefs.h"
+
+#include "iaupdaterfilelistfile.h"
+#include "iaupdaterfilelist.h"
+#include "iaupdaterfileinfo.h"
+#include "iaupdaterresultsfile.h"
+#include "iaupdaterresult.h"
+#include "iaupdateridentifier.h"
+
+#include "iaupdatedebug.h"
+
+
+// ======== LOCAL FUNCTIONS ========
+
+// ======== MEMBER FUNCTIONS ========
+
+
+// Maximum time (in microseconds) that ECOM is waited.
+const TInt KMaxEcomWait( 3000000 );
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::NewL() 
+// 
+// -----------------------------------------------------------------------------
+//
+CIAUpdaterMngr* CIAUpdaterMngr::NewL() 
+    {
+    CIAUpdaterMngr* self = CIAUpdaterMngr::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::NewLC() 
+// 
+// -----------------------------------------------------------------------------
+//
+CIAUpdaterMngr* CIAUpdaterMngr::NewLC() 
+    {
+    CIAUpdaterMngr* self = new (ELeave) CIAUpdaterMngr;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;	
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::ConstructL()
+// 
+// -----------------------------------------------------------------------------
+//
+void CIAUpdaterMngr::ConstructL()
+    {
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::ConstructL start");
+    iResultsFile = CIAUpdaterResultsFile::NewL();
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::ConstructL end");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::~CIAUpdater()
+//
+// -----------------------------------------------------------------------------
+//
+CIAUpdaterMngr::~CIAUpdaterMngr()
+    {
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::~CIAUpdaterMngr start");
+    delete iIAInstaller;        
+    delete iResultsFile;
+    iWsSession.Close();
+    iFs.Close();
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::~CIAUpdaterMngr end");
+    }
+  
+  
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::ProcessInstallingL()
+// 
+// -----------------------------------------------------------------------------
+//
+void CIAUpdaterMngr::ProcessInstallingL( TIAUpdaterStartParams& aStartParams )
+    {
+    IAUPDATE_TRACE("[IAUpdater] ProcessInstallingL");
+
+    // Reset member variables
+    iInstallError = KErrNone;
+    iEcomPluginInstalled = EFalse;
+
+
+    // Initialize the results file for operations
+    
+    // Just in case there would be some old information left.
+    iResultsFile->Reset();    
+    // Set the results file path.
+    iResultsFile->SetFilePathL( aStartParams.iResultFilePath );
+
+
+    // Start actual operations.
+
+    // Get the file info data from the file.
+    CIAUpdaterFileListFile* listFile( CIAUpdaterFileListFile::NewLC() );
+
+    // The correct path was given in the starting parameters.
+    // Set this path. So, the object can read its data from the correct file.
+    IAUPDATE_TRACE_1("[IAUpdater] ProcessInstallingL set path: %S", 
+                     &aStartParams.iInitFilePath);
+    listFile->SetFilePathL( aStartParams.iInitFilePath );
+
+    // Read data from the defined file.
+    listFile->ReadDataL();
+
+    // Remove the file, because all the information from the list file
+    // is now available in the lisFile object. Then, it will not be reused 
+    // if this operation leaves and iaupdate is restarted later.
+    IAUPDATE_TRACE_1("[IAUpdater] ProcessInstallingL fileRemove: %S", 
+                     &listFile->FilePath());
+    User::LeaveIfError( listFile->RemoveFile() );
+    IAUPDATE_TRACE("[IAUpdater] File removed.");
+    
+    // Now, get the info that is required for the dialog.
+    // Notice, that we keep the index value to constant. 
+    // This application supposes that all the installable
+    // bundles are part of the one same packet. So, indexing
+    // is not changed.
+    TInt KIndex( listFile->PckgStartIndex() );
+    const TInt KTotalCount( listFile->TotalPckgCount() );
+    // Check if the dialogs should be shown
+    const TBool KSilent( listFile->Silent() );
+
+    TInt count( listFile->FileList().Count() );
+    TBool showing( EFalse );
+    User::LeaveIfError( iFs.Connect() );
+    User::LeaveIfError( iWsSession.Connect( iFs ) );
+    CIAUpdaterDialog* dialogs( CIAUpdaterDialog::NewLC( iFs, *this ) );
+    if ( count > 0 )
+        {
+        TInt nameIndex( 0 );
+        for ( TInt i = 0; i < count; ++i )
+            {
+            IAUPDATE_TRACE_1("[IAUpdater] FileList: %d", i);
+            iCurrentFileList = listFile->FileList()[ i ];
+
+            if ( iInstallError == KErrNone )
+                {
+                IAUPDATE_TRACE("[IAUpdater] No errors. Continue install.");
+                if ( !KSilent && i == nameIndex )
+                    {
+                    IAUPDATE_TRACE("[IAUpdater] Show dialog");
+                    // If the dialog should be shown, then use the constant values for the
+                    // indexing and total count.
+                    // Search for the bundle name. Hidden names are not shown, so the first
+                    // not hidden name will be shown. Notice, that here we think that the name
+                    // that describes also the hidden items is non hidden item after those hidden
+                    // items.
+                    for ( TInt j = nameIndex; j < count; ++j )
+                        {
+                        IAUPDATE_TRACE_1("[IAUpdater] nameIndex: %d", j);
+                        CIAUpdaterFileList* list( listFile->FileList()[ j ] );
+                        if ( !list->Hidden() 
+                             || j + 1 == count && !showing )
+                            {
+                            if ( !KSilent && showing )
+                                {
+                                IAUPDATE_TRACE("[IAUpdater] Cancel waiting note");
+                                // Stop showing wait note before starting new note.       
+                                dialogs->CancelWaitingNoteL();
+                                showing = EFalse;
+                                }
+
+                            // Show dialog if the item is not hidden or 
+                            // if all the items are hidden and no dialog is showing, then show
+                            // the last one.
+                            // The last item is always thought as non hidden because it is the main item.
+                            // All other items before it are items that the main item depends on.
+                            // Show waiting note because we are starting the install operation
+                            IAUPDATE_TRACE_1("[IAUpdater] Show new waiting note: %S", 
+                                             &list->BundleName());
+                            dialogs->
+                                ShowWaitingNoteL( list->BundleName(), 
+                                                  KIndex, KTotalCount );                    
+                            nameIndex = j + 1;
+                            showing = ETrue;
+                            break;
+                            }
+                        }
+                    }
+
+                // Delete old installer. So, the new installer will be configured 
+                // with correct values.
+                delete iIAInstaller; 
+                iIAInstaller = NULL;            
+                iIAInstaller = CIAUpdaterInstaller::NewL( iFs, *this );
+                ProcessSISFilesL( *iCurrentFileList );
+                    
+                // Notice, that this is synchronous installation that will wait until the
+                // active install operation has finished its job. 
+                // Uses, CActiveSchedulerWait.
+                // So, be cautious about nested loops. 
+                iIAInstaller->StartInstallingL();                     
+                }
+            else if ( iInstallError == KErrCancel )
+                {
+                // Because cancel occurred during the last install,
+                // cancel installation of other items. 
+                // Set error code as KErrCancel for remaining items.
+                // Setting of these parameters is so quick operation,
+                // that do not show separate dialogs for this after
+                // the possible shown dialog is closed below.
+                IAUPDATE_TRACE("[IAUpdater] Cancel occurred. So, do not try to install.");
+                SetProcessParametersL( KErrCancel );
+                }
+            else
+                {
+                // Because an error occurred during the last install,
+                // abort installation of other items. 
+                // Set error code as KErrAbort for remaining items.
+                // Setting of these parameters is so quick operation,
+                // that do not show separate dialogs for this after
+                // the possible shown dialog is closed below.
+                IAUPDATE_TRACE("[IAUpdater] Error occurred. So, do not try to install.");
+                SetProcessParametersL( KErrAbort );
+                }
+            }
+
+        IAUPDATE_TRACE("[IAUpdater] Finished installation.");
+
+        if ( iEcomPluginInstalled )
+            {
+            IAUPDATE_TRACE("[IAUpdater] Wait for the ECOM.");
+            // Ecom plugin was installed during the update flow.
+            // Wait for the ECOM to finish indexing of its plugins.
+            EcomWaiterL();
+            }
+
+        }
+
+    
+    // Increase the index by one for the result. 
+    // Notice, that here the index may become as great as KTotalCount but
+    // it is up to the user of the results to check this later.
+    iResultsFile->SetPckgStartIndex( KIndex + 1 );
+    iResultsFile->SetTotalPckgCount( KTotalCount );
+    
+    // Look at is there iaupdate instance running
+    //
+    TApaTaskList tasklist( iWsSession );   
+    TApaTask task = tasklist.FindApp( TUid::Uid( IAUpdaterDefs::KIADUpdateUid3 ) );
+  
+    
+    
+    IAUPDATE_TRACE("[IAUpdater] Final process checks");
+      
+    // Result data is not written if user exit (end key pressed) and  
+    // there is not iaupdate running
+    if ( !iUserExit || task.Exists() )
+        {
+        IAUPDATE_TRACE("[IAUpdater] Write results file data");
+    	iResultsFile->WriteDataL();
+        }
+        
+    // Iaupdate is restarted only when there is not running instance.  
+    // When user exit (end key pressed) new iaupdate is not launched     
+    if ( !iUserExit && !task.Exists() )
+        {
+        IAUPDATE_TRACE("[IAUpdater] Start IAUpdate UI process");
+    	StartIADProcessesL();
+        }
+    
+    if ( !KSilent && showing )
+        {
+        IAUPDATE_TRACE("[IAUpdater] Stop showing dialog.");
+        // Stop showing wait note because we have finished this installation.       
+        TRAP_IGNORE( dialogs->CancelWaitingNoteL() );
+        CleanupStack::PopAndDestroy( dialogs );
+        }
+    
+    CleanupStack::PopAndDestroy( listFile );
+    listFile = NULL;
+    
+    if ( iUserExit )
+        {
+        IAUPDATE_TRACE("[IAUpdater] User exit");
+        User::Leave( IAUpdaterDefs::KIAUpdaterShutdownRequest );
+        }   
+  
+
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::ProcessInstallingL end");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::UserCancel
+//
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::UserCancel()
+    {
+    IAUPDATE_TRACE("[IAUpdater] UserCancel() start");
+    if ( iIAInstaller )
+        {
+    	iIAInstaller->CancelOperation();
+        }
+    IAUPDATE_TRACE("[IAUpdater] UserCancel() end");    
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::UserExit()
+//
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::UserExit()
+    {
+    IAUPDATE_TRACE("[IAUpdater] UserExit() start");
+    if ( iIAInstaller )
+        {
+    	iIAInstaller->CancelOperation();
+    	iUserExit = ETrue;
+        }
+    IAUPDATE_TRACE("[IAUpdater] UserExit() end"); 
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::ProcessSISFilesL()
+//
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::ProcessSISFilesL( CIAUpdaterFileList& aList )
+    { 
+    IAUPDATE_TRACE("[IAUpdater] ProcessSISFilesL start");       
+
+    TInt count( aList.FileInfos().Count() );
+    for ( TInt i = 0; i < count; ++i )
+        {
+        CIAUpdaterFileInfo* info( aList.FileInfos()[ i ] );
+        const TDesC& sisFileName( info->FilePath() );
+        iIAInstaller->AddFileToInstallL( sisFileName );
+        }
+
+    IAUPDATE_TRACE("[IAUpdater] ProcessSISFilesL end");        
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::SetProcessParametersL
+// Set installation return parameters for IAD process.
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::SetProcessParametersL( TInt aErr )
+    {    
+    IAUPDATE_TRACE_1("[IAUpdater] SetProcessParametersL start: %d", aErr);
+
+    if ( aErr == KErrNone )
+        {
+        IAUPDATE_TRACE("[IAUpdater] Installation was success");
+        // Because self update related item was successfully installed,
+        // make sure that the IAD is closed. In certain cases, the
+        // installer may not close the IAD. For example, if only
+        // NCD Engine is updated but IAD is not, or, if original
+        // IAD was in ROM but new update is installed into another
+        // drive.
+        CloseIADProcessesL();
+
+        // Check if the installed package should be thought as
+        // an ecom plugin. The UID value is used for the checking.
+        if ( IsEcomPlugin( iCurrentFileList->Identifier().Uid() ) )
+            {
+            IAUPDATE_TRACE("[IAUpdater] ECOM plugin was installed.");
+            iEcomPluginInstalled = ETrue;
+            }
+        }
+    else
+        {
+        IAUPDATE_TRACE_1("[IAUpdater] SetProcessParametersL error: %d", aErr);
+        // Set the error value to the member variable.
+        // So, the manager will know, that it will not try to install
+        // any other items after this.
+        iInstallError = aErr;
+        }
+    
+    CIAUpdaterResult* result( CIAUpdaterResult::NewLC() );
+    CIAUpdaterIdentifier& resultIdentifier( result->Identifier() );
+    CIAUpdaterIdentifier& currentIdentifier( iCurrentFileList->Identifier() );
+    resultIdentifier.SetIdL( currentIdentifier.Id() );
+    resultIdentifier.SetNamespaceL( currentIdentifier.Namespace() );
+    resultIdentifier.SetUid( currentIdentifier.Uid() );
+    result->SetErrorCode( aErr );
+    result->SetHidden( iCurrentFileList->Hidden() );
+    iResultsFile->Results().AppendL( result );
+    // Ownership of the result was transferred to the array.
+    CleanupStack::Pop( result );
+
+    IAUPDATE_TRACE("[IAUpdater] SetProcessParametersL end");
+    }
+    
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::StartIADProcessesL()
+// Start IAD process after installation.
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::StartIADProcessesL()
+    {    
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::StartIADProcessesL start"); 
+    // Apparc is not always up-to-date just after installation
+    // To guarantee that just installed iaupdate.exe will be launched
+    // it's checked that RApaLsSession is up-to-date before launching iupdatelancher.exe
+    
+    
+    TFileName fullNameOfIaupdate; 
+    InstalledIAUpdateL( fullNameOfIaupdate );
+    
+    RApaLsSession apa;
+    User::LeaveIfError( apa.Connect() );
+    CleanupClosePushL(apa);
+    
+    TBool foundInApparc = EFalse;
+    TApaAppInfo info;
+    // trying with 0.5 seconds intervals  max. 10 seconds. 
+    for( TInt i = 0; !foundInApparc && i < 21 ; i++)  
+        {
+        if ( i > 0 )
+            {
+            User::After( 500000 );
+            }
+        User::LeaveIfError( apa.GetAppInfo( info, TUid::Uid( IAUpdaterDefs::KIADUpdateUid3 ) ) );
+        if ( info.iFullName.CompareF ( fullNameOfIaupdate ) == 0 )
+            {
+            foundInApparc = ETrue;
+            }
+        }
+    CleanupStack::PopAndDestroy( &apa );   
+    
+    RProcess process;
+    User::LeaveIfError( 
+        process.Create( IAUpdaterDefs::KIAUpdateLauncherExe, KNullDesC ) );
+    process.Resume();
+    process.Close();
+    
+    User::LeaveIfError( 
+        process.Create( IAUpdaterDefs::KIAUpdateBgCheckerExe, KNullDesC ) );
+    process.Resume();
+    process.Close();    
+
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::StartIADProcessesL end"); 
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::CloseIADProcessesL()
+// Close IAD process after one successfull installation.
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::CloseIADProcessesL()
+    {
+    IAUPDATE_TRACE("[IAUpdater] CloseIADProcessesL start");
+    
+    //close background checker 
+    
+    TBool continueScanning = ETrue;
+    TFindProcess findProcess;
+    // : add search pattern to optimizing
+    TFullName fullName;
+    while( continueScanning )
+		{
+		if ( findProcess.Next( fullName ) == KErrNone ) 
+		    {
+		    RProcess process;
+	        User::LeaveIfError( process.Open( findProcess ) );
+	        TUid sid( process.SecureId() );
+	        if ( sid == IAUpdaterDefs::KUidIABgChecker && process.ExitType() == EExitPending )
+		        {
+		        process.Kill( KErrNone );
+		        continueScanning = EFalse;
+		        }
+		    process.Close(); 	
+		    }
+		else
+		    {
+		    continueScanning = EFalse;	
+		    }   
+		}
+    
+    //close IAD launcher
+    TInt wgId=0;
+    CApaWindowGroupName* wgName = CApaWindowGroupName::NewL( iWsSession );
+    CleanupStack::PushL( wgName );
+    TUid launcherUid( TUid::Uid( IAUpdaterDefs::KIADUpdateLauncherUid3 ) );
+    CApaWindowGroupName::FindByAppUid( launcherUid, iWsSession, wgId );
+    if ( wgId != KErrNotFound )
+        {
+        IAUPDATE_TRACE_1("[IAUpdater] IAD process found, wgId = %d", wgId ); 
+        wgName->ConstructFromWgIdL( wgId );
+        TApaTask task( iWsSession );
+        task.SetWgId( wgId );
+        RThread thread;
+        User::LeaveIfError( thread.Open( task.ThreadId() ) );
+        CleanupClosePushL(thread);
+                        
+        RProcess process;
+        User::LeaveIfError( thread.Process( process ) );
+        CleanupClosePushL( process );
+
+        TRequestStatus processStatus;
+        process.Logon( processStatus );
+                
+        // IAD launcher application should response to shutdown event, so just wait for it       
+        task.SendSystemEvent( EApaSystemEventShutdown );
+        IAUPDATE_TRACE("[IAUpdater] Closing IAD launcher");
+        User::WaitForRequest( processStatus );
+        IAUPDATE_TRACE("[IAUpdater] IAD launcher closed");
+        CleanupStack::PopAndDestroy( &process );
+        CleanupStack::PopAndDestroy( &thread );
+        }
+    CleanupStack::PopAndDestroy(wgName);
+    wgName = NULL;
+    
+    //close all processes of IAD 
+    wgId=0;
+    wgName = CApaWindowGroupName::NewL( iWsSession );
+	CleanupStack::PushL( wgName );
+	TUid iadUid( TUid::Uid( IAUpdaterDefs::KIADUpdateUid3 ) );
+	CApaWindowGroupName::FindByAppUid( iadUid, iWsSession, wgId );
+	while (wgId != KErrNotFound )
+		{
+		IAUPDATE_TRACE_1("[IAUpdater] IAD process found, wgId = %d", wgId ); 	
+		wgName->ConstructFromWgIdL( wgId );
+		TApaTask task( iWsSession );
+		task.SetWgId( wgId );
+		RThread thread;
+		User::LeaveIfError( thread.Open( task.ThreadId() ) );
+		CleanupClosePushL(thread);
+				
+		RProcess process;
+		User::LeaveIfError( thread.Process( process ) );
+		CleanupClosePushL( process );
+
+		TRequestStatus processStatus;
+		process.Logon( processStatus );
+		
+		// IAD application should response to shutdown event, so just wait for it		
+		task.SendSystemEvent( EApaSystemEventShutdown );
+        IAUPDATE_TRACE("[IAUpdater] Closing IAD");
+		User::WaitForRequest( processStatus );
+		IAUPDATE_TRACE("[IAUpdater] IAD closed");
+		CleanupStack::PopAndDestroy( &process );
+		CleanupStack::PopAndDestroy( &thread );
+		
+		// See if there's still an instance of IAD running.
+		CApaWindowGroupName::FindByAppUid( iadUid, iWsSession, wgId );
+		}
+	CleanupStack::PopAndDestroy(wgName);	
+  
+    IAUPDATE_TRACE("[IAUpdater] CloseIADProcessesL end");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::EcomWaiter()
+// Wait until the ECOM has updated its index list.
+// -----------------------------------------------------------------------------
+//	
+void CIAUpdaterMngr::EcomWaiterL() const
+    {
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::EcomWaiter() begin");
+
+    const TTimeIntervalMicroSeconds32 KWaitTime( KMaxEcomWait );
+
+    REComSession& session( REComSession::OpenL() );
+    CleanupClosePushL( session );
+
+    IAUPDATE_TRACE("[IAUpdater] Create timer"); 
+    RTimer timer;
+    CleanupClosePushL( timer );
+    timer.CreateLocal();
+
+    IAUPDATE_TRACE("[IAUpdater] Start timer");
+    TRequestStatus timerStatus( KErrNone );
+    timer.After( timerStatus, KWaitTime ); 
+
+    IAUPDATE_TRACE("[IAUpdater] Call notifier"); 
+    TRequestStatus ecomStatus( KErrNone );
+    session.NotifyOnChange( ecomStatus );
+
+    // Wait for the first request to complete
+    IAUPDATE_TRACE("[IAUpdater] Wait first");
+    User::WaitForRequest( ecomStatus, timerStatus );
+
+    IAUPDATE_TRACE_2("[IAUpdater] Continue after waitforrequest: %d, %d",
+                     ecomStatus.Int(), timerStatus.Int());
+
+    // These are synchronous operations.
+    // So, no need to use WaitForRequest after these.
+    // It does not hurt to call cancel to completed operation. 
+    // So, no need to check which one was completed.
+    session.CancelNotifyOnChange( ecomStatus );
+    timer.Cancel(); 
+
+    // Notice, that in this debug text another status should always imply
+    // that cancel operation is done. And, another will give the result of the
+    // completed operation.
+    IAUPDATE_TRACE_2("[IAUpdater] Continue after second waitforrequest: %d, %d",
+                     ecomStatus.Int(), timerStatus.Int());
+
+    CleanupStack::PopAndDestroy( &timer );
+    CleanupStack::PopAndDestroy( &session );
+    
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::EcomWaiter() end");
+    }
+
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::IsEcomPlugin()
+// Compares the given UID to the known ECOM plug-in installation package UIDs.
+// -----------------------------------------------------------------------------
+//	
+TBool CIAUpdaterMngr::IsEcomPlugin( const TUid& aUid ) const
+    {
+    IAUPDATE_TRACE_1("[IAUpdater] CIAUpdaterMngr::IsEcomPlugin() begin: %d",
+                     aUid.iUid);
+
+    TBool isEcomPlugin( EFalse );
+
+    switch ( aUid.iUid )
+        {
+        // Part of these NCD UIDs are not exactly ECOM plugins themselves
+        // but they are most likely part of the package that contains
+        // a plugin. So, if any of these matches. Then just think
+        // the package as ECOM plugin.
+        case KCatalogsServerUid:
+        case KNcdProviderUid:
+        case KCatalogsEngineUid:
+        case KCatalogsEngineInterfaceUid:
+        case KCatalogsEngineImplementationUid:
+            IAUPDATE_TRACE("[IAUpdater] ECOM plugin.");
+            isEcomPlugin = ETrue;
+            break;
+
+        default:
+            IAUPDATE_TRACE("[IAUpdater] Not ECOM plugin.");
+            break;
+        }
+
+    IAUPDATE_TRACE("[IAUpdater] CIAUpdaterMngr::IsEcomPlugin() end");
+
+    return isEcomPlugin;
+    }
+
+// -----------------------------------------------------------------------------
+// CIAUpdaterMngr::InstalledIAUpdateL
+// 
+// -----------------------------------------------------------------------------
+//
+void CIAUpdaterMngr::InstalledIAUpdateL( TFileName& aFullName ) const
+    {
+    Swi::RSisRegistrySession registrySession;
+    Swi::RSisRegistryEntry entry;
+    User::LeaveIfError( registrySession.Connect() );
+    CleanupClosePushL( registrySession );
+    TInt exeFound = EFalse;
+    if ( entry.Open( registrySession, TUid::Uid( IAUpdaterDefs::KIADUpdateUid3 ) ) == KErrNone )
+        {
+        CleanupClosePushL( entry );
+        RPointerArray<HBufC> files; 
+        entry.FilesL( files );
+        for( TInt i = 0; !exeFound && i < files.Count(); i++)
+            {
+            TFileName fullName = *files[i]; 
+            TParse parse;
+            parse.Set( fullName, NULL, NULL);    
+            if ( parse.NameAndExt().CompareF( IAUpdaterDefs::KIAUpdateExe() ) == 0 )
+                {
+                aFullName = fullName;
+                exeFound = ETrue;
+                }
+            }
+        files.ResetAndDestroy();    
+        CleanupStack::PopAndDestroy( &entry );
+        }
+    CleanupStack::PopAndDestroy( &registrySession );
+    }
+
+//EOF