iaupdate/IAD/ui/src/iaupdateuicontroller.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 17 Dec 2009 08:51:10 +0200
changeset 0 ba25891c3a9e
child 15 51c0f5edf5ef
permissions -rw-r--r--
Revision: 200949 Kit: 200951

/*
* 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:   This module contains the implementation of CIAUpdateUiController
*                class member functions.
*
*/



// INCLUDES
#include <avkon.hrh>
#include <StringLoader.h> 
#include <centralrepository.h>
#include <AknUtils.h>
#include <SWInstDefs.h>
#include <avkon.rsg>
#include <featurecontrol.h>
#include <iaupdate.rsg>
#include <iaupdateparameters.h>

#include "iaupdateuicontroller.h"
#include "iaupdateuicontrollerobserver.h"
#include "iaupdateappui.h"
#include "iaupdate.hrh"
#include "iaupdatewaitdialog.h"
#include "iaupdateprogressdialog.h"
#include "iaupdatenode.h"
#include "iaupdatefwnode.h"
#include "iaupdatebasenode.h"
#include "iaupdatenodefilter.h"
#include "iaupdatefactory.h"
#include "iaupdatestarter.h"
#include "iaupdateprivatecrkeys.h"
#include "iaupdatecontrollerfile.h"
#include "iaupdateuiconfigdata.h"
#include "iaupdatedialogutil.h"
#include "iaupdateutils.h"
#include "iaupdateagreement.h"
#include "iaupdateautomaticcheck.h"
#include "iaupdateroaminghandler.h"
#include "iaupdatependingnodesfile.h"
#include "iaupdaterestartinfo.h"
#include "iaupdaterresultsfile.h"
#include "iaupdaterresult.h"
#include "iaupdateridentifier.h"
#include "iaupdateruids.h"
#include "iaupdaterdefs.h"
#include "iaupdatetools.h"
#include "iaupdateparametersfilemanager.h"
#include "iaupdateerrorcodes.h"
#include "iaupdatefileconsts.h"
#include "iaupdatefirsttimeinfo.h"
#include "iaupdaterefreshhandler.h"
#include "iaupdatedebug.h"


// cenrep in emulator:
// copy 2000F85A.txt to '\epoc32\release\winscw\udeb\Z\private\10202be9\'
// delete 2000F85A.txt from 'epoc32\winscw\c\private\10202be9\persists'
//
// cenrep in hardware:
// copy 2000F85A.txt to '\epoc32\data\Z\private\10202be9'
//


