iaupdate/IAD/engine/controller/src/iaupdatecontentoperationmanager.cpp
changeset 0 ba25891c3a9e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/iaupdate/IAD/engine/controller/src/iaupdatecontentoperationmanager.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,1321 @@
+/*
+* Copyright (c) 2007-2008 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:   CIAUpdateContentOperationManager 
+*
+*/
+
+
+
+#include <ncdpurchasedetails.h>
+
+#include "iaupdatecontentoperationmanager.h"
+#include "iaupdatenodeimpl.h"
+#include "iaupdateoperation.h"
+#include "iaupdatepurchaseoperation.h"
+#include "iaupdatedownloadoperation.h"
+#include "iaupdateinstalloperation.h"
+#include "iaupdateselfupdateinitoperation.h"
+#include "iaupdatectrlnodeconsts.h"
+#include "iaupdatenodefactory.h"
+
+#include "iaupdatedebug.h"
+
+
+// Const value for the progress init value.
+const TInt KInitProgress( 0 );
+
+
+// This is a static function that is used with RPointerArray::Sort to sort
+// the nodes according to their node depths.
+TInt NodeArraySorter( const CIAUpdateNode& aNode1, const CIAUpdateNode& aNode2 )
+    {
+    // The leaf should be in the end of the array and the root in the beginning.
+    // The depth value informs how deep in the 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.
+    return ( aNode1.Depth() - aNode2.Depth() );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::::NewL
+// 
+// ---------------------------------------------------------------------------
+// 
+CIAUpdateContentOperationManager* CIAUpdateContentOperationManager::NewL()
+    {
+    CIAUpdateContentOperationManager* self = 
+        CIAUpdateContentOperationManager::NewLC();
+    CleanupStack::Pop( self );
+    return self;
+    }
+    
+    
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::::NewLC
+// 
+// ---------------------------------------------------------------------------
+// 
+CIAUpdateContentOperationManager* CIAUpdateContentOperationManager::NewLC()
+    {
+    CIAUpdateContentOperationManager* self =
+        new( ELeave ) CIAUpdateContentOperationManager();
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::CIAUpdateContentOperationManager
+// 
+// ---------------------------------------------------------------------------
+// 
+CIAUpdateContentOperationManager::CIAUpdateContentOperationManager()
+: CActive( CActive::EPriorityStandard )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CIAUpdateContentOperationManager");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::ConstructL
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::ConstructL()
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ConstructL begin");
+
+    CActiveScheduler::Add( this );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ConstructL end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager
+// 
+// ---------------------------------------------------------------------------
+// 
+CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager()
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager begin");
+
+    // It is always good to call this in active object destructor 
+    // to be sure that no operations are left hanging. 
+    // This will also reset and delete all the necessary data if needed.
+    Cancel();
+
+    // Reset the array to be sure.
+    // If the operation has left during startup, the array may not be reseted.
+    iNodes.Reset();
+
+    // Delete operation to make sure that it is also deleted.
+    delete iOperation;
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::CheckErrorCode
+// 
+// ---------------------------------------------------------------------------
+// 
+TInt CIAUpdateContentOperationManager::CheckErrorCode( TInt aError )
+    {
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode begin: %d",
+                     aError);
+    
+    if ( aError > ( IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
+                    - IAUpdateCtrlNodeConsts::KErrBaseRange ) 
+         && aError <= IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Service pack install");
+        aError -= IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall;
+        }
+    else if ( aError > IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
+              && aError <= IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Service pack download");
+        aError -= IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload;
+        }
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode end: %d",
+                     aError);
+
+    return aError;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::CheckErrorCode
+// 
+// ---------------------------------------------------------------------------
+// 
+CIAUpdateContentOperationManager::TContentOperationType 
+    CIAUpdateContentOperationManager::ServicePackOperationType( 
+        MNcdPurchaseDetails& aNodeDetails )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode begin");
+
+    if ( !IAUpdateNodeFactory::IsServicePack( 
+            aNodeDetails.AttributeString( 
+                MNcdPurchaseDetails::EPurchaseAttributeContentMimeType ) ) )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode end: ENoContentOperation");
+        return ENoContentOperation;
+        }
+    
+    TContentOperationType type( EPurchaseOperation );
+    
+    TInt errorCode( aNodeDetails.LastOperationErrorCode() );
+
+    if ( errorCode > ( IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
+                       - IAUpdateCtrlNodeConsts::KErrBaseRange ) 
+         && errorCode <= IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Service pack install");
+        type = EInstallOperation;
+        }
+    else if ( errorCode > IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
+              && errorCode <= IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Service pack download");
+        type = EDownloadOperation;
+        }
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode end: %d",
+                     type);
+
+    return type;     
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::SortNodeArray
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::SortNodeArray( 
+    RPointerArray< CIAUpdateNode >& aNodes )
+    {
+    // Use that static function to sort the array.
+    aNodes.Sort( TLinearOrder< CIAUpdateNode >( &NodeArraySorter ) );
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::GetOperationNodesL
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::GetOperationNodesL( 
+    const CIAUpdateNode& aNode, RPointerArray< CIAUpdateNode >& aNodes,
+    TBool aAcceptHiddenDependencyNodes, TBool aAcceptVisibleDependencyNodes )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationNodeArrayL() begin");
+    
+    // Reset the array.
+    // So, new nodes can be inserted into it.
+    aNodes.Reset();
+
+    // We need to get the array of the nodes that this node depends on.
+    // Notice, that here we just want the specific type of nodes that belong 
+    // to this node. If another dependency node does not match the criteria then 
+    // ignore that branch starting from that node.
+    HandleDependenciesL( aNode, aNodes,
+                         aAcceptHiddenDependencyNodes, 
+                         aAcceptVisibleDependencyNodes );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationNodeArrayL() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::TotalContentSizeL
+// 
+// ---------------------------------------------------------------------------
+//     
+TInt CIAUpdateContentOperationManager::TotalContentSizeL( 
+    const CIAUpdateNode& aNode,
+    TBool aIncludeDownloaded,
+    TBool aIncludeInstalled,
+    TBool aAcceptHiddenDependencyNodes,
+    TBool aAcceptVisibleDependencyNodes )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNode::TotalContentSizeL() begin");
+
+    RPointerArray< CIAUpdateNode > nodes;
+    CleanupClosePushL( nodes );
+    GetOperationNodesL( 
+        aNode, nodes,
+        aAcceptHiddenDependencyNodes, 
+        aAcceptVisibleDependencyNodes );
+    TInt totalContentSize( 
+        ArrayTotalContentSizeL( 
+            nodes, aIncludeDownloaded, aIncludeInstalled ) );
+    CleanupStack::PopAndDestroy( &nodes );
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNode::TotalContentSizeL() end: %d",
+                     totalContentSize);
+
+    return totalContentSize;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::StartL
+// 
+// ---------------------------------------------------------------------------
+//     
+void CIAUpdateContentOperationManager::StartL( 
+    MIAUpdateContentOperationObserver& aObserver,
+    const CIAUpdateContentOperationManager::TContentOperationType& aOperationType,
+    CIAUpdateNode& aNode )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::StartL begin");
+
+    if ( iOperation || IsActive() )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] ERROR Operation already existed");
+        User::Leave( KErrInUse );
+        }
+    else if ( aNode.Hidden()  )
+        {
+        // The main node is not allowed to be hidden.
+        IAUPDATE_TRACE("[IAUPDATE] ERROR: Hidden node given");
+        User::Leave( KErrArgument );
+        }
+    else if ( aOperationType != EPurchaseOperation
+              && aOperationType != EDownloadOperation
+              && aOperationType != EInstallOperation )
+        {
+        // The main node is not allowed to be hidden.
+        IAUPDATE_TRACE("[IAUPDATE] ERROR Operation type not supported");
+        User::Leave( KErrNotSupported );
+        }
+
+    // Reset member variables
+    iSuccessCount = 0;
+
+    // Set progress values to defaults.
+    ResetProgress();
+    
+    // Notice, that this will also set the main node.
+    SetNodeArrayL( aNode );
+
+    // Progress values were resetted above.
+    // Now, set the expected total maximum value for the progress.
+    InitTotalMaxProgressL( aOperationType );
+
+    // Set the observer
+    iObserver = &aObserver;
+    
+    // Set the operation type
+    iOperationType = aOperationType;
+
+    // Start the operation by calling the first round for active loop.
+    iStatus = KRequestPending;
+    SetActive();
+    TRequestStatus* ptrStatus = &iStatus;
+    User::RequestComplete( ptrStatus, KErrNone );                
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::StartL end");
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::OperationType
+// 
+// ---------------------------------------------------------------------------
+// 
+const CIAUpdateContentOperationManager::TContentOperationType& 
+    CIAUpdateContentOperationManager::OperationType() const
+    {
+    return iOperationType;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::ContentOperationComplete
+// 
+// ---------------------------------------------------------------------------
+//
+void CIAUpdateContentOperationManager::ContentOperationComplete( 
+    CIAUpdateBaseNode& /*aNode*/,
+    TInt aError )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationComplete() begin");
+
+    // Content operation has completed.
+    // In normal cases, start new active loop. So, RunL will be called.
+    // Notice, that if Cancel was called, this callback function is called from the
+    // operation when its cancel is synchronously completed. Because Cancel is waiting 
+    // for DoCancel function to complete the request, let it complete here. So, 
+    // actual cancel can finish its job. We do not want to call callbacks of the observer 
+    // of this operation manager after Cancel.
+
+    if ( aError == KErrNone )
+        {
+        ++iSuccessCount;
+        IAUPDATE_TRACE_1("[IAUPDATE] Successfull operation: %d",
+                         iSuccessCount); 
+
+        // Check that the node MIME is set correctly.
+        // Then, the history will be shown also correctly for the nodes.
+        // By updating the purchase history, also the correct MIME type
+        // is set, for example, if node is hidden.
+        IAUPDATE_TRACE("[IAUPDATE] Update purchase history for current node.");
+        UpdatePurchaseHistory( *iCurrentNode, aError );
+        }
+
+    TRequestStatus* ptrStatus = &iStatus;
+    User::RequestComplete( ptrStatus, aError );
+    
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationComplete() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::ContentOperationProgress
+// 
+// ---------------------------------------------------------------------------
+//
+void CIAUpdateContentOperationManager::ContentOperationProgress( 
+    CIAUpdateBaseNode& /*aNode*/, 
+    TInt aProgress, 
+    TInt aMaxProgress )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationProgress() begin");
+
+    UpdateProgress( aProgress, aMaxProgress );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationProgress() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::DoCancel
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::DoCancel()
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::DoCancel() begin");
+    
+    // If we are here, then there should always be an operation going on.
+
+    // Notice, that if disclaimers are shown, for example,
+    // when installing, then the KErrCancel can be gotten from
+    // the operation even if the cancellation was not started from here.
+    // But, then the RunL is called and the operation is finished correctly.
+    // But, if cancellation is started here, the RunL is not called and the 
+    // cancellation proceedes correctly. Instead then, operations call directly
+    // ContentOperationComplete callback function that completes the request that
+    // active object Cancel is listening to complete its actions.
+    
+    // Cancel the current operation by deleting it.
+    delete iOperation;
+    iOperation = NULL;
+
+    // No need for the observer anymore.
+    iObserver = NULL;
+
+
+    // Because, the main node is the one that is visible, its error code
+    // needs to be updated here separately. Also, the current node needs
+    // to be updated. So, set them by hand. If other nodes were not operated,
+    // no need to update their info to purchase history because they should
+    // not be shown in the history view anyways.
+    // Notice, that even if the operations may have updated the purchase history
+    // by themselves in NCD Engine side, the purchase history MIME type may
+    // need to be updated according to the IAD node values. So, that is why
+    // we update the purchase history here one more time.
+    // Notice, that in case of service packs and other service packs 
+    // inside them, also then just set the purchase history for the head
+    // service pack.
+
+    if ( iNode != iCurrentNode )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Update current node purchase history with KErrCancel");
+        UpdatePurchaseHistory( *iCurrentNode, KErrCancel );
+        }
+
+    IAUPDATE_TRACE("[IAUPDATE] Update head node purchase history with KErrCancel");
+    UpdatePurchaseHistory( *iNode, KErrCancel );
+
+
+    // No need for nodes
+    iNodes.Reset();
+    iNode = NULL;
+    iCurrentNode = NULL;
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::DoCancel() end");
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::RunL
+// 
+// ---------------------------------------------------------------------------
+//     
+void CIAUpdateContentOperationManager::RunL()
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::RunL() begin");
+
+    // Reset progress for current operation.
+    ResetCurrentProgress();
+
+    // Delete old operation.
+    // Later a new and correct type of operation will be created for
+    // the new node if one is found.
+    delete iOperation;
+    iOperation = NULL;
+
+    // When the operation flow is started, the error code is always KErrNone.    
+    // We only get errors to status if content operation is going on.
+    User::LeaveIfError( iStatus.Int() );
+    
+    // Handle the next content in the array.
+    if ( iNodes.Count() > 0 )
+        {
+        // Handle next node.
+        SetCurrentNodeL();
+
+        if ( IsServicePack( *iNode ) 
+             && iCurrentNode->IsSelfUpdate() )
+            {
+            // Because operation was created, it means that the self update inside
+            // the service pack is not installed yet. Because we do not support
+            // self updates inside service packs, leave from here.
+            
+            // Note for future improvements: 
+            // If service packs support for self update is added, remove
+            // the if clause and always append nodes.
+            // Also, remember to update CIAUpdateServicePackNode::IsSelfUpdate 
+            // function if UI side should know about the self updates inside
+            // the service pack. Then, most likely service pack should be thought 
+            // as self update if any of the items gotten in the dependency hierarchy
+            // is a self update.
+
+            IAUPDATE_TRACE("[IAUPDATE] Service pack does not support self updates");
+            User::Leave( KErrNotSupported );
+            }
+
+
+        // Notice, that in case of service packs, the operation is not created.
+        // Skip, service pack items themself and only handle operations for 
+        // their dependencies.
+
+        TBool operationStarted( EFalse );      
+
+        iOperation = CreateOperationL( iOperationType, *iCurrentNode );
+
+        if ( iOperation )
+            {
+            IAUPDATE_TRACE("[IAUPDATE] Operation existed");
+            operationStarted = iOperation->StartOperationL();
+            if ( !operationStarted )
+                {
+                IAUPDATE_TRACE("[IAUPDATE] Operation already completed successfully");
+                // Notice, we increase iSuccessCount value here
+                // even if the operation has already been finished.
+                // This is because in CompleteOperation function success count is
+                // checked to give a correct error code to observer. If we do not
+                // count already completed successes and for some reason a next type of
+                // operation in the flow is stopped (for example cancelled), then
+                // the continuation of the flow in a new try of the flow may be prevented.
+                // For example, some of the items are downloaded and some had errors. But,
+                // flow continues to install which is then cancelled. So, not all items
+                // are installed. Then flow is started again, but no new items can be
+                // downloaded because of errors. Then we need to count also previous
+                // successess to make the flow to continue to the install operations of
+                // previously cancelled items. 
+                // So, by also counting previous successes we ensure that the flow 
+                // will continue in all the cases. The downside of this is that in 
+                // some cases the flow will continue even if there is nothing to do
+                // in next type of operation, but it is better than let the flow 
+                // been locked.
+                ++iSuccessCount;
+                }
+            }
+
+        // Make the active object to listen operation completion.
+        iStatus = KRequestPending;
+        SetActive();            
+
+        if ( !operationStarted )
+            {
+            IAUPDATE_TRACE("[IAUPDATE] Operation was not started");
+            // Complete the active request now. 
+            // This way a new active loop will continue.
+            // We come hear when a service pack has been already fully handled,
+            // or if the item operation was already finished before.
+            // There should be no need to update the progress here because
+            // the node operation were already done. When the total progress
+            // variables were initialized during the start of the operation, 
+            // already handled items were skipped also then.
+            // So, skip progress handling for them also now. 
+            TRequestStatus* ptrStatus = &iStatus;
+            User::RequestComplete( ptrStatus, KErrNone );                        
+            }
+        }
+    else
+        {
+        // No other node content to handle.
+        // So, complete the whole operation.
+        CompleteOperation( KErrNone );
+        }
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::RunL() end");
+    }
+    
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::RunError
+// 
+// ---------------------------------------------------------------------------
+// 
+TInt CIAUpdateContentOperationManager::RunError( TInt aError )
+    {
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::RunError() begin: %d",
+                     aError);
+
+    // By updating the purchase history here, the correct MIME type
+    // is set, for example, if node is hidden. NCD Engine sets the
+    // purchase history details already in its own operations but
+    // we need to be sure that MIME type is set correctly according
+    // to the IAD node values. Update current notde only if it was
+    // not skipped.
+    if ( iCurrentNode != iNode
+         && aError != IAUpdateCtrlNodeConsts::KErrSkipNode )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Update purchase history for current node.");
+        UpdatePurchaseHistory( *iCurrentNode, aError );
+        }
+
+    // Because, the main node is the one that is visible, its error code
+    // needs to be updated here separately. So, set it by hand. If other
+    // nodes were not handled, no need to update their info to purchase
+    // history because they should not be shown in the history view
+    // anyways.
+    // Notice, that in case of service packs and other service packs 
+    // inside them, also then just set the purchase history for the head
+    // service pack.
+    // Do not update the purchase history if the node has been skipped
+    // inside a service pack. If node has been skipped during normal
+    // dependency chain, then most likely UI tries to operate normal 
+    // visible node whose dependency has not been completed before in
+    // the update flow. Notice, that also in this case there may be some
+    // hidden nodes that are installed before the main node. So, skipping
+    // may also start from those hidden nodes.
+    if ( aError != IAUpdateCtrlNodeConsts::KErrSkipNode
+         || !IsServicePack( *iNode ) )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Update purchase history for main node.");
+        UpdatePurchaseHistory( *iNode, aError );
+        }
+
+    // If the head node is service pack,
+    // one error does not prevent the whole head 
+    // service pack operation.
+    // If the head node is not a service pack, then the operation
+    // will end here. 
+    // Also, do not continue with service packs either if no node
+    // is left in the node array.
+
+    if ( iNodes.Count() > 0 && IsServicePack( *iNode ) )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Service pack error accepted");
+
+        // Because we are still going to continue the operation,
+        // update the progrees for the error node.
+        if ( !IsServicePack( *iCurrentNode ) )
+            {
+            // Skip service packs because their own size is zero.
+            // In the progress bar point of view, just increase the
+            // progress in a same way as if the operation had been completed
+            // correctly.
+            TInt newProgress( iCurrentMaxProgress );
+            if ( newProgress == KInitProgress )
+                {
+                if ( iOperationType == EDownloadOperation )
+                    {
+                    TRAP_IGNORE ( newProgress += iCurrentNode->OwnContentSizeL() );
+                    }
+                else
+                    {
+                    ++newProgress;
+                    }
+                }
+            // Update progress with new max values.
+            // Notice, that if newProgress was left to KInitProgress,
+            // the this function call will immediately return.
+            UpdateProgress( newProgress, newProgress );  
+            }
+
+        // Continue to the next branch now that error is handled.
+        IAUPDATE_TRACE("[IAUPDATE] Start new loop");
+        iStatus = KRequestPending;
+        SetActive();
+        TRequestStatus* ptrStatus = &iStatus;
+        User::RequestComplete( ptrStatus, KErrNone );
+        }
+    else
+        {
+        CompleteOperation( aError );       
+        }
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::RunError() end");
+    
+    // Return KErrNone. So, the application will not panic.
+    return KErrNone;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::UpdateProgress
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::UpdateProgress( 
+    TInt aProgress, TInt aMaxProgress )
+    {
+    IAUPDATE_TRACE_2("[IAUPDATE] CIAUpdateContentOperationManager::UpdateProgress() begin: %d, %d",
+                     aProgress, aMaxProgress);
+
+    if ( aProgress < 0 
+         || aMaxProgress <= 0
+         || ( aProgress == iCurrentProgress && aMaxProgress == iCurrentMaxProgress ) )
+        {
+        // Do not proceed if progress is negative or max progress is zero or less.
+        // Also, do not proceed if nothing has changed.
+        IAUPDATE_TRACE("[IAUPDATE] Progress values negative or zero or no changes. Return.");
+        return;
+        }
+
+    TInt currentDif( aProgress - iCurrentProgress );
+    if ( currentDif != 0 )
+        {
+        // Progress has occurred.
+        IAUPDATE_TRACE_2("[IAUPDATE] New value for current: %d . Dif: %d", 
+                         aProgress, currentDif);
+        iTotalProgress += currentDif;
+        IAUPDATE_TRACE_1("[IAUPDATE] New total current. Dif: %d", iTotalProgress);
+        }
+
+    iCurrentProgress = aProgress;
+    iCurrentMaxProgress = aMaxProgress;
+    if ( iCurrentProgress > iCurrentMaxProgress )
+        {
+        // A sanity check to be sure that max progress is at least as great as the
+        // current progress.
+        IAUPDATE_TRACE("[IAUPDATE] Progress was greater than max progress.");
+        iCurrentMaxProgress = iCurrentProgress;
+        }
+
+    if ( iCurrentMaxProgress > iTotalMaxProgress )
+        {
+        // It seems that the total max progress has been set to too little value.
+        // Update it to match the given data.
+        iTotalMaxProgress = iCurrentMaxProgress;
+        IAUPDATE_TRACE_1("[IAUPDATE] Current max greater than total max: %d", 
+                         iTotalMaxProgress);
+        }
+
+    if ( iTotalProgress > iTotalMaxProgress )
+        {
+        // It seems that the total max progress has been set to too little value.
+        // Update it to match the possible pending progress.
+        iTotalMaxProgress = iTotalProgress + iCurrentMaxProgress - iCurrentProgress; 
+        IAUPDATE_TRACE_1("[IAUPDATE] New total max: %d", iTotalMaxProgress);
+        }
+
+    IAUPDATE_TRACE("[IAUPDATE] Progress updated. Call observer.");
+    iObserver->ContentOperationProgress( 
+        *iCurrentNode, iTotalProgress, iTotalMaxProgress );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::UpdateProgress() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::CompleteOperation
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::CompleteOperation( TInt aError )
+    {
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CompleteOperation() begin: %d",
+                     aError);
+
+    // First do service pack related checks and settings.
+    if ( IsServicePack( *iNode ) )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Head node is service pack");
+        // Because node is a service pack, the error code that will be 
+        // returned to observer needs to be checked. Notice, that if
+        // an error occurred, then purchase history already contains
+        // correct error code for the service pack. If everything was
+        // a success, then update purchase history for the main service
+        // pack. UI may use that function to get the last error value if
+        // necessary. But, use KErrNone for callback parameter in all the 
+        // cases. Then, the value suggests that UI may try to continue
+        // the update flow.
+        // Notice, here we also check self updates because they should be
+        // handled from the UI before other items, such as service packs
+        // are handled.
+        if ( CheckNode( *iNode, ETrue ) )
+            {
+            IAUPDATE_TRACE("[IAUPDATE] Service pack thought as success");
+            // Because no error occurred, the service pack error code
+            // has not been yet set to the purchase history. So, it
+            // needs to be set now.
+            aError = KErrNone;
+            UpdatePurchaseHistory( *iNode, aError );
+            }
+        else if ( iSuccessCount > 0 )
+            {
+            IAUPDATE_TRACE("[IAUPDATE] Some of operations were success");
+            // If at least one item was successfully handled,
+            // then return KErrNone in the callback function.
+            // So, observer knows that update flow may continue
+            // at least for some items.
+            aError = KErrNone;
+            }
+        else
+            {
+            IAUPDATE_TRACE("[IAUPDATE] All item operations failed.");
+            // All operations that were tried at this operation flow were failures.
+            // Notice, that in preivous flows something may have been completed
+            // but not now. So, set the current error code for the callback.
+            // Here, use the function that gives the decoded error value
+            // of the error that has been saved to purchase history for the
+            // service pack.
+            // The parameter value of aError is not accepted
+            // because it may not give the service pack specific error
+            // but, for example, the skip error of dependency chain skips.
+            TRAPD ( trapError, 
+                    aError = iNode->LastUpdateErrorCodeL() );
+            if ( trapError != KErrNone )
+                {
+                IAUPDATE_TRACE_1("[IAUPDATE] Trap error: %d", trapError);
+                // Something failed with the error code. Maybe out of memory.
+                // So, use the trapError after this.
+                aError = trapError;
+                }
+            else if ( aError == KErrNone )
+                {
+                IAUPDATE_TRACE("[IAUPDATE] Change error to KErrGeneral");
+                // Use KErrGeneral as default if the correct
+                // error code can not be gotten from the history.
+                // Also, we do not return the possible trapError.
+                // Instead, in this case, just give a vague error.
+                aError = KErrGeneral;
+
+                // Because error code was read from the history successfully
+                // to aError but it was KErrNone, try to update the history
+                // also here with the KErrGeneral.
+                UpdatePurchaseHistory( *iNode, aError );
+                }
+            }
+        }
+
+    // Reset and set everything before calling observer complete because
+    // the observer may delete this object immediately. So, take temporary
+    // information for the function call.
+    MIAUpdateContentOperationObserver* tmpObserver( iObserver );
+    CIAUpdateNode* tmpNode( iNode );    
+    
+    // Observer is not needed anymore
+    iObserver = NULL;    
+
+    // No need for the operation anymore.
+    delete iOperation;
+    iOperation = NULL;
+
+    // Reset the array because operations will not continue.
+    iNodes.Reset();
+
+    // Node not needed anymore.
+    iNode = NULL;
+    iCurrentNode = NULL;
+
+    // Inform the observer about the completion of the operation. 
+    // Give the main node as a parameter.
+    tmpObserver->ContentOperationComplete( *tmpNode, aError );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CompleteOperation() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::ResetProgress
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::ResetProgress()
+    {
+    ResetCurrentProgress();
+    iTotalMaxProgress = KInitProgress;
+    iTotalProgress = KInitProgress;
+    }
+
+    
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::ResetCurrentProgress
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::ResetCurrentProgress()
+    {
+    iCurrentMaxProgress = KInitProgress;
+    iCurrentProgress = KInitProgress;    
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::InitTotalMaxProgressL
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::InitTotalMaxProgressL( 
+    const CIAUpdateContentOperationManager::TContentOperationType& aOperationType )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::InitTotalMaxProgressL() begin");
+                     
+    // For download operation use the given content size for expected progress values.
+    // For other operations just use the node count.
+    if ( aOperationType == CIAUpdateContentOperationManager::EDownloadOperation )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Download operation");
+        // Notice, that here we do not want to include already downloaded 
+        // or installed nodes into the total contant size.
+        iTotalMaxProgress = 
+            ArrayTotalContentSizeL( iNodes, EFalse, EFalse );
+        }
+    else
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Not download operation");
+        iTotalMaxProgress = iNodes.Count();        
+        }
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::InitTotalMaxProgressL() end: %d",
+                     iTotalMaxProgress);
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::ArrayTotalContentSizeL
+// 
+// ---------------------------------------------------------------------------
+//     
+TInt CIAUpdateContentOperationManager::ArrayTotalContentSizeL( 
+    const RPointerArray< CIAUpdateNode >& aNodes,
+    TBool aIncludeDownloaded,
+    TBool aIncludeInstalled )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNode::ArrayTotalContentSizeL() begin");
+
+    TInt totalContentSize( 0 );
+
+    TInt count( aNodes.Count() );
+    IAUPDATE_TRACE_1("[IAUPDATE] Node count: %d", count);
+    for ( TInt i = 0; i < count; ++i )
+        {
+        CIAUpdateNode& node( *aNodes[ i ] );
+        TBool skipNode( !aIncludeDownloaded && node.IsDownloaded()
+                        || !aIncludeInstalled && node.IsInstalled()
+                        || IsServicePack( node ) );
+        if ( !skipNode )
+            {
+            IAUPDATE_TRACE_1("[IAUPDATE] Node accepted: %d", i);
+            totalContentSize += node.OwnContentSizeL();           
+            }
+        }
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNode::ArrayTotalContentSizeL() end: %d",
+                     totalContentSize);
+
+    return totalContentSize;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::SetNodeArrayL
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::SetNodeArrayL( CIAUpdateNode& aNode )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::SetNodeArrayL() begin");
+    
+    // Reset and put required nodes into the node array.
+    // Only accept hidden dependency nodes. Skip visible nodes.
+    GetOperationNodesL( aNode, iNodes, ETrue, EFalse );
+
+    // Sort the created node array according to the
+    // node depths. This way the operation can just use the
+    // last node and there is no need to check dependencies
+    // because the leaf nodes are in the end of the array after sorting.
+    // This provides some what optimized way to handle things later.
+    // Also, note that here trust that no loops will be in the dependency
+    // chains. If loops may occur, then the depths of the nodes may not be
+    // correct because in a loop there is now way to decide what is first and
+    // what is last.
+    SortNodeArray( iNodes );
+
+    // Ownership is not taken.
+    iNode = &aNode;
+    iCurrentNode = NULL;
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::SetNodeArrayL() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::HandleDependenciesL
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::HandleDependenciesL( 
+    const CIAUpdateNode& aNode,
+    RPointerArray< CIAUpdateNode >& aNodes,
+    TBool aAcceptHiddenDependencyNodes,
+    TBool aAcceptVisibleDependencyNodes )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::HandleDependenciesL() begin");
+    
+    if ( !aAcceptHiddenDependencyNodes && !aAcceptVisibleDependencyNodes
+         || aNodes.Find( &aNode ) != KErrNotFound )
+        {
+        // Nothing is accepted. So, no need to do anything.
+        // Or the node has already been inserted into the array, which means that
+        // branch has already been handled.
+        IAUPDATE_TRACE("[IAUPDATE] Nothing to do for this branch");
+        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::HandleDependenciesL() end");
+        return;
+        }
+
+    // Insert all the required nodes into the array.
+    // Here we know, that the given node should be inserted into the array.
+    aNodes.AppendL( &aNode );
+
+    // Create temporary array for the nodes that current node depends on.
+    RPointerArray< CIAUpdateNode > dependencyNodes;
+    CleanupClosePushL( dependencyNodes );
+
+    // Get nodes that this node depends on into the temporary list.
+    aNode.GetDependencyNodesL( dependencyNodes, ETrue );
+    for ( TInt i = 0; i < dependencyNodes.Count(); ++i )
+        {
+        CIAUpdateNode& node( *dependencyNodes[ i ] );
+        if ( aAcceptHiddenDependencyNodes && node.Hidden() 
+             || aAcceptVisibleDependencyNodes && !node.Hidden() )
+            {
+            // Because node fills the criteria, handle the tree below it
+            // to get all the nodes of the dependencies.
+            HandleDependenciesL( node, aNodes, 
+                                 aAcceptHiddenDependencyNodes, 
+                                 aAcceptVisibleDependencyNodes );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &dependencyNodes );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::HandleDependenciesL() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::CreateOperationL
+// 
+// ---------------------------------------------------------------------------
+// 
+MIAUpdateOperation* CIAUpdateContentOperationManager::CreateOperationL(
+    const CIAUpdateContentOperationManager::TContentOperationType& aOperationType,
+    CIAUpdateNode& aNode )
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationL() begin");
+    
+    if ( IsServicePack( aNode ) )
+        {
+        // Because node is a service pack, no operations are
+        // created for it. So, just return the NULL value.
+        IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationL() end: NULL");
+        return NULL;
+        }
+
+    MIAUpdateOperation* operation( NULL );
+
+    switch ( aOperationType )
+        {
+        case EPurchaseOperation:
+            operation = 
+                CIAUpdatePurchaseOperation::NewL( aNode, *this );
+            break;
+
+        case EDownloadOperation:
+            if ( IsServicePack( *iNode ) && !aNode.IsPurchased() )
+                {
+                // Already previous operation has failed.
+                // So, skip the operation for this node.
+                IAUPDATE_TRACE("[IAUPDATE] Skip download because not purhcased, KErrSkipNode"); 
+                User::Leave( IAUpdateCtrlNodeConsts::KErrSkipNode );
+                }
+            operation = 
+                CIAUpdateDownloadOperation::NewL( aNode, *this );
+            break;
+
+        case EInstallOperation:
+            if ( IsServicePack( *iNode ) && !aNode.IsDownloaded() )
+                {
+                // Already previous operation has failed.
+                // So, skip the operation for this node.
+                IAUPDATE_TRACE("[IAUPDATE] Skip install because not downloaded, KErrSkipNode"); 
+                User::Leave( IAUpdateCtrlNodeConsts::KErrSkipNode );
+                } 
+            if ( aNode.IsSelfUpdate() )
+                {
+                operation = 
+                    CIAUpdateSelfUpdateInitOperation::NewL( aNode, *this );
+                }
+            else
+                {
+                operation = 
+                    CIAUpdateInstallOperation::NewL( aNode, *this );
+                }
+            break;
+
+        case ENoContentOperation:
+            // Let it be NULL.
+            // Should not ever come here.
+            break;
+
+        default:
+            // Let it be NULL.
+            // Should not ever come here.
+            User::Leave( KErrNotSupported );
+            break;
+        }
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationL() end");
+
+    return operation;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::UpdatePurchaseHistory
+// 
+// ---------------------------------------------------------------------------
+// 
+void CIAUpdateContentOperationManager::UpdatePurchaseHistory( 
+    CIAUpdateNode& aNode, TInt aError ) const
+    {
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::UpdatePurchaseHistory() begin: %d",
+                     aError);
+
+    if ( IsServicePack( aNode ) )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Is service pack");
+        // Because NCD API does not provide means to update the purchase details
+        // type, it is always EStatePurchased. So, here we edit the error code.
+        // Later, by checking the base code of the error, the correct operation
+        // can be concluded.
+        switch ( iOperationType )
+            {
+            case EDownloadOperation:
+                IAUPDATE_TRACE("[IAUPDATE] Download operation");    
+                aError += IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload;
+                break;
+
+            case EInstallOperation:
+                IAUPDATE_TRACE("[IAUPDATE] Install operation");
+                aError += IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall;
+                break;
+
+            default:
+                // For purchase operations just use the default value.
+                IAUPDATE_TRACE("[IAUPDATE] Default");
+                break;
+            }
+        }
+
+    // In normal cases, just update the history error value.
+    // If service pack is handled, then the error code is edited above
+    // to make it a correct value.
+    IAUPDATE_TRACE_1("[IAUPDATE] Set error to history: %d", aError);
+    TRAP_IGNORE ( aNode.SetIdleErrorToPurchaseHistoryL( aError, EFalse ) );
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::UpdatePurchaseHistory() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::IsServicePack
+// 
+// ---------------------------------------------------------------------------
+// 
+TBool CIAUpdateContentOperationManager::IsServicePack( 
+    const CIAUpdateNode& aNode )
+    {
+    return ( aNode.Type() == MIAUpdateNode::EPackageTypeServicePack );
+    }
+
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::SetCurrentNodeL
+// 
+// ---------------------------------------------------------------------------
+//
+void CIAUpdateContentOperationManager::SetCurrentNodeL()
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager:SetCurrentNodeL() begin");
+    
+    // Take the node from the end of the array because root of the dependency
+    // hierarchy starts from the beginning of the array and leaves are in the end.
+    TInt index( iNodes.Count() - 1 );
+    iCurrentNode = iNodes[ index ];
+    iNodes.Remove( index );
+
+    // In case of service packs an error does not complete the whole operation chain. 
+    // So, check here if some nodes need to be skipped because their dependencies are 
+    // not operated correctly.
+    // Also, this check is needed if UI tries to operate nodes whose dependencies
+    // were not handled successfully before.
+
+    IAUPDATE_TRACE("[IAUPDATE] Current node is not service pack");
+
+    RPointerArray< CIAUpdateNode > dependencies;
+    CleanupClosePushL( dependencies );
+
+    iCurrentNode->GetDependencyNodesL( dependencies, ETrue );
+
+    // Check all the dependencies.
+    for ( TInt i = 0; i < dependencies.Count(); ++i )
+        {
+        CIAUpdateNode& dependency( *dependencies[ i ] );
+        if ( !CheckNode( dependency, EFalse ) )
+            {
+            // In normal cases, the flow will be immediately completed 
+            // if error occurs. If we come here it means that the operation
+            // has still been continued and we are handling a service pack.
+            // Because the dependency node is reason of the error for this leaf,
+            // leave here with the specified skip error. So, later
+            // we know that the reason of the leave is this skip.
+            IAUPDATE_TRACE("[IAUPDATE] Error: KErrSkipNode");
+            User::Leave( IAUpdateCtrlNodeConsts::KErrSkipNode );
+            }
+        }
+
+    CleanupStack::PopAndDestroy( &dependencies );        
+
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager:SetCurrentNodeL() end");
+    }
+
+
+// ---------------------------------------------------------------------------
+// CIAUpdateContentOperationManager::CheckNode
+// 
+// ---------------------------------------------------------------------------
+//
+TBool CIAUpdateContentOperationManager::CheckNode( 
+    const CIAUpdateNode& aNode,
+    TBool aCheckSelfUpdate ) const
+    {
+    IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CheckNode() begin");
+
+    TBool checkPassed( EFalse );
+
+    if ( aNode.Hidden() )
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Dependency node is hidden");
+        // In service packs and in hidden dependency chains, update flow goes 
+        // so that same operation is done to all of the items in that dependency
+        // chain before continuing to another type of operation.
+        // So, check accordingly.
+        switch ( iOperationType )
+            {
+            case EPurchaseOperation:
+                if ( aNode.IsPurchased()
+                     || aNode.IsDownloaded() 
+                     || aNode.IsInstalled() )
+                    {
+                    // Notice, item may be in more advanced state
+                    // than is required at the moment. If operations
+                    // have been done from somewhere else. For example,
+                    // content may have been installed outside of IAD.
+                    checkPassed = ETrue;
+                    }
+                break;
+            
+            case EDownloadOperation:
+                if ( aNode.IsDownloaded() 
+                     || aNode.IsInstalled() )
+                    {
+                    // Notice, item may be in more advanced state
+                    // than is required at the moment. If operations
+                    // have been done from somewhere else. For example,
+                    // content may have been installed outside of IAD.
+                    checkPassed = ETrue;
+                    }
+                break;
+                
+            case EInstallOperation:
+                if ( !aCheckSelfUpdate && aNode.IsSelfUpdate() )
+                    {
+                    IAUPDATE_TRACE("[IAUPDATE] Always accept self update during install");
+                    checkPassed = ETrue;
+                    }
+                else
+                    {
+                    checkPassed = aNode.IsInstalled();
+                    }
+                break;
+
+            case ENoContentOperation:
+                break;
+                
+            default:
+                break;
+            }        
+        }
+    else
+        {
+        IAUPDATE_TRACE("[IAUPDATE] Dependency node is visible");
+        // Because dependency node is some visible node, it should have been
+        // installed before the update flow of this node has been started.
+        // So, if dependency node is not installed, then check will fail.
+        if ( !aCheckSelfUpdate && aNode.IsSelfUpdate() )
+            {
+            IAUPDATE_TRACE("[IAUPDATE] Always accept self update during install");
+            checkPassed = ETrue;
+            }
+        else
+            {
+            checkPassed = aNode.IsInstalled();
+            }
+        }
+
+
+    IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckNode() end: %d",
+                     checkPassed);
+
+    return checkPassed;
+    }
+