// This is a static function that is used with RPointerArray::Sort to sort
// the nodes according to their node depths and other special values.
TInt SortSelectedNodes( const MIAUpdateNode& aNode1, const MIAUpdateNode& aNode2 )
    {
    // Temporarily use the const_cast here to get the base node.
    // After that, base node is set back to const. So, the casting here
    // is safe to do.
    const MIAUpdateBaseNode& baseNode1( 
        const_cast< MIAUpdateNode& >( aNode1 ).Base() );
    const MIAUpdateBaseNode& baseNode2( 
        const_cast< MIAUpdateNode& >( aNode2 ).Base() );

    if ( baseNode1.Uid().iUid == KIAUpdaterUid
         && baseNode2.Uid().iUid != KIAUpdaterUid )
        {
        // Self updater should always be the first one
        // in the node array.
        return -1;
        }
    else if ( baseNode2.Uid().iUid == KIAUpdaterUid
              && baseNode1.Uid().iUid != KIAUpdaterUid )
        {
        // Self updater should always be the first one
        // in the node array.
        return 1;
        }
    else if ( aNode1.IsSelfUpdate() && !aNode2.IsSelfUpdate() )
        {
        // Self updates always before normal nodes.
        return -1;
        }
    else if ( !aNode1.IsSelfUpdate() && aNode2.IsSelfUpdate() )
        {
        // Self updates always before normal nodes.
        return 1;
        }
    else
        {
        // The depth can be used in normal cases to make sure that dependency
        // nodes are handled before their dependants. Notice, that this is
        // a safe way even if dependency chain contains hidden nodes.
        // The dependency nodes should be before its dependants in the array.
        // The depth value informs how deep in the dependency hierarchy the node is.
        // A depth value zero means that the node is a root. If multiple branches lead to
        // a same node, then the greatest depth value is used for the node.
        // The node can not ever depend on the node that has the same or greater depth.

        TInt depthDiff( aNode2.Depth() - aNode1.Depth() );

        if ( depthDiff != 0 )
            {
            // Depths were different.
            // In some cases, the user may have chosen a dependency node only
            // and left the dependant out. Then this node may be moved unnecessarily
            // in the array. But because dependecies may change the selection order
            // usually quite much, the possible unnecessary movement here should not
            // matter. Notice, that using the depth values is really safe way to make
            // sure the dependency nodes are handled before their dependants.
            return depthDiff;
            }
        else
            {
            // Because depthDiffs equal we need to do some additional checking.
            // This kind of comparison is also used in the filter.
            // See: CIAUpdateNodeFilter::CompareAndMarkFilterNodes
            TInt importanceDiff( 
                baseNode2.Importance() - baseNode1.Importance() );
            if ( importanceDiff != 0 )
                {
                // Sort according to the importance because importances
                // differ.
                return importanceDiff;
                }
            else
                {
                // Because evertyhing else matched, we finally check
                // the name. Items should be handled in alphabetical order
                // now.
                return baseNode1.Name().CompareC( baseNode2.Name() );
                }
            }
        }
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::NewLC
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CIAUpdateUiController* CIAUpdateUiController::NewLC( 
    MIAUpdateUiControllerObserver& aObserver )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::NewLC() begin");
    CIAUpdateUiController* self = 
        new( ELeave ) CIAUpdateUiController( aObserver );
    CleanupStack::PushL( self );
    self->ConstructL();
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::NewLC() end");
    return self;
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::NewL
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
CIAUpdateUiController* CIAUpdateUiController::NewL( 
    MIAUpdateUiControllerObserver& aObserver )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::NewL() begin");
    CIAUpdateUiController* self = 
        CIAUpdateUiController::NewLC( aObserver );
    CleanupStack::Pop( self );
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::NewL() end");
    return self;
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::CIAUpdateUiController
// C++ constructor
// -----------------------------------------------------------------------------
//
CIAUpdateUiController::CIAUpdateUiController( 
    MIAUpdateUiControllerObserver& aObserver )
: iObserver( aObserver ),
  iState( EIdle )
    {    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CIAUpdateUiController()");
    iEikEnv = CEikonEnv::Static();
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::ConstructL
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::ConstructL()
    {    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ConstructL() begin");
        
    iClosingAllowedByClient = ETrue;
    iController = 
        IAUpdateFactory::CreateControllerL( 
            TUid::Uid( KIAUpdateFamilyUid ), *this );
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ConstructL() 1");
    iFilter = CIAUpdateNodeFilter::NewL();
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ConstructL() 2");

    // Notice, this will read the init values from the file
    // if the file exists. Otherwise, default values are used.
    iControllerFile = 
        CIAUpdateControllerFile::NewL( IAUpdateFileConsts::KControllerFile );
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ConstructL() 3");
    
    iConfigData = CIAUpdateUiConfigData::NewL();
    
    iOffConfigurated = !IAUpdateEnabledL();

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ConstructL() end");   
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::~CIAUpdateUiController
// Destructor
// -----------------------------------------------------------------------------
//
CIAUpdateUiController::~CIAUpdateUiController()
    {    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::~CIAUpdateUiController() begin");

    CancelOperation();
    delete iController;
    iNodes.Reset();
    iFwNodes.Reset();
    iSelectedNodesArray.Reset();
    iServicePackNodes.Reset();
    delete iFilter;
    delete iControllerFile;
    delete iIdle;
    delete iStarter;
    delete iConfigData;
    delete iRoamingHandler;
    delete iParams;
    delete iRefreshHandler;
    delete iPreviousSelections;

    // If dialogs have not been released yet, release them now.
    // ProcessFinishedL() should normally be used for dialogs but
    // here just use non-leaving delete. In normal cases, dialogs should
    // already be released in the end of the update flow before coming here.
    delete iWaitDialog;
    delete iProgressDialog;
        
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::~CIAUpdateUiController() end");
    }        


// -----------------------------------------------------------------------------
// CIAUpdateUiController::ConfigData
// Returns the configuration data from the config file.
// -----------------------------------------------------------------------------
//
const CIAUpdateUiConfigData& CIAUpdateUiController::ConfigData() const
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ConfigData()");
    return *iConfigData;
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::SetDefaultConnectionMethodL
// Sets the connection method for the update network connection.
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::SetDefaultConnectionMethodL( const TIAUpdateConnectionMethod& aMethod )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::SetDefaultConnectionMethodL() begin");

    iController->SetDefaultConnectionMethodL( aMethod );

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::SetDefaultConnectionMethodL() end"); 
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::CheckUpdatesL
// Updates the update item list.
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::CheckUpdatesL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CheckUpdatesL() begin");

    iCountOfAvailableUpdates = 0;
    
    if ( iParams )
        {
    	iFilter->SetFilterParams( iParams ); //iParams ownership is changed
    	iParams = NULL;
        }
     
    TBool agreementAccepted( EFalse ); 
    CIAUpdateAgreement* agreement = CIAUpdateAgreement::NewLC();
    agreementAccepted = agreement->AgreementAcceptedL();
    if ( ( !agreementAccepted )&& ( iRequestType != IAUpdateUiDefines::ECheckUpdates ) )
        {
        // agreement (disclaimer) dialog is not prompted when CheckUpdates is called
        //
        // Refresh from network is allowed when first time case 
        iRefreshFromNetworkDenied = EFalse;
    	agreementAccepted = agreement->AcceptAgreementL();	
        }
        	
    CleanupStack::PopAndDestroy( agreement );
             
    if ( !agreementAccepted )
        {
        if ( iRequestType == IAUpdateUiDefines::ECheckUpdates )
            {
            CIAUpdateAutomaticCheck* automaticCheck = CIAUpdateAutomaticCheck::NewLC();
            TBool autoUpdateCheckEnabled = automaticCheck->AutoUpdateCheckEnabledL();
            CleanupStack::PopAndDestroy( automaticCheck );
            if ( !autoUpdateCheckEnabled )
                {
                iObserver.RefreshCompleteL( ETrue, KErrNone );
                return;
                }
            }
        else if ( iRequestType == IAUpdateUiDefines::EShowUpdates )
            {
       	    iObserver.UpdateCompleteL( KErrNone ); 
       	    return;
       	    }
       	else
       	    {
       	    CIAUpdateAppUi* appUi = 
       	            static_cast< CIAUpdateAppUi* >( iEikEnv->EikAppUi() );
            appUi->Exit();
       	    return;	
       	    }
        }
            
    if ( iRequestType == IAUpdateUiDefines::EShowUpdates && iRefreshed )
        {
    	iFilter->FilterAndSortNodesL( iNodes, iFwNodes );
        iObserver.RefreshCompleteL( ETrue, KErrNone );
        }
    else
        {
        if ( IsStartedByLauncher() && AllowNetworkRefreshL() )
            {
        	iUserRoamingRejection = iRoamingHandler->RoamingRejectionL();
            }

        TInt ret( iController->Startup() );
        if ( ret == KErrAlreadyExists )   
            {
            IAUPDATE_TRACE("[IAUPDATE] Controller startup already done.");
            // Controller startup has already been done. 
            // So, no operation was started from the controller. 
            // So, call StartupComplete directly from here. 
    	    StartupComplete( KErrNone );
            }
        else
            {
            IAUPDATE_TRACE_1("[IAUPDATE] Controller startup error code: %d", ret);
            // Something went wrong with controller startup if error code is not
            // KErrNone here. Above, KErrAlreadyExists was handled separately.
            // If ret is KErrInUse, then startup was still going on
            // and new startup should not be called. Also, leave in that case.
            User::LeaveIfError( ret );	
            }	
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CheckUpdatesL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::StartUpdateL
// Starts software updating
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::StartUpdateL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartUpdateL() begin");

    // Just to be sure that self update related information
    // is always in resetted state when new update flows are
    // started.
    iController->ResetSelfUpdate();

    iUserRoamingRejection = iRoamingHandler->RoamingRejectionL();
    if ( !iUserRoamingRejection )
        {
        CreateSelectedNodesArrayL();
                
        if ( !IAUpdateUtils::SpaceAvailableInInternalDrivesL( iSelectedNodesArray ) )
            {
    	    HBufC* noteText = NULL;
            noteText = StringLoader::LoadLC( R_IAUPDATE_INSUFFICIENT_MEMORY );
            IAUpdateDialogUtil::ShowInformationQueryL( *noteText ); 
            CleanupStack::PopAndDestroy( noteText );
            }
        else
            {
            if ( !IsStartedByLauncher() )
                {
                if ( !iStarter )
                    {
                    // Notice, that the ownership of the filter parameters will
                    // remain in the filter.
                    CIAUpdateParameters* params = iFilter->FilterParams();
        	        iStarter = CIAUpdateStarter::NewL( params->CommandLineExecutable(), 
        	                                           params->CommandLineArguments() );
                    }
                }
            // Inform the controller that we are now starting updates. This way the
            // controller can handle situations as a whole and not as one item at the
            // time.
            iController->StartingUpdatesL();
            
            iFileInUseError = EFalse;
            // Set the node index to -1 because ContinueUpdateL increases it by one
            // in the beginning of the function. So, we can use the ContinueUpdateL
            // also in here.
            iNodeIndex = -1;
            ContinueUpdateL( EFalse );
            }
        }

	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartUpdateL() end");
    }

  
// ---------------------------------------------------------------------------
// CIAUpdateUiController::ContinueUpdateL
// Continues software updating from the next node
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::ContinueUpdateL( TBool aSelfUpdateFinished )
    {
    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateUiController::ContinueUpdateL() begin: %d",
                   aSelfUpdateFinished );
    
    // Get the node index of the next node.
    // The node that is indexed by iNodeIndex has already been handled in
    // previous loop. So, increase the temp index by one here as it will be done
    // in the while loop below for real index.
    TInt tmpIndex( iNodeIndex + 1 );
    if ( tmpIndex > 0 
        && tmpIndex < iSelectedNodesArray.Count()
        && iSelectedNodesArray[ tmpIndex - 1 ]->IsSelfUpdate()
        && !iSelectedNodesArray[ tmpIndex ]->IsSelfUpdate()
        && !aSelfUpdateFinished
        && iController->SelfUpdateDataExists() )
        {
        IAUPDATE_TRACE_1("[IAUPDATE] Self updates have been handled now: %d",
                         iNodeIndex);
        // Self update should be started now because
        // current node is not anymore self update and previous nodes were.
        // UpdateCompleteL will start the self updater and inform observers.
        // If no self update data can be found, then there has been some error
        // when self update data has been set. So, then there is no reason to start
        // self updater here. In that case, continue normally in the while loop below if
        // other items are waiting for update.
        iNodeIndex++;
        UpdateCompleteL( KErrNone );

        // Do not continue after this.
        return;
        }

    TBool nextUpdate( ETrue );
    while ( nextUpdate )
       {
       IAUPDATE_TRACE_1("[IAUPDATE] Next update while loop: %d",
                        iNodeIndex);
       iNodeIndex++;
       if ( iNodeIndex < iSelectedNodesArray.Count() )
            {
            MIAUpdateNode* selectedNode = iSelectedNodesArray[ iNodeIndex ];

            // Only update items that have not been installed yet.
            if ( !selectedNode->IsInstalled() )
                {
                IAUPDATE_TRACE("[IAUPDATE] Item not installed yet");    
                if ( !selectedNode->IsDownloaded() )
                    {
                    // Because content has not been downloaded or installed yet,
                    // it needs to be downloaded before it can be installed.
                    IAUPDATE_TRACE("[IAUPDATE] Download");
                    selectedNode->DownloadL( *this );
                    iState = EDownloading;
                    iClosingAllowedByClient = ETrue;
                    ShowUpdatingDialogL( R_IAUPDATE_DOWNLOADING_NOTE,
                                         selectedNode->Base().Name(),
                                         iNodeIndex + 1,
                                         iSelectedNodesArray.Count() ); 
                    nextUpdate = EFalse;
                    }
                else
                    {
                    // Because content has been downloaded but not installed yet,
                    // it needs to be installed now.
                    IAUPDATE_TRACE("[IAUPDATE] Install");
                    selectedNode->InstallL( *this );
                    iState = EInstalling;
                    iClosingAllowedByClient = EFalse;
                    CIAUpdateAppUi* appUi = 
                        static_cast< CIAUpdateAppUi* >( iEikEnv->EikAppUi() );
                    appUi->StartWGListChangeMonitoring();
                    ShowUpdatingDialogL( R_IAUPDATE_INSTALLING_NOTE,
                                         selectedNode->Base().Name(),
                                         iNodeIndex + 1,
                                         iSelectedNodesArray.Count() ); 
                    nextUpdate = EFalse;                     
                    }      
                }
            }
        else
            {
            IAUPDATE_TRACE("[IAUPDATE] Update flow complete");
            nextUpdate = EFalse;
            UpdateCompleteL( KErrNone );	
            }
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ContinueUpdateL() end");
    }
   

// ---------------------------------------------------------------------------
// CIAUpdateUiController::StartInstallL
// Starts software installing
// ---------------------------------------------------------------------------
//    
void CIAUpdateUiController::StartInstallL( MIAUpdateNode& aNode )   
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartInstallL() begin");
   
    if ( aNode.Type() == MIAUpdateNode::EPackageTypeServicePack )
        {
        iServicePackNodes.Reset();
        aNode.GetDependenciesL( iServicePackNodes, ETrue );
        }
            
    aNode.InstallL( *this );
    iState = EInstalling;
    CIAUpdateAppUi* appUi = static_cast<CIAUpdateAppUi*>( iEikEnv->EikAppUi() );
    appUi->StartWGListChangeMonitoring();
    iClosingAllowedByClient = EFalse;
    ShowUpdatingDialogL( R_IAUPDATE_INSTALLING_NOTE,
                         aNode.Base().Name(),
                         iNodeIndex + 1,
                         iSelectedNodesArray.Count()  );
    
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartInstallL() end");
    }

    
// ---------------------------------------------------------------------------
// CIAUpdateUiController::StartRefreshL()
// Starts meta data refresh
// ---------------------------------------------------------------------------
// 
void CIAUpdateUiController::StartRefreshL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartRefreshL() begin");
    
    iCountOfAvailableUpdates = 0;
    iClosingAllowedByClient = ETrue;
    if ( iOffConfigurated  )
        {
        iObserver.RefreshCompleteL( ETrue, KErrNone );
        }
    else
        {
        iState = ERefreshing;    
        TBool allowNetworkRefresh = AllowNetworkRefreshL();
        iSelectedNodesArray.Reset();
        iController->StartRefreshL( allowNetworkRefresh );
            
        if ( iRequestType == IAUpdateUiDefines::ECheckUpdates && iFilter->FilterParams() )
            {
            if ( iFilter->FilterParams()->ShowProgress() )
                {
                // to avoid flickering IAD is brought to foreground only when wait dialog is really shown
                if ( allowNetworkRefresh )
                    {
                    iEikEnv->RootWin().SetOrdinalPosition( 0, ECoeWinPriorityNormal );
                    HBufC* noteText = StringLoader::LoadLC( R_IAUPDATE_REFRESHING_UPDATE_LIST );
                    ShowWaitDialogL( *noteText, ETrue );
                    CleanupStack::PopAndDestroy( noteText );
                    }
                }
            }
        else
            {
            HBufC* noteText = StringLoader::LoadLC( R_IAUPDATE_REFRESHING_UPDATE_LIST );
            ShowWaitDialogL( *noteText, EFalse );
            CleanupStack::PopAndDestroy( noteText );
            }
        }
    
       
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartRefreshL() end");
    }
 
   
// ---------------------------------------------------------------------------
// CIAUpdateUiController::Nodes
// 
// ---------------------------------------------------------------------------
//     
const RPointerArray< MIAUpdateNode >& CIAUpdateUiController::Nodes() const
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::Nodes()");
    return iNodes;
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::FwNodes
// 
// ---------------------------------------------------------------------------
//     
const RPointerArray<MIAUpdateFwNode>& CIAUpdateUiController::FwNodes() const
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::FwNodes()");
    return iFwNodes;
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::HistoryL
// 
// ---------------------------------------------------------------------------
//  
MIAUpdateHistory& CIAUpdateUiController::HistoryL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HistoryL()");
    return iController->HistoryL();
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::SetRequestType
// 
// ---------------------------------------------------------------------------
void CIAUpdateUiController::SetRequestType( 
    IAUpdateUiDefines::TIAUpdateUiRequestType aRequestType )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::SetRequestType() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] request type: %d", aRequestType );

    iRequestType = aRequestType;    
    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::SetRequestType() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::CancelOperation
// 
// ---------------------------------------------------------------------------    
void CIAUpdateUiController::CancelOperation() 
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CancelOperation() begin");

    // Set the flag to inform possible callback functions
    // that operation cancell is going on.
    iCancelling = ETrue;

    if ( iIdle )
        {
    	iIdle->Cancel();
        }
    if ( iStarter )
        {
    	iStarter->Cancel();
        }
    if ( iRoamingHandler )
        {
    	iRoamingHandler->CancelPreparing();
        }
    
	if ( iState == EDownloading || iState == EInstalling )
	    {
	    // Current node.
        MIAUpdateNode* node( iSelectedNodesArray[ iNodeIndex ] );

        // Cancel the operation of that node.
    	node->CancelOperation();

        // Also set the purchase history information to other nodes
        // even if their operations were not started yet.
        for ( TInt i = iNodeIndex + 1; i < iSelectedNodesArray.Count(); ++i )
            {
            node = iSelectedNodesArray[ i ];
            if ( MIAUpdateNode::EPackageTypeServicePack == node->Type()
                  && node->IsInstalled() )
                {
                IAUPDATE_TRACE("[IAUPDATE] Service pack was completed");
                // Even if cancel occurred, some of the nodes inside the
                // service pack were installed from some other dependency
                // chain way. And, now there is nothing to be installed
                // inside the service pack.
                TRAP_IGNORE ( node->Base().
                    SetInstallStatusToPurchaseHistoryL( KErrNone, ETrue ) );
                }
            else
                {
                IAUPDATE_TRACE("[IAUPDATE] Node cancelled");
                // Notice, that this can also still be service pack node.
                // Because we are handling nodes that are visible in UI,
                // we can force the node as visible in history.
                TRAP_IGNORE ( 
                    node->Base().SetIdleCancelToPurchaseHistoryL( ETrue ) ); 
                }
            }
	    }
    else if ( iState == ERefreshing )
        {
        iController->CancelRefresh();
        }

    // Just to be sure that self update related information
    // is always in resetted state when new update flows are
    // started after operation cancel.
	if ( iController )
	    {
	    iController->ResetSelfUpdate();
	    }
    // After cancellation, the new state is idle.
    iState = EIdle;
    iClosingAllowedByClient = ETrue;

    // Cancelling is over. So, set the flag accrodingly.
    iCancelling = EFalse;

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CancelOperation() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::ResultsInfo
// 
// ---------------------------------------------------------------------------    
TIAUpdateResultsInfo CIAUpdateUiController::ResultsInfo() const
	{
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ResultsInfo() begin");

	TIAUpdateResultsInfo resultsInfo( 0, 0, 0, iFileInUseError, EFalse );
	for ( TInt i = 0; i < iSelectedNodesArray.Count(); ++i )
	    {
	    MIAUpdateNode* node( iSelectedNodesArray[ i ] );
	    TInt lastErrorCode( KErrNone );
	    TRAPD ( trapError, 
	            lastErrorCode = node->Base().LastUpdateErrorCodeL() );
	    if ( node->IsInstalled() )
	        {
	        // Because node is installed, update must have been a success.
	        ++resultsInfo.iCountSuccessfull;
	        if ( node->Base().RebootAfterInstall() )
	            {
	            resultsInfo.iRebootAfterInstall = ETrue;
	            }
	        }
        else if ( trapError == KErrNone 
                  && lastErrorCode == KErrCancel )
            {
            ++resultsInfo.iCountCancelled;
            }
        else
            {
            ++resultsInfo.iCountFailed;
            }
	    }
	    
	IAUPDATE_TRACE_1("[IAUPDATE] Successfull count: %d", resultsInfo.iCountSuccessfull );
	IAUPDATE_TRACE_1("[IAUPDATE] Cancelled count: %d", resultsInfo.iCountCancelled );
	IAUPDATE_TRACE_1("[IAUPDATE] Failed count: %d", resultsInfo.iCountFailed );
	
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ResultsInfo() end");

	return resultsInfo;
	}


// ---------------------------------------------------------------------------
// CIAUpdateUiController::CountOfAvailableUpdates
// 
// ---------------------------------------------------------------------------    
TInt CIAUpdateUiController::CountOfAvailableUpdates() const
	{
	IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateUiController::CountOfAvailableUpdates() count: %d",
                     iCountOfAvailableUpdates );
	return iCountOfAvailableUpdates;
	}


// ---------------------------------------------------------------------------
// CIAUpdateUiController::Starter()
// 
// ---------------------------------------------------------------------------    
const CIAUpdateStarter* CIAUpdateUiController::Starter() const
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::Starter()");
    return iStarter;	
    }

// ---------------------------------------------------------------------------
// CIAUpdateUiController::Filter()
// 
// --------------------------------------------------------------------------- 
const CIAUpdateNodeFilter* CIAUpdateUiController::Filter() const
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::Filter()");
    return iFilter;	
    }

// -----------------------------------------------------------------------------
// CIAUpdateUiController::DoCancelIfAllowed
// 
// -----------------------------------------------------------------------------
//
TBool CIAUpdateUiController::DoCancelIfAllowed()
   {
   IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DoCancelIfAllowed() begin");

   if ( iClosingAllowedByClient )
       {
   	   CancelOperation();
       }

   IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DoCancelIfAllowed() end");

   return iClosingAllowedByClient;	
   }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::ClosingAllowedByClient
// 
// -----------------------------------------------------------------------------
//  
 TBool CIAUpdateUiController::ClosingAllowedByClient()
     {
     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ClosingAllowedByClient()");
     IAUPDATE_TRACE_1("[IAUPDATE] closing allowed: %d", iClosingAllowedByClient );
     TBool closingAllowed = iClosingAllowedByClient;
     if ( iRequestType != IAUpdateUiDefines::EShowUpdates )
         {
         // iaupdate can be orphaned from its client only when ShowUpdates() was called  
         closingAllowed = ETrue;
         }
 	 return closingAllowed;
     }
 	

// -----------------------------------------------------------------------------
// CIAUpdateUiController::CheckUpdatesDeferredL
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::CheckUpdatesDeferredL( CIAUpdateParameters* aParams, 
                                                   TBool aRefreshFromNetworkDenied )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CheckUpdatesDeferredL() begin");
    
    iClosingAllowedByClient = ETrue;
    delete iParams;
    iParams = aParams; //ownership of parameters is taken
    iRefreshFromNetworkDenied = aRefreshFromNetworkDenied; 
    delete iIdle;
    iIdle = NULL;
	iIdle = CIdle::NewL( CActive::EPriorityIdle ); 
    iIdle->Start( TCallBack( CheckUpdatesDeferredCallbackL, this ) );

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CheckUpdatesDeferredL() end");
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::PrepareRoamingHandlerL
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::PrepareRoamingHandlerL()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::PrepareRoamingHandlerL() begin");
	    
    if ( !iRoamingHandler )
        {
    	iRoamingHandler = CIAUpdateRoamingHandler::NewL();
        }
    if ( !iRoamingHandler->Prepared() )
        {
    	iRoamingHandler->CancelPreparing();
    	//async call that will return in RoamingHandlerPrepared()
    	iRoamingHandler->PrepareL( *this );
        }
    else
        {
        CheckUpdatesL();	
        }
    
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::PrepareRoamingHandlerL() end");
    }



// -----------------------------------------------------------------------------
// CIAUpdateUiController::HandlePossibleSelfUpdateRestartL
// 
// -----------------------------------------------------------------------------
//
TBool CIAUpdateUiController::HandlePossibleSelfUpdateRestartL( TBool aShutdownRequest )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandlePossibleSelfUpdateRestartL() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] ShutdownRequest: %d", aShutdownRequest );

    TBool restarted( EFalse );

    CIAUpdateRestartInfo* info( iController->SelfUpdateRestartInfo() );

    if ( info )
        {
        IAUPDATE_TRACE("[IAUPDATE] Self updater related info available.");

        CleanupStack::PushL( info );

        // Delete the unnecessary files because we will still have 
        // required objects available.
        // Notice, that if for some reason a leave occurs after this and the
        // application does not continue the update, then next time the application
        // is started, update restart is not rehandled any more.
        info->DeleteFiles();

        // Get the data for the updater results.            
        CIAUpdaterResultsFile& results( info->ResultsFile() );

        // This flag is set if self updater operation was cancelled.
        TBool selfUpdateCancelled( EFalse );

        // Because we have restarted the iaupdate after self updating,
        // also start to gather possible new update flow reports into 
        // a report bundle. Inform the controller, so the controller 
        // can handle situations as a whole and not as one item at the
        // time.
        iController->StartingUpdatesL();

        RPointerArray< CIAUpdaterResult >& resultArray( results.Results() );
        // Because self updater will insert the possible hidden dependencies
        // before the actual item, start from the beginning of the array to
        // set the error codes. This way, the main item will be set last and
        // it will get the latest time for the purchase history.
        for ( TInt i = 0; i < resultArray.Count(); ++i )
            {
            CIAUpdaterResult* result( resultArray[ i ] );
            
            if ( result->ErrorCode() == KErrCancel )
                {
                IAUPDATE_TRACE("[IAUPDATE] Self Updater cancelled"); 
            	selfUpdateCancelled = ETrue;
                }

            // Because, the self update installation was finished.
            // Update the purchase history with the correct information.
            // Notice, that we can just set the purchase history here for
            // the self updater items. If some of the items were installed,
            // before self updater items, then their information was already
            // correctly into the history. Notice, that result nodes may be hidden
            // nodes that were not initially visible in the UI. So, do not
            // force the results visible in purchase history.
            MIAUpdateNode& node( iController->NodeL( result->Identifier() ) );
            node.Base().
                SetInstallStatusToPurchaseHistoryL( 
                    result->ErrorCode(), EFalse );
            }

        IAUPDATE_TRACE("[IAUPDATE] Self update info inserted to purchase history."); 

           
        // Get the data for the pending node info.
        CIAUpdatePendingNodesFile& pendings(
            info->PendingNodesFile() );


        // Because ContinueUpdateL will use the counters and
        // node index and iSelectedNodesArray, we set the correponding information
        // here. Then, the update operation will continue correctly for the pending
        // nodes.
            

        // Set the node index to -1 because ContinueUpdateL increases it by one
        // in the beginning of the function. So, we can use the ContinueUpdateL
        // also in the end of this function to start the actual update process.
        iNodeIndex = -1;
        iSelectedNodesArray.Reset();
        
        // Also, reset nodearray nodes as not selected because original parameter
        // settings may have been overruled by the user before user started 
        // the self update from UI. Correct nodes will be chosen in the for-loops below.
        for ( TInt i = 0; i < iNodes.Count(); ++i )
            {
            MIAUpdateNode& node( *iNodes[ i ] );
            node.Base().SetSelected( EFalse );
            }
        for ( TInt i = 0; i < iFwNodes.Count(); ++i )
            {
            MIAUpdateFwNode& fwNode( *iFwNodes[ i ] );  
            fwNode.Base().SetSelected( EFalse );
            }
        

        if ( !selfUpdateCancelled )
            {
            IAUPDATE_TRACE("[IAUPDATE] Self update not cancelled.");

            // Notice, that the ownership of the filter parameters will
            // remain in the filter.
            CIAUpdateParameters* params( iFilter->FilterParams() );
            if ( !IsStartedByLauncher() || params )
                {
                IAUPDATE_TRACE("[IAUPDATE] Self update handling will set parameters.");

                // Check if IAD was started from the grid or through API.
                // If IAD was started like from the grid but it still has parameters set,
                // then act as it was started through API. Most likely, then the IAD was
                // originally started through API but because of self update IAD was restarted
                // and now it has original parameters set.

                if ( !iStarter )
                    {
                    IAUPDATE_TRACE("[IAUPDATE] iStarter not set");
            	    iStarter = CIAUpdateStarter::NewL( params->CommandLineExecutable(), 
            	                                       params->CommandLineArguments() );
                    }
                }
            }

        // Get list of nodes that were initially chosen for the flow.
        RPointerArray< CIAUpdaterIdentifier >& pendingIdentifiers = 
            pendings.PendingNodes();
        TInt pendingIdentifiersCount( pendingIdentifiers.Count() );
        // Get the index to the node that has not yet been handled.
        TInt pendingsIndex( pendings.Index() );
        iSelectedNodesArray.ReserveL( pendingIdentifiersCount );
        for ( TInt i = 0; i < pendingIdentifiersCount; ++i )
            {
            CIAUpdaterIdentifier* identifier( pendingIdentifiers[ i ] );
            MIAUpdateNode& node( 
                iController->NodeL( *identifier ) );
            iSelectedNodesArray.AppendL( &node );

            // Also, set the node as selected because then UI can easily check
            // which nodes should be marked when the UI is restarted after selfupdate.
            node.Base().SetSelected( ETrue );

            if ( i < pendingsIndex )
                {
                // We come here if index suggests that node has already been handled

                // Increase the node index. So, it will already point
                // to the correct place. Because, we want to omit these files
                // when list is gone through.
                ++iNodeIndex;

            	if ( iStarter && node.IsInstalled() )
            	    {
                    IAUPDATE_TRACE("[IAUPDATE] Self update handling will set parameters, node installed");
                    // Because application starting parameters may have been given through the
                    // API, we need to pass UID of installed package to starter if it exists.
                    // Then, the starter will start the given exe in the end of the install flow
                    // if at least one file was succesfully installed.
            		iStarter->CheckInstalledPackageL( node.Base().Uid() );
            	    }
                }
            else if ( selfUpdateCancelled )
                {
                IAUPDATE_TRACE("[IAUPDATE] Set idle cancel info to purchase history");
                // Check if self updater actions were cancelled.
                // Set the purchase history information to nodes not handled yet.
                // If visible service pack was changed to hidden during the operation
                // then force the current history info visible. Then the history
                // corresponds the situation that was when operation flow was started.
                // This may occure if some of the items were installed after all.
                // Notice, that here we can think that node was initially visible
                // because all nodes in UI selection list are visible and possible
                // hidden self update nodes have been handled already in the beginning
                // of this for loop.
                if ( MIAUpdateNode::EPackageTypeServicePack == node.Type()
                      && node.IsInstalled() )
                    {
                    IAUPDATE_TRACE("[IAUPDATE] Service pack was completed");
                    // Even if cancel occurred, some of the nodes inside the
                    // service pack were installed. And, now there is nothing
                    // to be installed inside the service pack.
                    node.Base().
                        SetInstallStatusToPurchaseHistoryL( KErrNone, ETrue );
                    }
                else
                    {
                    IAUPDATE_TRACE("[IAUPDATE] Node cancelled");
                    // Notice, that this can also still be service pack node.
                    // Because we are handling nodes that are visible in UI,
                    // we can force the node as visible in history.
                    node.Base().SetIdleCancelToPurchaseHistoryL( ETrue ); 
                    }
                }
            else if ( MIAUpdateNode::EPackageTypeServicePack == node.Type()
                      && node.IsInstalled() )
                {
                IAUPDATE_TRACE("[IAUPDATE] Service pack has become installed");
                // Because service pack has become installed during self update
                // it means that the service pack was originally missing only
                // the selfupdate. Set, the service pack as installed also into
                // purchase history because no other operation will be done to
                // it after this. Notice, that because service pack was originally
                // in the list, it has been visible for UI. So, make sure that it
                // is also visible in history. IAD Engine will set service packs
                // whose all content is installed as hidden. Therefore, force the
                // visibility here.
                // Notice, that here we can think that node was initially visible
                // because all nodes in UI selection list are visible and possible
                // hidden self update nodes have been handled already in the beginning
                // of this for loop.
                node.Base().
                    SetInstallStatusToPurchaseHistoryL( KErrNone, ETrue );
                }
            }

        // Info is not needed any more. 
        // So, delete it before update flow will be continued below 
        // if necessary.
        CleanupStack::PopAndDestroy( info );

        // Check if self updater actions was closed by using red key.
        // If so, then do not continue update flow here. 
        // Instead, this application should be closed.
        if ( !aShutdownRequest )
            {
            IAUPDATE_TRACE("[IAUPDATE] Self update not closed with red key.");            
            if ( selfUpdateCancelled )
                {
                IAUPDATE_TRACE("[IAUPDATE] Self update cancelled.");
                // Because self update is cancelled, do not continue here either.
                // Instead end the update flow directly.
                UpdateCompleteL( KErrCancel );
                }
            else
                {
                IAUPDATE_TRACE("[IAUPDATE] Self update finished, continue udpate.");
                // Continue udpate normally.
                ContinueUpdateL( ETrue );                
                }
            }
        else
            {
            IAUPDATE_TRACE("[IAUPDATE] Self update closed with red key. Handle dialogs.");
            // Because shutdown was requested, we do not continue the update flow.
            // A updating dialog may still show. So, release it here.
            RemoveUpdatingDialogsL();
            }

        // Self updater provided some data that was handeld above.
        restarted = ETrue;
        }

    IAUPDATE_TRACE_1("[IAUPDATE] restarted: %d", restarted );   
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandlePossibleSelfUpdateRestartL() end");

    return restarted;
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::TestRole
// 
// -----------------------------------------------------------------------------
//
TBool CIAUpdateUiController::TestRole() const 
    {
    return iTestRole;	
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::RefreshComplete
// 
// -----------------------------------------------------------------------------
//                            
void CIAUpdateUiController::RefreshComplete( 
    const RPointerArray< MIAUpdateAnyNode >& aNodes,
    TInt aError )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RefreshComplete() begin");
    TInt completionError = KErrNone;
    if ( iState == EUiRefreshing )
        {
    	iState = EIdle;
    	TRAP( completionError, RefreshUiCompleteL( aNodes, aError ) );
        }
    else
        {
        iState = EIdle;
        TRAP ( completionError, RemoveWaitDialogL() );
        if ( completionError == KErrNone )
            {
    	    TRAP( completionError, RefreshCompleteL( aNodes, aError ) );
            }	
        }
    if ( completionError == KErrNone )
        {
        iRefreshed = ETrue;
        }
    else
        {
        iObserver.HandleLeaveErrorWithoutLeave( completionError );
        }
    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RefreshComplete() end");
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::SelfUpdaterComplete
// 
// -----------------------------------------------------------------------------
//                            
void CIAUpdateUiController::SelfUpdaterComplete( TInt aErrorCode )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::SelfUpdaterComplete() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] error code: %d", aErrorCode );

    // Self updater completed its job.
    // Normally we should not come here because self update should shut down this
    // application before installation. But, now because we came here, complete
    // the update operation.

    // Remove params file if it exists. This is a temporary file that would be
    // otherwise read during next grid start if not removed here. There is no need
    // to use that file now, because all the necessary parameters are already set
    // because restart of IAD did not occur.
    
    iState = EIdle;
    TRAP_IGNORE ( ParamsRemoveFileL() );

    TInt err( KErrNone );
    TBool restartDataWasAvailable( EFalse );
    TRAP ( err, 
           restartDataWasAvailable = 
            HandlePossibleSelfUpdateRestartL( 
                aErrorCode == IAUpdaterDefs::KIAUpdaterShutdownRequest ) );
    if ( err != KErrNone )
        {
    	iObserver.HandleLeaveErrorWithoutLeave( err );
        }
    else if ( !restartDataWasAvailable )
        {
        IAUPDATE_TRACE("[IAUPDATE] Restart data not available");
        // For some reason the self updater was not able to give the restart data.
        // So, try to continue the update in a normal way.
        TRAP ( err, UpdateFailedSelfUpdaterInfoToPurchaseHistoryL( aErrorCode ) );
        if ( err == KErrNone )
            {
            IAUPDATE_TRACE("[IAUPDATE] Continue update flow");
        	TRAP ( err, ContinueUpdateL( EFalse ) );
            }
        if ( err != KErrNone )
            {
            IAUPDATE_TRACE_1("[IAUPDATE] Purchase history update error: %d", err);
        	iObserver.HandleLeaveErrorWithoutLeave( err );
            }
        }

    if ( aErrorCode == IAUpdaterDefs::KIAUpdaterShutdownRequest )
        {
        CIAUpdateAppUi* appUi = static_cast<CIAUpdateAppUi*>( iEikEnv->EikAppUi() );
    	appUi->Exit();
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::SelfUpdaterComplete() end");
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::ServerReportSent
// 
// -----------------------------------------------------------------------------
//                            
void CIAUpdateUiController::ServerReportSent( TInt aError )
    {
    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateUiController::ServerReportSent() begin: %d",
                     aError);

    // This call back is called when MIAUpdateController::UpdateFinishedL
    // function is called and that asynchronous operation completes.
    // Report sending is done in the background.
    if ( iState == ESendingReport )
        {
        IAUPDATE_TRACE("[IAUPDATE] End the update flow now that report has been sent");
        // Reports are sent only when update flow has finished. Also, in normal 
        // flow, we wait that report sending finishes before continuing to the end. 
        TRAP_IGNORE( EndUpdateFlowL( aError ) ); 
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ServerReportSent() end");
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::ClientRole
// 
// -----------------------------------------------------------------------------
//     
void CIAUpdateUiController::ClientRole( const TDesC& aClientRole )
    {
	if ( aClientRole == IAUpdateUiDefines::KTestRole() )
	    {
	    iTestRole = ETrue;
	    }
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::DownloadProgress
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::DownloadProgress( MIAUpdateNode& /*aNode*/, 
                                              TUint aProgress,
                                              TUint aMaxProgress )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DownloadProgress() begin");  

    if ( iProgressDialog )
        {
    	TRAP_IGNORE ( iProgressDialog->SetProgressDialogFinalValueL( aMaxProgress ) );
        TRAP_IGNORE ( iProgressDialog->UpdateProgressDialogValueL( aProgress ) );
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DownloadProgress() end");  
    }                            


// -----------------------------------------------------------------------------
// CIAUpdateUiController::DownloadComplete
// 
// -----------------------------------------------------------------------------
//                            
void CIAUpdateUiController::DownloadComplete( MIAUpdateNode& aNode,
                                              TInt aError )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DownloadComplete() begin");

    iState = EIdle;
	TRAPD ( completionError, DownloadCompleteL( aNode, aError ) );
    if ( completionError != KErrNone )
        {
        // If we came here, DownloadCompleteL function may have left
        // before dialog was removed. So, try one more time to remove it here
        // before informing the observer.
        TRAP_IGNORE( RemoveUpdatingDialogsL() );
        iObserver.HandleLeaveErrorWithoutLeave( completionError );
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DownloadComplete() end");
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::InstallProgress
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::InstallProgress( MIAUpdateNode& /*aNode*/, 
                                             TUint /*aProgress*/,
                                             TUint /*aMaxProgress*/ )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallProgress()");    
    }                            


// -----------------------------------------------------------------------------
// CIAUpdateUiController::InstallComplete
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::InstallComplete( MIAUpdateNode& aNode,
                                             TInt aError )  
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallComplete() begin");

    iState = EIdle;
    CIAUpdateAppUi* appUi = static_cast<CIAUpdateAppUi*>( iEikEnv->EikAppUi() );
    appUi->StopWGListChangeMonitoring();
    if ( aError == SwiUI::KSWInstErrFileInUse )
        {
    	iFileInUseError = ETrue;
        }
    
	TRAPD ( completionError, InstallCompleteL( aNode, aError ) );
    if ( completionError != KErrNone )
        {
        // If we came here, InstallCompleteL function may have left
        // before dialog was removed. So, try one more time to remove it here
        // before informing the observer.
        TRAP_IGNORE( RemoveUpdatingDialogsL() );
        iObserver.HandleLeaveErrorWithoutLeave( completionError );
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallComplete() end");
    }

    
// ---------------------------------------------------------------------------
// CIAUpdateUiController::StartupComplete
// 
// ---------------------------------------------------------------------------
// 
void CIAUpdateUiController::StartupComplete( TInt aError )
    {  
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartupComplete() begin");  

    if ( aError == IAUpdateErrorCodes::KErrCacheCleared )
        {
        IAUPDATE_TRACE("[IAUPDATE] Cache cleared during startup.");  
        // Because cache was cleared, change the refresh information data
        // so that the network refresh will be done during refresh operation.
        
        // The values have been read from the file when the controller file 
        // object was created or the defaul values are used if the file did
        // not exist. So, no need to re-read them here.
        // Replace the time with zero. So, the zero time will
        // suggest that network refresh is required later on. 
        iControllerFile->SetRefreshTime( 0 );

        // Save data into the file.
        // Change aError value to correct one. 
        // aError will be KErrNone if everything goes ok inside trap,
        // or else it will contain the correct error code.
        TRAP ( aError, iControllerFile->WriteControllerDataL(); );
        
        CIAUpdateRestartInfo* info( iController->SelfUpdateRestartInfo() ); 
        if ( info ) 
            { 
            IAUPDATE_TRACE("[IAUPDATE] Delete restart info because of cache clean.");
            // Restart info was available. 
            // Delete self upate files because otherwise a net connection
            // may be prevented during refresh and the cleared cache can not
            // be updated. If this is not done here, HandlePossibleSelfUpdateRestartL
            // may leave because required nodes are not found. Notice, that also
            // HandlePossibleSelfUpdateRestartL deletes these files but by handling
            // this special case here, an application can continue without leave later.
            info->DeleteFiles();
            delete info; 
            info = NULL; 
            }
        }
        
    iObserver.StartupComplete( aError );
    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartupComplete() end");  
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::StartExecutableCompletedL
// 
// ---------------------------------------------------------------------------
// 
void CIAUpdateUiController::StartExecutableCompletedL( TInt /*aError*/ )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartExecutableCompletedL() begin"); 

    // Before informing the observer, close the possible existing dialog.
    RemoveUpdatingDialogsL();
    
    // Possible error is not passed to a client. Typically client is already closed. 
    // Even in the case when client's request is still ongoing, it's disinformation to return
    // error from failed executable start. 
    TRAPD ( err, iObserver.UpdateCompleteL( KErrNone ) );
    if ( err != KErrNone )
        {
    	iObserver.HandleLeaveErrorL( err );
        }

	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartExecutableCompletedL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RoamingHandlerPrepared
// 
// ---------------------------------------------------------------------------
// 
void CIAUpdateUiController::RoamingHandlerPrepared()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RoamingHandlerPrepared() begin");
    TRAPD ( err, CheckUpdatesL() );
	if ( err != KErrNone )
        {
    	iObserver.HandleLeaveErrorWithoutLeave( err );
        }
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RoamingHandlerPrepared() end");
    }


// -----------------------------------------------------------------------------
// CIAUpdateUiController::HandleDialogExitL
// Called when wait/progress dialog is about to be cancelled.
// (other items were commented in a header).
// -----------------------------------------------------------------------------
//
TBool CIAUpdateUiController::HandleDialogExitL( TInt aButtonId )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandleDialogExitL() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] button id: %d", aButtonId );
    
    TInt ret( ETrue );
    if ( aButtonId == EAknSoftkeyCancel )
        {  
        TRAPD ( err, HandleUserCancelL() );
        if ( err != KErrNone )
            {
        	iObserver.HandleLeaveErrorL( err );
            }
        }   

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandleDialogExitL() end");

    return ret;    
    }

// -----------------------------------------------------------------------------
// CIAUpdateUiController::HandleUiRefreshL
// 
// -----------------------------------------------------------------------------
//
void CIAUpdateUiController::HandleUiRefreshL()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandleUiRefreshL() begin"); 

	if ( iRequestType == IAUpdateUiDefines::ECheckUpdates )
	    {
	    iRefreshed = EFalse;
	    }
	else if ( iState == EIdle )
	    {
	    CIAUpdateAppUi* appUi = static_cast< CIAUpdateAppUi* >( iEikEnv->EikAppUi() );
        if ( appUi->UiRefreshAllowed() )
		    {
	    	iState = EUiRefreshing;
	        // store node identification (package UID and version) of currently selected nodes
	        // to restore selections after refresh
	        delete iPreviousSelections;
	        iPreviousSelections = NULL;
	        iPreviousSelections = new( ELeave ) CArrayFixFlat<SIAUpdateNodeId>( iNodes.Count() + 1 );
	        for ( TInt i = 0; i < iNodes.Count(); ++i )
                {
                MIAUpdateNode* node( iNodes[ i ] );
                SIAUpdateNodeId nodeId;
                nodeId.iNodeType = MIAUpdateAnyNode::ENodeTypeNormal;
                nodeId.iPackageUid = node->Base().Uid();
                nodeId.iVersion = node->Base().Version();
                nodeId.iSelected = node->Base().IsSelected();
                iPreviousSelections->AppendL( nodeId );
                }

            if ( iFwNodes.Count() > 0 )
                {   
                MIAUpdateFwNode* fwNode( iFwNodes[ 0 ] );
                SIAUpdateNodeId nodeId;
                nodeId.iNodeType = MIAUpdateAnyNode::ENodeTypeFw;
                nodeId.iSelected = fwNode->Base().IsSelected();
                iPreviousSelections->AppendL( nodeId );
                }
        
   	        iController->StartRefreshL( EFalse );
	        }
	    }
	
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandleUiRefreshL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RefreshCompleteL
// 
// ---------------------------------------------------------------------------
//        
void CIAUpdateUiController::RefreshCompleteL( 
    const RPointerArray< MIAUpdateAnyNode >& aNodes,
    TInt aError )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RefreshCompleteL() begin");

    iState = EIdle;
    if ( !iRefreshHandler  && !iOffConfigurated )
        {
        iRefreshHandler = CIAUpdateRefreshHandler::NewL();
        }
    if ( aError == KErrNone ) 
        {
        // Inform refresh to other IAD instances 
        if ( !iOffConfigurated  && AllowNetworkRefreshL() && iRefreshHandler )
            {
            iRefreshHandler->InformRefreshL();   
            }
                  
        // Because refresh was successfully completed,
        // update the controller information to the controller file
        UpdateControllerFileL();
        }

    // Even in a case when refresh failed, there may be old cache available.
    // It's also possible that only firmware node or normal node refresh failed, so there is 
    // partial list available
    // ==> all nodes returned by engine are shown in UI
    iNodes.Reset();
    iFwNodes.Reset();
    iNodes.ReserveL( aNodes.Count() );
    for ( TInt i = 0; i < aNodes.Count(); ++i )
        {
        MIAUpdateAnyNode* anyNode( aNodes[ i ] );
        if ( anyNode->NodeType() == MIAUpdateAnyNode::ENodeTypeNormal )
            {
            MIAUpdateNode* node( 
                static_cast< MIAUpdateNode* >( anyNode ) );
            iNodes.AppendL( node );                
            }
        else if ( anyNode->NodeType() == MIAUpdateAnyNode::ENodeTypeFw )
            {
            MIAUpdateFwNode* fwNode( 
                static_cast< MIAUpdateFwNode* >( anyNode ) );
            iFwNodes.AppendL( fwNode );
            }
        }

    switch ( iRequestType )
        {
        case IAUpdateUiDefines::ECheckUpdates:
        	
            if ( iFilter->FilterParams() )
                {
           		iFilter->CountOfAvailableUpdatesL( 
               		                         iNodes, 
               		                         iFwNodes,
               		                         iCountOfAvailableUpdates ); 
                }
            break;
        
        default: 
            // Sort the nodes according to the filter values
            // This function performs default marking also
            iFilter->FilterAndSortNodesL( iNodes, iFwNodes );
                                          
            break;
        }

    if ( aError == KErrNone )
        {
        // Now, that refresh has been done, 
        // check if there is some self update related settings .
        HandlePossibleSelfUpdateRestartL( EFalse );
        }
    
    if ( !iOffConfigurated  && iRefreshHandler )
        {
        iRefreshHandler->StartListeningL( this );
        }
    iObserver.RefreshCompleteL( ETrue, aError );        
        
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RefreshCompleteL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RefreshUiCompleteL
// 
// ---------------------------------------------------------------------------
//        
void CIAUpdateUiController::RefreshUiCompleteL( 
    const RPointerArray< MIAUpdateAnyNode >& aNodes,
    TInt /*aError*/ )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RefreshUiCompleteL() begin");
    // : Is error handling needed?
    iNodes.Reset();
    iFwNodes.Reset();
    iNodes.ReserveL( aNodes.Count() );
    // Find out if there was umarked firmware update in old selections,
    // that case needs special handling
    TBool unmarkedFw = EFalse;
    for ( TInt i = 0; i < iPreviousSelections->Count(); ++i )
        {
        SIAUpdateNodeId prevNodeId = iPreviousSelections->At( i );
        if ( prevNodeId.iNodeType == MIAUpdateAnyNode::ENodeTypeFw  && !prevNodeId.iSelected )
             {
             unmarkedFw = ETrue;
             }
        }
     
    for ( TInt i = 0; i < aNodes.Count(); ++i )
        {
        MIAUpdateAnyNode* anyNode( aNodes[ i ] );
        if ( anyNode->NodeType() == MIAUpdateAnyNode::ENodeTypeNormal )
            {
            MIAUpdateNode* node( static_cast< MIAUpdateNode* >( anyNode ) );
            iNodes.AppendL( node );                
            }
        else if ( anyNode->NodeType() == MIAUpdateAnyNode::ENodeTypeFw && !unmarkedFw )
            {
            // if umarked firmware update in old selections, firmawares are not appended 
            // before iFilter->FilterAndSortNodesL() is called
            MIAUpdateFwNode* fwNode( 
                    static_cast< MIAUpdateFwNode* >( anyNode ) );
            iFwNodes.AppendL( fwNode );
            }
        }
    iFilter->FilterAndSortNodesL( iNodes, iFwNodes );
    
    if ( unmarkedFw )
        {
        for ( TInt i = 0; i < aNodes.Count(); ++i )
            {
            MIAUpdateAnyNode* anyNode( aNodes[ i ] );
            if ( anyNode->NodeType() == MIAUpdateAnyNode::ENodeTypeFw )
                {
                MIAUpdateFwNode* fwNode( 
                        static_cast< MIAUpdateFwNode* >( anyNode ) );
                iFwNodes.AppendL( fwNode );
                }
            }
        }
    
    //restore previous selections/deselections  
    for ( TInt i = 0; i < iNodes.Count(); ++i )
        {
        MIAUpdateNode* node( iNodes[ i ] );
        for ( TInt j = 0; j < iPreviousSelections->Count(); ++j )
            {
            SIAUpdateNodeId prevNodeId = iPreviousSelections->At(j);
        	if ( node->Base().Uid() == prevNodeId.iPackageUid &&
        	     node->Base().Version() == prevNodeId.iVersion )
                {
        		node->Base().SetSelected( prevNodeId.iSelected );
        	    }
            }
        }
    
    // When dependant is marked, all dependencies to be marked also
    for ( TInt i = 0; i < iNodes.Count(); ++i )
        {
        MIAUpdateNode* node( iNodes[ i ] );
        if ( node->Base().IsSelected() )
            {
            iFilter->SetDependenciesSelectedL( *node, iNodes );
            }
        }
    
    TBool firmwareSelected = EFalse;
    for ( TInt i = 0; i < iFwNodes.Count(); ++i )
        {
        MIAUpdateFwNode* fwNode( iFwNodes[ i ] );
    	for ( TInt j = 0; j < iPreviousSelections->Count(); ++j )
    	    {
    	    SIAUpdateNodeId prevNodeId = iPreviousSelections->At(j);
    		if ( prevNodeId.iNodeType == MIAUpdateAnyNode::ENodeTypeFw )
    		    {
    			fwNode->Base().SetSelected( prevNodeId.iSelected );
    		    }
    	    }
    	if ( fwNode->Base().IsSelected() )
    	    {
    	    firmwareSelected = ETrue;
    	    }
        }
    
    // if firmware is marked, normal nodes to be unmarked
    if ( firmwareSelected )
        {
        for ( TInt i = 0; i < iNodes.Count(); ++i )
            {
            MIAUpdateNode* node( iNodes[ i ] );
            node->Base().SetSelected( EFalse );
            }
        }
    
    CreateSelectedNodesArrayL();
    iObserver.RefreshCompleteL( EFalse, KErrNone );
     
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RefreshUiCompleteL() end"); 
    }
    
    
    
// ---------------------------------------------------------------------------
// CIAUpdateUiController::DownloadCompleteL
// 
// ---------------------------------------------------------------------------
//            
void CIAUpdateUiController::DownloadCompleteL( MIAUpdateNode& aNode, TInt aError )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DownloadCompleteL() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] error code: %d", aError );

    if ( aError == KErrAbort )
        {
        // Abort is interpreted so that a connection was not allowed by the user.
        // So, do not continue to a new operation. 
        // Instead, complete the update flow now.
        // Set the purchase history information to nodes.
        // Because the current node has KErrAbort as the last operation error code,
        // change it to KErrCancel because we want to think it as cancellation instead
        // of as abort error. This way, error counters and history info will show cancel
        // instead of failed. Also, update cancel info to other pending nodes.
        for ( TInt i = iNodeIndex; i < iSelectedNodesArray.Count(); ++i )
            {
            MIAUpdateNode* node( iSelectedNodesArray[ i ] );
            // Because we are handling nodes that are visible in UI,
            // we can force the node as visible in history.
            TRAP_IGNORE ( 
                node->Base().SetIdleCancelToPurchaseHistoryL( ETrue ) );
            }
        UpdateCompleteL( KErrNone );        
        }
    else if ( aError != KErrNone )
        {
    	InstallCompleteL( aNode, aError );
        }
    else   
        {
	    StartInstallL( aNode );
        }    
 
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::DownloadCompleteL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::InstallCompleteL
// 
// ---------------------------------------------------------------------------
//      
void CIAUpdateUiController::InstallCompleteL( MIAUpdateNode& aNode, 
                                              TInt aError )    
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallCompleteL() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] error code: %d", aError );

    // In release mode, we do not need the aError info, because
    // success counters are counted by using the last operation error info
    // when counter info is asked. In debug mode the error code is logged above.
    (void)aError;
    
    // pass UID of installed package to starter
    if ( iStarter )
        {
    	if ( aNode.Type() == MIAUpdateNode::EPackageTypeServicePack )
    	    { 
    	    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallCompleteL() node type is service pack");
     	    for ( TInt i = 0; i < iServicePackNodes.Count(); ++i )
    	        {
    	        if ( iServicePackNodes[i]->IsInstalled() )   
    	            {
    	            IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallCompleteL() node is installed");
    	            iStarter->CheckInstalledPackageL( iServicePackNodes[i]->Base().Uid() );
    	            }
    	        }
    	    iServicePackNodes.Reset();
    	    }
    	else if ( aNode.IsInstalled() )
    	    {
    	    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallCompleteL() node is installed");
    	    iStarter->CheckInstalledPackageL( aNode.Base().Uid() );
    	    }
        }
    
    // If installation was marked as KErrCancel here,
    // we think that it was just the disclaimer and
    // let this continue.        
    ContinueUpdateL( EFalse );

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::InstallCompleteL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::UpdateCompleteL
// 
// ---------------------------------------------------------------------------
//      
void CIAUpdateUiController::UpdateCompleteL( TInt aError ) 
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::UpdateCompleteL() begin");

    iState = EIdle;
    iClosingAllowedByClient = EFalse;

    // Remove installed nodes from the node array.
	for ( TInt i = iNodes.Count() - 1; i >= 0; --i ) 
        {   
        MIAUpdateNode* node = iNodes[ i ];
        if ( node->IsInstalled() ) 
            {
            iNodes.Remove( i );
            }
        }
    
    TInt error( aError );
    TBool selfUpdaterStarted( EFalse );

    if ( error == KErrNone )
        {
        IAUPDATE_TRACE("[IAUPDATE] Check self update start");
        // Set the error to correspond to the trap error. So, 
        // the observer will get correct information about the end result
        // of the update.
        TRAP ( error, 
               selfUpdaterStarted = StartPossibleSelfUpdateL() );
        if ( error != KErrNone )
            {
            IAUPDATE_TRACE_1("[IAUPDATE] trap error: %d", error);
            // Because self update could not be started the counters may not be
            // correct. Also, update purchase history with the error value 
            // because install operation failed here.
            UpdateFailedSelfUpdaterInfoToPurchaseHistoryL( error ); 
            }
        }                   

    // Check if self updater was started.
    // If it was not, then there most likely was not any self updates set,
    // or something went wrong when self updater was tried to be started.
    if ( selfUpdaterStarted )
        {
        iState = ESelfUpdating;
        }
    else
        {
        IAUPDATE_TRACE("[IAUPDATE] SelfUpdater was not started");

        // Notice, that if the self updater was started, then
        // do not inform the UI here that the operation was completed.
        // Also, do not start possible executable yet.
        // Instead, let the self updater do its thing in the background.
        // Most likely, the updater will close this application during installation.
        // But, if it does not, it will result to the SelfUpdaterComplete function
        // call, and we can continue the installation from there.

        // Inform the controller that we finished the updates. This way the
        // controller can handle situations as a whole and not as one item at the
        // time. Notice, that this will start the asynchronous operation that sends
        // possible reports to the server. Callback is called when operation is finished.
        // Also notice, that this reporting operation is not part of the normal update
        // flow but a separate action meant  after update flow finishes. 
        // The destructor of the engine controller can handle the cancellation of 
        // the reporting operation. Also, no callbacks are called back to UI when 
        // cancellation occurs. Notice, that if close request for application is issued
        // before reports are sent, then objects are delete immediately and we will not 
        // wait report sending to finish but reports are sent next time the application 
        // is started.
        // Maximum wait time for server reports is given in micro seconds.
        // Notice, that in case of cancellations there would not be any need
        // for timer. But just use it as in normal cases. Then, server report
        // completion or timer will call the callback later. But, that callback
        // will be ignored in CIAUpdateUiController::ServerReportSent because
        // iState is already then changed from ESendingReport to something else. 
        const TInt KServerReportMaxWaitTime( 10000000 );
        iController->FinishedUpdatesL( ETrue, KServerReportMaxWaitTime );
        iState = ESendingReport;
        }

    // When reports are sent, EndUpdateFlowL is called via the callback functions
    // and the update flow will be finished there. But, if we come here when cancel
    // is pressed, then call EndUpdateFlowL directly because then we do not wait
    // report sending to finish. This will also set the state to EIdle to inform
    // that when cancelling, we do not wait for the report sending to complete.
    if ( aError == KErrCancel )
        {
        IAUPDATE_TRACE("[IAUPDATE] Cancelling. Call EndUpdateFlowL directly");
        EndUpdateFlowL( error );
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::UpdateCompleteL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::EndUpdateFlowL
// 
// ---------------------------------------------------------------------------
//  
void CIAUpdateUiController::EndUpdateFlowL( TInt aError )    
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::EndUpdateFlowL() begin");

    // Because we are ending the flow, set the state to idle.
    iState = EIdle;
    
    // Notice, that the ownership of the filter parameters will
    // remain in the filter.
    CIAUpdateParameters* params( iFilter->FilterParams() );
    if ( !IsStartedByLauncher()
         || params )
        {
        IAUPDATE_TRACE_1("[IAUPDATE] Request type check matched: %d", iRequestType);

        // Check if IAD was started from the grid or through API.
        // If IAD was started like from the grid but it still has parameters set,
        // then act as it was started through API. Most likely, then the IAD was
        // originally started through API but because of self update IAD was restarted
        // and now it has original parameters set.

        if ( !iStarter )
            {
            IAUPDATE_TRACE("[IAUPDATE] iStarter not set");
        	iStarter = CIAUpdateStarter::NewL( params->CommandLineExecutable(), 
        	                                   params->CommandLineArguments() );
            }

        // Notice, that when starter calls StartExecutableCompletedL callback function,
        // the observer is informed from there about the completion of the update flow.
        // So, do not inform observer here.
        iStarter->StartExecutableL( *this );
        }
    else
        {
        // Do not try to start any application. 
        // But, use the start application callback function
        // to end the update flow correctly (same way as after 
        // application start with other options).
        IAUPDATE_TRACE_1("[IAUPDATE] Update complete error: %d", aError );
        StartExecutableCompletedL( aError );
        }    

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::EndUpdateFlowL() end");
    }

// ---------------------------------------------------------------------------
// CIAUpdateUiController::CheckUpdatesDeferredCallbackL
// CheckUpdates as deferred to get empty main view visible before CheckUpdates
//
// ---------------------------------------------------------------------------
//
TInt CIAUpdateUiController::CheckUpdatesDeferredCallbackL( TAny* aPtr )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CheckUpdatesDeferredCallbackL() begin");

    CIAUpdateUiController* uiCtrl = static_cast<CIAUpdateUiController*>( aPtr );
    
    TRAPD ( err, uiCtrl->PrepareRoamingHandlerL() );
    if ( err != KErrNone )
        {
        uiCtrl->iObserver.HandleLeaveErrorL( err );
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CheckUpdatesDeferredCallbackL() end");

	return KErrNone;
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::ShowUpdatingDialogL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::ShowUpdatingDialogL( TInt aTextResourceId,
                                                 const TDesC& aName,
                                                 TInt aNumber,
                                                 TInt aTotalCount )   
                                                    
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ShowUpdatingDialogL() begin");

    // Before trying ot create a new dialog,
    // remove possible existing dialog.
    RemoveUpdatingDialogsL();

    CDesCArray* stringArray = new( ELeave ) CDesCArrayFlat( 1 );
    CleanupStack::PushL( stringArray );
    stringArray->AppendL( aName );
    CArrayFix<TInt>* numberArray = new( ELeave ) CArrayFixFlat<TInt>( 2 );
    CleanupStack::PushL( numberArray );
    numberArray->AppendL( aNumber ); 
    numberArray->AppendL( aTotalCount );
    HBufC* noteText = NULL;
    noteText = StringLoader::LoadLC( aTextResourceId, 
                                     *stringArray, 
                                     *numberArray );
    TPtr ptr = noteText->Des();
    AknTextUtils::DisplayTextLanguageSpecificNumberConversion( ptr ); 
    if ( iState == EDownloading )
        {
    	ShowProgressDialogL( *noteText, ETrue );
        }
    else
        {
        ShowWaitDialogL( *noteText, ETrue );	
        }
    
    CleanupStack::PopAndDestroy( noteText ); 
    CleanupStack::PopAndDestroy( numberArray );
    CleanupStack::PopAndDestroy( stringArray );

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ShowUpdatingDialogL() end");
    }
 

// ---------------------------------------------------------------------------
// CIAUpdateUiController::ShowWaitDialogL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::ShowWaitDialogL( const TDesC& aDisplayString, 
                                             TBool aVisibilityDelayOff ) 
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ShowWaitDialogL() begin");

    if ( iWaitDialog )
        {
        IAUPDATE_TRACE("[IAUPDATE] Wait dialog already existed. Remove it first");
        // in some rare cases previous dialog still exists
        // it's now just deleted (not recommended way) to avoid forwarding problem(s). 
        delete iWaitDialog;
        iWaitDialog = NULL;
        }
    iWaitDialog = 
        new( ELeave ) CIAUpdateWaitDialog( 
            reinterpret_cast< CEikDialog** >( &iWaitDialog ),
            aVisibilityDelayOff );
                
    iWaitDialog->SetTextL( aDisplayString );
    iWaitDialog->SetCallback( this );        
    iWaitDialog->ExecuteLD( R_IAUPDATE_WAIT_DIALOG );

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ShowWaitDialogL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::ShowProgressDialogL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::ShowProgressDialogL( const TDesC& aDisplayString, 
                                                 TBool aVisibilityDelayOff ) 
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ShowProgressDialogL() begin");

    if ( iProgressDialog )
        {
        IAUPDATE_TRACE("[IAUPDATE] Progress dialog already existed. Remove it first");
        // in some rare cases previous dialog still exists
        // it's now just deleted (not recommended way) to avoid forwarding problem(s). 
        delete iProgressDialog;
        iProgressDialog = NULL;
        }
    iProgressDialog = 
        new( ELeave ) CIAUpdateProgressDialog( 
            reinterpret_cast< CEikDialog** >( &iProgressDialog ),
            aVisibilityDelayOff );
                
    iProgressDialog->SetTextL( aDisplayString );
    iProgressDialog->SetCallback( this );        
    iProgressDialog->ExecuteLD( R_IAUPDATE_PROGRESS_DIALOG );

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ShowProgressDialogL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RemoveUpdatingDialogsL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::RemoveUpdatingDialogsL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RemoveUpdatingDialogsL() begin");
    
    RemoveWaitDialogL();
    RemoveProgressDialogL();

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RemoveUpdatingDialogsL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RemoveWaitDialogL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::RemoveWaitDialogL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RemoveWaitDialogL() begin");

    if ( !iCancelling )  //that's needed because AVKON  in 3.2.3 wk12, returning
                         //EFalse in TryToExitL() causes a crash   
        {
    	if ( iWaitDialog )
            {
    	    iWaitDialog->ProcessFinishedL();
            }
        }
    
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RemoveWaitDialogL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RemoveProgressDialogL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::RemoveProgressDialogL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RemoveProgressDialogL() begin");

    if ( !iCancelling )  //that's needed because AVKON  in 3.2.3 wk12, returning
                         //EFalse in TryToExitL() causes a crash   
        {
    	if ( iProgressDialog )
            {
    	    iProgressDialog->ProcessFinishedL();
            }
        }
    
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RemoveProgressDialogL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::AllowNetworkRefreshL
// 
// ---------------------------------------------------------------------------
//
TBool CIAUpdateUiController::AllowNetworkRefreshL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::AllowNetworkRefreshL() begin");
    
    TBool allowRefresh( EFalse );
    if ( IsStartedByLauncher() )
        {
    	if ( !iRefreshFromNetworkDenied && 
    	     !iUserRoamingRejection && 
    	     !RestartedFromSelfUpdate() )
    	    {
    		if ( LocalNodesExpiredL() )
    		    {
    			allowRefresh = ETrue;
    		    }
    	    }
        }
    else   
        {
        // started by an application
        if ( iFilter )
    	    {
    	    CIAUpdateParameters* params( iFilter->FilterParams() );
    	    if ( params )
    	        {
    	    	if ( params->Refresh() )
    	    	    {
      	      		// Check from the central repocitory what are the automatic checking and 
                    // roaming settings.     
                    TInt autoUpdateCheckValue( 0 );
                    CRepository* cenrep( 
                             CRepository::NewLC( KCRUidIAUpdateSettings ) );
                    // Notice, that KIAUpdateSettingAutoUpdateCheck can give following values
                    // 0 = No automatic update check
                    // 1 = Automatic update check enabled when not roaming
                    // 2 = Automatic update enabled

                    User::LeaveIfError( cenrep->Get( KIAUpdateAutoUpdateCheck, 
                                                     autoUpdateCheckValue ) );
                    CleanupStack::PopAndDestroy( cenrep );
                    if ( ( autoUpdateCheckValue == EIAUpdateSettingValueEnable ) || 
    	               ( autoUpdateCheckValue == EIAUpdateSettingValueDisableWhenRoaming &&
    	                 !iRoamingHandler->IsRoaming() ) )
                        {
                    	allowRefresh = ETrue;
                        }
     	    	    }
    	        }
    	    }
        }
    
    IAUPDATE_TRACE_1("[IAUPDATE] allowRefresh: %d", allowRefresh );    
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::AllowNetworkRefreshL() end");  
    return allowRefresh;
    }



// ---------------------------------------------------------------------------
// CIAUpdateUiController::LocalNodesExpiredL
// 
// ---------------------------------------------------------------------------
//
TBool CIAUpdateUiController::LocalNodesExpiredL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::LocalNodesExpiredL() begin");

    // Notice, that the values for the iControllerFile, that are used here for
    // expiration checkings, are set after successfull completion of refresh
    // operation. See, UpdateControllerFileL that is called when operation
    // finishes successfully. 

    const TTimeIntervalHours KExpirationDeltaInHours( 
        ConfigData().GridRefreshDeltaHours() );
    
    // Make sure that the most current data is gotten from the file.
    iControllerFile->ReadControllerDataL();

    TLanguage currentLanguage = User::Language();
    TLanguage lastTimeLanguage = iControllerFile->Language();
    if ( lastTimeLanguage != currentLanguage )
        {
        // Think nodes as expired because the language 
        // has been changed in the phone. By updating the nodes,
        // the items in UI will show correct language.
        // No need to set the language to the controller file here.
        // The value is set when the operation is successfully completed.
        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::LocalNodesExpiredL() ETrue end");
        return ETrue;
        }
        
    // Because the language check has passed,
    // check also the time expirations.

    // Get the last recorded refresh time from the controller file    
    TTime lastRefreshTime( iControllerFile->RefreshTime() );

    // Initialize expireTime with the last refresh time. Notice,
    // that this expire time will be increased below with the correct 
    // value
    TTime expireTime( lastRefreshTime );

    expireTime += KExpirationDeltaInHours;

    // Get the current time.
    TTime universalTime;
    universalTime.UniversalTime();

    if ( expireTime < universalTime
         || lastRefreshTime > universalTime )
        {
        // Database is expired because current time has passed the
        // expiration time. Also, sanity check is made. If
        // last refresh time is larger than current time, then the
        // last refresh value has been set wrong, and the database can
        // be thought as expired. This might be the case if the user has
        // changed the time in the phone.
        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::LocalNodesExpiredL() ETrue end");
        return ETrue;
        }
    else
        {
        // Database is not expired yet.
        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::LocalNodesExpiredL() EFalse end");
        return EFalse;        
        } 
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::UpdateControllerFileL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::UpdateControllerFileL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::UpdateControllerFileL() begin");

    // This function is called after the refresh operation has
    // completed.

    // Check if local nodes were updated from the server.
    // Notice, that last refresh time and language are both checked
    // here when LocalNodesExpiredL() is called from AllowNetworkRefreshL.
    // AllowNetworkRefreshL is called here because autoupdate and roaming checks
    // should also be done when deciding if the nodes were updated.
    if ( AllowNetworkRefreshL() )
        {
        // Update controller file with current information 
        // because old values were expired.
        iControllerFile->SetCurrentData();

        // Because data is not up to date,
        // save new data into the file.
        iControllerFile->WriteControllerDataL();        
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::UpdateControllerFileL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::IsStartedByLauncher
// 
// ---------------------------------------------------------------------------
//
TBool CIAUpdateUiController::IsStartedByLauncher()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::IsStartedByLauncher()");

    if ( iRequestType == IAUpdateUiDefines::ENoRequest )
        {
        IAUPDATE_TRACE("[IAUPDATE] Started by launcher");
        // This operation was started from the application that was
        // started by launcher
        // Currently it means that launching is originated 
        // from application grid or background checker. There is only
        // one iaupdate instance started by launcher
        return ETrue;
        }
    else
        {
        IAUPDATE_TRACE("[IAUPDATE] NOT started by launcher");
        // According to the request type, 
        // API was used to start the operation.
        return EFalse;        
        }
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::StartPossibleSelfUpdateL
// 
// ---------------------------------------------------------------------------
//
TBool CIAUpdateUiController::StartPossibleSelfUpdateL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartPossibleSelfUpdateL() begin");

    // If there exist some self updater files that need to be installed
    // separately, start self updating process.
    TBool started( 
        iController->
            StartPossibleSelfUpdateL( iNodeIndex, 
                                      iSelectedNodesArray.Count(),
                                      iSelectedNodesArray,
                                      EFalse ) );
            
    // Because self updater has gotten all the information it needs now,
    // we can reset the data that is meant for the updater.
    iController->ResetSelfUpdate();

    IAUPDATE_TRACE_1("[IAUPDATE] started: %d", started );
    if ( started )
        {
        // Because self update was started, save possible parameters data 
        // for the possible restart of IAD. The, IAD can continue correctly.
        ParamsWriteFileL();
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::StartPossibleSelfUpdateL() end");
    
    return started;  
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::UpdateFailedSelfUpdaterInfoToPurchaseHistoryL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::UpdateFailedSelfUpdaterInfoToPurchaseHistoryL( TInt aErrorCode )
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::UpdateFailedSelfUpdaterInfoToPurchaseHistoryL() begin");
    IAUPDATE_TRACE_1("[IAUPDATE] error code: %d", aErrorCode );

    // Check all the items that have been updated so far.
    // And, set the error info to purchase history accordingly.
    for ( TInt i = 0; 
          i < iSelectedNodesArray.Count()
          && i < iNodeIndex + 1;
          ++i )
        {
        MIAUpdateNode* node( iSelectedNodesArray[ i ] );
        if ( node->IsSelfUpdate() )
            {
            TBool installSuccess( node->IsInstalled() );
            if ( !installSuccess  )
                {
                // Notice, that we can just set the purchase history here for
                // the self updater items. If some of the items were installed,
                // before self updater items, then their information was already
                // correctly into the history.
                TInt error( aErrorCode );
                if ( aErrorCode == KErrNone )
                    {
                    error = KErrUnknown;
                    }

                // Because we are handling nodes that are visible in UI,
                // we can force the node as visible in history.                    
                node->Base().SetInstallStatusToPurchaseHistoryL( error, ETrue );
                }
            }
        }

    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::UpdateFailedSelfUpdaterInfoToPurchaseHistoryL() end");    
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::HandleUserCancelL
// 
// ---------------------------------------------------------------------------
//      
void CIAUpdateUiController::HandleUserCancelL()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandleUserCancelL() begin");

    // Get the current state.
    // CancelOperation will set a new value for the state and we do not 
    // want to use that.
    TState state( iState );
    
    CancelOperation();
    
    // Set the flag on. 
    // So, dialogs are handled correctly.
    iCancelling = ETrue;
    
    if ( state == EDownloading || state == EInstalling )
        {
        IAUPDATE_TRACE("[IAUPDATE] Cancel pressed while updating");
        // Update flow is completed here.
        // Notice, that this will also start the report sending,
        // but we do not wait the sending to be complete before continuing.
        UpdateCompleteL( KErrCancel );
        }
    else if ( state == ESendingReport )
        {
        IAUPDATE_TRACE("[IAUPDATE] Dialog cancel called while sending reports");
        // Reports are sent only when update flow has finished.
        // So, UpdateCompleteL has already been called and an update flow
        // dialog is still being shown. Because cancel is called, complete 
        // flow without waiting for the report sending to finish.
        EndUpdateFlowL( KErrCancel ); 
        }

    // Set the flag off because cancellation is over.
    iCancelling = EFalse;

	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::HandleUserCancelL() end");
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::RestartedFromSelfUpdate
// 
// ---------------------------------------------------------------------------
//      
TBool CIAUpdateUiController::RestartedFromSelfUpdate()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::RestartedFromSelfUpdate() begin");
	
    TBool restarted( EFalse );
    
    CIAUpdateRestartInfo* info( iController->SelfUpdateRestartInfo() ); 
    if ( info ) 
        { 
        // Restart info was available. 
        delete info; 
        info = NULL; 
        restarted = ETrue; 
        }    

	IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateUiController::RestartedFromSelfUpdate() end: %d", 
	                 restarted);
    
    return restarted;
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::ParamsReadAndRemoveFileL
// 
// ---------------------------------------------------------------------------
//  
CIAUpdateParameters* CIAUpdateUiController::ParamsReadAndRemoveFileL()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ParamsReadAndRemoveFileL() begin");
	
    CIAUpdateParameters* params( NULL );

    CIAUpdateParametersFileManager* mgr( CIAUpdateParametersFileManager::NewLC() );
    params = mgr->ReadL();
    mgr->RemoveFile();
    CleanupStack::PopAndDestroy( mgr );
        
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ParamsReadAndRemoveFileL() end");    
    
    return params;
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::ParamsWriteFileL
// 
// ---------------------------------------------------------------------------
//  
void CIAUpdateUiController::ParamsWriteFileL()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ParamsWriteFileL() begin");
	
	// Ownership is not transferred here.
	CIAUpdateParameters* params( iFilter->FilterParams() );
	if ( params )
	    {
        CIAUpdateParametersFileManager* mgr( 
            CIAUpdateParametersFileManager::NewLC() );
        mgr->WriteL( *params );
        CleanupStack::PopAndDestroy( mgr );
	    }

	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ParamsWriteFileL() end");    
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::ParamsRemoveFileL
// 
// ---------------------------------------------------------------------------
//  
void CIAUpdateUiController::ParamsRemoveFileL()
    {
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ParamsRemoveFileL() begin");
	
    CIAUpdateParametersFileManager* mgr( 
        CIAUpdateParametersFileManager::NewL() );
    mgr->RemoveFile();
    delete mgr;
    mgr = NULL;
            
	IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::ParamsRemoveFileL() end");    
    }


// ---------------------------------------------------------------------------
// CIAUpdateUiController::CreateSelectedNodesArrayL
// 
// ---------------------------------------------------------------------------
//
void CIAUpdateUiController::CreateSelectedNodesArrayL()
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CreateSelectedNodesArrayL() begin");
    iSelectedNodesArray.Reset();
    for ( TInt i = 0; i < iNodes.Count(); ++i )
        {
        if ( iNodes[ i ]->Base().IsSelected() )
            {
            iSelectedNodesArray.AppendL( iNodes[ i ] );
            }
        }

    // Dependency nodes to be updated before their dependants.
    // Also, self update nodes should be handled correctly.
    iSelectedNodesArray.Sort( 
          TLinearOrder< MIAUpdateNode >( &SortSelectedNodes ) );
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::CreateSelectedNodesArrayL() end");
    }

// ---------------------------------------------------------------------------
// CIAUpdateUiController::IAUpdateEnabledL()
// ---------------------------------------------------------------------------
//
TBool CIAUpdateUiController::IAUpdateEnabledL() const
    {
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::IAUpdateEnabledL() begin");
    TBool enabled = EFalse;
    RFeatureControl featureControl;
    TInt error( KErrNone );

    error = featureControl.Connect();
    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateUiController::IAUpdateEnabledL() Connection to the Feature Manager Server: %d", error);
    
    User::LeaveIfError( error );
    
    TUid iaupdatefeature;
    iaupdatefeature.iUid = KFeatureIdIAUpdate;
    
    TInt ret = featureControl.FeatureSupported( iaupdatefeature );
    if ( ret == KFeatureSupported )
        {
        enabled = ETrue;
        }
    featureControl.Close(); 
    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateUiController::IAUpdateEnabledL() end");
    return enabled;        
    }

// End of File