iaupdate/IAD/engine/controller/src/iaupdatenodecontainer.cpp
changeset 0 ba25891c3a9e
child 2 661f3784fe57
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:   ?Description
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include "iaupdatenodecontainer.h"
       
    21 
       
    22 #include "iaupdatecontrollerimpl.h"
       
    23 #include "iaupdatecontentoperationmanager.h"
       
    24 #include "iaupdatenodeimpl.h"
       
    25 #include "iaupdatefwnodeimpl.h"
       
    26 #include "iaupdatenodedetails.h"
       
    27 #include "iaupdatenodedependencyimpl.h"
       
    28 #include "iaupdateplatformdependency.h"
       
    29 #include "iaupdateutils.h"
       
    30 #include "iaupdatenodefactory.h"
       
    31 
       
    32 #include "iaupdatedebug.h"
       
    33 
       
    34 
       
    35 // Constant that is used to inform that dependency node
       
    36 // was not found when dependencies were checked.
       
    37 const TInt KDependencyNotFound( -1 );
       
    38 
       
    39 
       
    40 CIAUpdateNodeContainer* CIAUpdateNodeContainer::NewLC(
       
    41     CIAUpdateController& aController )
       
    42     {
       
    43     CIAUpdateNodeContainer *self = 
       
    44         new (ELeave) CIAUpdateNodeContainer( aController );
       
    45     CleanupStack::PushL( self );
       
    46     self->ConstructL();
       
    47     return self;
       
    48     }
       
    49     
       
    50 CIAUpdateNodeContainer* CIAUpdateNodeContainer::NewL(
       
    51     CIAUpdateController& aController )
       
    52     {    
       
    53     CIAUpdateNodeContainer *self = 
       
    54         CIAUpdateNodeContainer::NewLC( aController );
       
    55     CleanupStack::Pop( self );
       
    56     return self;
       
    57     }
       
    58 
       
    59     
       
    60 CIAUpdateNodeContainer::CIAUpdateNodeContainer(
       
    61     CIAUpdateController& aController )
       
    62 : CBase(),
       
    63   iController( aController )
       
    64     {
       
    65     }
       
    66 
       
    67 void CIAUpdateNodeContainer::ConstructL()
       
    68     {
       
    69     }
       
    70 
       
    71         
       
    72 CIAUpdateNodeContainer::~CIAUpdateNodeContainer()
       
    73     {
       
    74     Clear();
       
    75     }    
       
    76     
       
    77     
       
    78 void CIAUpdateNodeContainer::AddNodeL( CIAUpdateNode* aNode )
       
    79     {
       
    80     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddNodeL() begin");
       
    81     
       
    82     if ( !aNode )
       
    83         {
       
    84         // Null is not acceptable
       
    85         IAUPDATE_TRACE("[IAUPDATE] LEAVE: Node null");
       
    86         User::Leave( KErrArgument );
       
    87         }
       
    88 
       
    89     CleanupStack::PushL( aNode );
       
    90 
       
    91     IAUPDATE_TRACE("[IAUPDATE] Check if node is acceptable");
       
    92     if ( !NodeAlreadyExists( *aNode )
       
    93          && aNode->Details().PlatformDependency().AcceptablePlatformL()
       
    94          && InstallCheckL( *aNode ) 
       
    95          && !aNode->Details().EmbededDegrades()
       
    96          && PackageTypeAcceptedL( *aNode ) )
       
    97         {
       
    98         IAUPDATE_TRACE("[IAUPDATE] Node accepted. Add into the node array.");
       
    99 
       
   100         // The node list will contain nodes 
       
   101         // that can be downloaded and installed.
       
   102         // The header node list will provide 
       
   103         // most recent version of the content.
       
   104 
       
   105         // The ownership of the node transfers.
       
   106         // So try to append it into the array.
       
   107         // If node can not be added into the array, 
       
   108         // it will be deleted when appending leaves.
       
   109         iNodes.AppendL( aNode );
       
   110         // Appending was successfull. 
       
   111         // So, ownership has been transferred successfully.
       
   112         CleanupStack::Pop( aNode );
       
   113         }
       
   114     else
       
   115         {
       
   116         IAUPDATE_TRACE("[IAUPDATE] Node not accepted. Delete it.");
       
   117         
       
   118         // Because the node is not deployable 
       
   119         // or it was for the wrong platform, 
       
   120         // there is no use for it. Delete the node.
       
   121         CleanupStack::PopAndDestroy( aNode );
       
   122         }
       
   123 
       
   124     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddNodeL() end");
       
   125     }
       
   126 
       
   127 
       
   128 void CIAUpdateNodeContainer::AddExcessNodeL( CIAUpdateNode* aNode )
       
   129     {
       
   130     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddExcessNodeL() begin");
       
   131     
       
   132     if ( aNode == NULL )
       
   133         {
       
   134         // Null is not acceptable
       
   135         IAUPDATE_TRACE("[IAUPDATE] LEAVE: NULL node");
       
   136         User::Leave( KErrArgument );
       
   137         }
       
   138 
       
   139     // The node list will contain nodes that do not belong to any other
       
   140     // node category.
       
   141      
       
   142     // The ownership of the node transfers.
       
   143     // So try to append it into the array.
       
   144     CleanupStack::PushL( aNode );
       
   145     iExcessNodes.AppendL( aNode );
       
   146     CleanupStack::Pop( aNode );
       
   147 
       
   148     // Force the node to be hidden.
       
   149     aNode->ForceHidden( ETrue );
       
   150         
       
   151     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddExcessNodeL() end");
       
   152     }
       
   153 
       
   154 
       
   155 void CIAUpdateNodeContainer::AddFwNodeL( CIAUpdateFwNode* aNode )
       
   156     {
       
   157     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddFwNodeL() begin");
       
   158 
       
   159     if ( !aNode )
       
   160         {
       
   161         // Null is not acceptable
       
   162         IAUPDATE_TRACE("[IAUPDATE] LEAVE: Node null");
       
   163         User::Leave( KErrArgument );
       
   164         }
       
   165 
       
   166     CleanupStack::PushL( aNode );
       
   167 
       
   168     iFwNodes.AppendL( aNode );
       
   169 
       
   170     CleanupStack::Pop( aNode );
       
   171         
       
   172     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::AddFwNodeL() end");
       
   173     }
       
   174 
       
   175 
       
   176 void CIAUpdateNodeContainer::Clear()
       
   177     {
       
   178     // Just reset this list because all the nodes 
       
   179     // are owned by the iNodes list.
       
   180     iHeadNodes.Reset();
       
   181     
       
   182     // Reset the list and delete the nodes.
       
   183     iNodes.ResetAndDestroy();
       
   184 
       
   185     // Reset the list and delete the nodes.    
       
   186     iExcessNodes.ResetAndDestroy();
       
   187 
       
   188     // Reset the list and delete the nodes.
       
   189     iFwNodes.ResetAndDestroy();
       
   190     }
       
   191 
       
   192 
       
   193 const RPointerArray< CIAUpdateNode >& CIAUpdateNodeContainer::AllNodes() const
       
   194     {
       
   195     return iNodes;
       
   196     }
       
   197 
       
   198 
       
   199 const RPointerArray< CIAUpdateNode >& CIAUpdateNodeContainer::ExcessNodes() const
       
   200     {
       
   201     return iExcessNodes;
       
   202     }
       
   203     
       
   204     
       
   205 const RPointerArray< CIAUpdateNode >& CIAUpdateNodeContainer::HeadNodesL()
       
   206     {
       
   207     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HeadNodesL() begin");
       
   208     
       
   209     // Make sure that dependencies are correct. 
       
   210     // Notice, that here the dependencies are checked for all the nodes 
       
   211     // in the node list. So, some dependencies that may not be required 
       
   212     // are also checked. (Unnecessary dependency checks can exist, for example, 
       
   213     // if the server sends multiple update packets for a same content version.)
       
   214     // But, checking of dependencies first makes it easier to find correct header 
       
   215     // nodes later because we can be sure that all the nodes have intact dependency 
       
   216     // chains then. Also, notice that this function will set the information about 
       
   217     // the dependency checks into the nodes and remove nodes, whose dependencies
       
   218     // are broken, from the list.
       
   219     UpdateDependenciesL();
       
   220 
       
   221     // Create the header node list and remove nodes 
       
   222     // whose dependency chains are broken.
       
   223     ManageHeaderNodesL();
       
   224 
       
   225     // Create the dependecy for self update nodes 
       
   226     // and mark selfupdater and ncd hidden.
       
   227     // RemoveHiddenNodesFromHeadList will handle those nodes 
       
   228     // after they have been marked hidden.
       
   229     CreateSelfUpdateBundleL();
       
   230 
       
   231     // This will set the service pack dependency nodes as hidden.
       
   232     HandleServicePacksL();
       
   233 
       
   234     // Bundles may contain nodes that are head nodes
       
   235     // but have been marked hidden.
       
   236     // So, remove hidden nodes from the head list. 
       
   237     // Hidden nodes should be visible to UI.
       
   238     RemoveHiddenNodesFromHeadList();
       
   239         
       
   240     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HeadNodesL() end");
       
   241     
       
   242     return iHeadNodes;
       
   243     }
       
   244 
       
   245 
       
   246 const RPointerArray< CIAUpdateFwNode >& CIAUpdateNodeContainer::FwNodes()
       
   247     {
       
   248     return iFwNodes;    
       
   249     }
       
   250 
       
   251 
       
   252 void CIAUpdateNodeContainer::UpdateDependenciesL()
       
   253     {
       
   254     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateDependenciesL() begin");
       
   255 
       
   256     // Reset node statuses
       
   257     for ( TInt i = 0; i < iNodes.Count(); ++i )
       
   258         {
       
   259         iNodes[ i ]->Reset();
       
   260         }
       
   261     
       
   262     // Check and update the dependencies for all the nodes.
       
   263     // So, it will be checked that all the nodes can be installed correctly
       
   264     // and no dependencies for them are missing.
       
   265     for ( TInt i = 0; i < iNodes.Count(); ++i )
       
   266         {
       
   267         // If the node dependency status has already been set, 
       
   268         // then it was already checked in some previous loop 
       
   269         // or recursion of dependency check. So, do not recheck 
       
   270         // the same branch here. Notice, the DependencyCheckStatus is 
       
   271         // also checked in the recursion in UpdateNodeDependenciesL. 
       
   272         // So, recheck should not even be allowed here. Otherwise checks
       
   273         // will fail unless the statuses are resetted before.
       
   274         // If the state has not been set, then check the branch.
       
   275         CIAUpdateNode& node( *iNodes[ i ] );
       
   276         if ( node.DependencyCheckStatus() 
       
   277              == CIAUpdateNode::EDependencyCheckNotSet )
       
   278             {
       
   279             // Notice, that this function sets the dependency check status 
       
   280             // for the node and to the nodes belonging to that branch in 
       
   281             // its dependency tree.
       
   282             UpdateNodeDependenciesL( node, 0 );
       
   283             }        
       
   284         }
       
   285 
       
   286     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateDependenciesL() end");
       
   287     }
       
   288 
       
   289     
       
   290 TInt CIAUpdateNodeContainer::UpdateNodeDependenciesL( 
       
   291     CIAUpdateNode& aNode, TInt aDepth )
       
   292     {
       
   293     IAUPDATE_TRACE_2("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() begin: %S, %S",
       
   294                      &aNode.MetaNamespace(), &aNode.MetaId());
       
   295 
       
   296     // Notice that this function creates a recursive loop together with 
       
   297     // FindBestMatchL function.
       
   298 
       
   299     // Check if we have already handled this node and dependency loops back to it.
       
   300     // If node check is already going on for the node, then there is loop in dependency.
       
   301     // Do not accept loops for dependencies. If no loop, then continue normally. 
       
   302     // Notice, that if we loop here, other sub branches may have not been
       
   303     // checked for this node yet. So, only set the status when the whole subtree has
       
   304     // been checked.
       
   305 
       
   306     if ( aNode.DependencyCheckStatus() 
       
   307          == CIAUpdateNode::EDependencyCheckNotSet )
       
   308         {
       
   309         IAUPDATE_TRACE("[IAUPDATE] Dependency check not set yet");
       
   310 
       
   311         // Gives the total leaf distance of this part of the dependency tree. 
       
   312         // The tallest branch gives the total leaf distance.    
       
   313         TInt totalLeafDistance( KDependencyNotFound );
       
   314 
       
   315         // Mark the check state here to prevent loops.
       
   316         aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckGoing );
       
   317         
       
   318         RPointerArray< CIAUpdateNodeDependency > deps;
       
   319         CleanupClosePushL( deps );
       
   320                 
       
   321         // Get dependency objects from aNode into the deps array.
       
   322         // Get dependencies that were gotten from the server.
       
   323         aNode.Details().GetDependenciesL( deps );
       
   324 
       
   325         // Now, that we have the dependency information for the given node,
       
   326         // find the nodes that provide the best dependency branches.            
       
   327         for ( TInt i = 0; i < deps.Count(); ++i )
       
   328             {
       
   329             // The best branch is thought to be the branch that is the flattest.
       
   330             // FindBestMatchL function inserts the best match information 
       
   331             // to the dependency object. The best match information of the dependency 
       
   332             // will contain the possible node whose content is required 
       
   333             // for the dependency chain to be complete. Also, that node may need other nodes. 
       
   334             // So, the dependency branch may continue there.
       
   335             // Dependency depth is one greater than the depth of dependant aNode.
       
   336             TInt leafDistance( 
       
   337                 FindBestMatchL( aNode, *deps[ i ], aDepth + 1 ) );
       
   338 
       
   339             // Notice, that here we are looking for the total leaf distance for this branch.
       
   340             // FindBestMatchL -function that is used above will use this value to check 
       
   341             // what branch has the shortes totalLeafDistance. 
       
   342             // The branch that is flattest will be chosen for the current parent node.
       
   343             if ( leafDistance == KDependencyNotFound )
       
   344                 {
       
   345                 IAUPDATE_TRACE("[IAUPDATE] Dependency check failed");
       
   346 
       
   347                 // Because dependency was not found from the node list or from 
       
   348                 // the installed applications, the node dependency chain is broken.
       
   349                 // Set this information into the node.
       
   350                 // So, this node will be removed from the node list later.
       
   351                 aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckFailed );
       
   352                     
       
   353                 // Because, one missing item is enough to break the chain, just return here.
       
   354                 // If other nodes are required, they are checked separately later in their own
       
   355                 // checkings. The chain break affects all the nodes that depend on this one. So,
       
   356                 // this information will be set to the nodes, when the recursion goes back.
       
   357                 CleanupStack::PopAndDestroy( &deps );
       
   358 
       
   359                 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: KDependencyNotFound");
       
   360 
       
   361                 return KDependencyNotFound;            
       
   362                 }
       
   363              else if ( totalLeafDistance < leafDistance )
       
   364                 {
       
   365                 IAUPDATE_TRACE_2("[IAUPDATE] Replace old totalLeafDistance %d, %d",
       
   366                                  totalLeafDistance, leafDistance);
       
   367                 // Set the total leaf distance of this part of the dependency chain because
       
   368                 // the chain is intact.
       
   369                 totalLeafDistance = leafDistance;
       
   370                 }            
       
   371             }
       
   372             
       
   373         CleanupStack::PopAndDestroy( &deps );
       
   374 
       
   375         // Dependency chain for the node is intact.
       
   376         // Set this information into the node.    
       
   377         aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckPassed );
       
   378         IAUPDATE_TRACE("[IAUPDATE] EDependencyCheckPassed");
       
   379 
       
   380         // Add one, so the parent will get its own actual leaf distance in return.
       
   381         ++totalLeafDistance;
       
   382         
       
   383         // Also, set the total leaf distance for the node.
       
   384         aNode.SetLeafDistance( totalLeafDistance );
       
   385 
       
   386 
       
   387         IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: %d",
       
   388                          totalLeafDistance);
       
   389         
       
   390         return totalLeafDistance;    
       
   391         }
       
   392     else if ( aNode.DependencyCheckStatus()
       
   393               == CIAUpdateNode::EDependencyCheckPassed )
       
   394         {
       
   395         IAUPDATE_TRACE("[IAUPDATE] Dependency check already passed");
       
   396         
       
   397         // Because this node and the hierarchy below it has already been handled,
       
   398         // check if the depth of the node and its dependency hierarchy should be
       
   399         // updated with the new value. 
       
   400         aNode.UpdateDependencyDepthsL( aDepth );
       
   401 
       
   402         // Because we have already handled this branch successfully,
       
   403         // just return its own leaf distance information.
       
   404         IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: %d",
       
   405                          aNode.LeafDistance());
       
   406         return aNode.LeafDistance();
       
   407         }
       
   408     else if ( aNode.DependencyCheckStatus()
       
   409               == CIAUpdateNode::EDependencyCheckGoing )
       
   410         {
       
   411         IAUPDATE_TRACE("[IAUPDATE] Dependency loop has occurred");
       
   412         // Notice, we come here if there are loops in dependencies.
       
   413         // Looping dependency chains are not acceptable in normal cases.
       
   414         // Notice, in case of service packs, if another branch of service pack
       
   415         // is intact and it does not loop, then the service pack check status 
       
   416         // is set to CIAUpdateNode::EDependencyCheckPassed when the recursion 
       
   417         // is over above and all the branches of the service pack have been handled. 
       
   418         // Still loopin branches inside service pack will also be removed.
       
   419         aNode.SetDependencyCheckStatus( CIAUpdateNode::EDependencyCheckFailed );
       
   420         }
       
   421 
       
   422     // We come here if dependency check status has been set to 
       
   423     // CIAUpdateNode::EDependencyCheckFailed. So, then always 
       
   424     // return KDependencyNotFound to correspond that situation.
       
   425 
       
   426     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateNodeDependenciesL() end: KDependencyNotFound");
       
   427 
       
   428     return KDependencyNotFound;
       
   429     }
       
   430 
       
   431 
       
   432 TInt CIAUpdateNodeContainer::FindBestMatchL( CIAUpdateNode& aNode,
       
   433                                              CIAUpdateNodeDependency& aDependency,
       
   434                                              TInt aDependencyDepth )
       
   435     {
       
   436     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::FindBestMatchL() begin");
       
   437 
       
   438     // Notice that this function creates a recursive loop together with 
       
   439     // UpdateNodeDependenciesL function.
       
   440 
       
   441     // As a default, the dependency we are looking for is marked as not found.
       
   442     TInt totalLeafDistance( KDependencyNotFound );
       
   443 
       
   444     // Check if the dependency file has already been installed and get the version
       
   445     // of the application if it has been installed.
       
   446     TIAUpdateVersion installedVersion;
       
   447     TBool installed( 
       
   448         IAUpdateUtils::IsAppInstalledL( 
       
   449             aDependency.Uid(), installedVersion ) );
       
   450     
       
   451     if ( aDependency.IsEmbedded() )
       
   452         {
       
   453         IAUPDATE_TRACE("[IAUPDATE] Dependency is embedded in the node.");
       
   454         // If dependency node is already embedded into the package, then use it
       
   455         // instead of downloading it separately. Embedded dependencies are always
       
   456         // matched by the node itself. Embedded package has to be installed 
       
   457         // when content is installed, or the whole installation fails.
       
   458         // Best match for this dependency is the node content itself. But, 
       
   459         // to prevent loops, set the best match to NULL.
       
   460         aDependency.SetBestMatch( NULL );
       
   461 
       
   462         // If the embedded node will require downgrades, 
       
   463         // then do not accept this dependency. Notice, here we think 
       
   464         // that the embedded content version value is given as version roof value.
       
   465         // So, the installed version has to be equal or smaller than the roof value,
       
   466         // if the embedded content can be accepted.
       
   467         // Note for future improvements: 
       
   468         // When support is added for embedded sisx to have dependencies, 
       
   469         // this needs to be changed accordingly
       
   470         if ( !installed
       
   471              || installedVersion <= aDependency.VersionRoof() )
       
   472             {
       
   473             IAUPDATE_TRACE("[IAUPDATE] Embedded content can be installed");
       
   474             // Leaf distance is zero because embedded item is already part
       
   475             // of the node itself.
       
   476             totalLeafDistance = 0;           
       
   477             }
       
   478         }
       
   479     else
       
   480         {
       
   481         IAUPDATE_TRACE("[IAUPDATE] Dependency content is not embedded.");
       
   482 
       
   483         // Check here if the best matching content is already installed or if
       
   484         // content needs to be downloaded and installed
       
   485 
       
   486         // Note, that the dependency may also describe an update dependency
       
   487         // for the content instead of just describing that a content depends 
       
   488         // on another content. But, we can handle it all these cases in a same
       
   489         // way.
       
   490 
       
   491         // This value will be updated when the recursive call of 
       
   492         // UpdateNodeDependenciesL inside for-loop has found an acceptable leaf node. 
       
   493         // Then, recursion will come back of the tree hierarchy and find other branches 
       
   494         // and update this value if necessary.
       
   495         CIAUpdateNode* currentBestMatch( NULL );
       
   496 
       
   497         RPointerArray< CIAUpdateNode > matches;
       
   498         CleanupClosePushL( matches );
       
   499 
       
   500         // Find the nodes that fullfill the given dependency requirement.
       
   501         // Node list may contain multiple alternatives. 
       
   502         // So, first find the alternatives.
       
   503         // Notice, that this function skips already installed items.
       
   504         FindMatchesL( matches, aDependency );
       
   505 
       
   506         // Find the best match from the alternatives.
       
   507         for ( TInt i = 0; i < matches.Count(); ++i )
       
   508             {
       
   509             CIAUpdateNode& tmpNode( *matches[ i ] );
       
   510 
       
   511             // The node that matches can be part of the best dependency branch.
       
   512             // But, we still need to check the whole branch before we can be sure. 
       
   513             // So, check the dependency branch forward by using the recursion.
       
   514             TInt leafDistance( 
       
   515                 UpdateNodeDependenciesL( tmpNode, aDependencyDepth ) );
       
   516 
       
   517             // If no match has been handled so far, then the new one is best match.
       
   518             // If there is already a current best match, then check if the
       
   519             // new one should replace it.
       
   520             if ( leafDistance != KDependencyNotFound 
       
   521                  && ( totalLeafDistance == KDependencyNotFound 
       
   522                       || currentBestMatch 
       
   523                          && ReplaceRecommendedL( 
       
   524                                 *currentBestMatch, tmpNode ) ) )
       
   525                 {
       
   526                 IAUPDATE_TRACE("[IAUPDATE] New best match found.");
       
   527                 currentBestMatch = &tmpNode;
       
   528                 totalLeafDistance = leafDistance;
       
   529                 }
       
   530             }
       
   531         
       
   532         CleanupStack::PopAndDestroy( &matches );
       
   533 
       
   534         // Set the best match information for the dependency.
       
   535         // Notice, that if installedVersion equals the currentBestMatch version,
       
   536         // the node is set instead of NULL value. This way if a content in the
       
   537         // middle of the dependency chain is installed, the dependency way will
       
   538         // not be cut in that place.
       
   539         if ( installed
       
   540              && installedVersion >= aDependency.VersionFloor()
       
   541              && installedVersion <= aDependency.VersionRoof()
       
   542              && ( !currentBestMatch 
       
   543                   || installedVersion > currentBestMatch->Version() ) )
       
   544             {
       
   545             IAUPDATE_TRACE("[IAUPDATE] Best dependency content is already installed. Use it.");
       
   546             // The content was already installed and its version belonged 
       
   547             // to the required version range. Also, the installed version 
       
   548             // was greater than the version of other matches.
       
   549             // The best match was found, but it requires no nodes and their content.
       
   550             aDependency.SetBestMatch( NULL );
       
   551             totalLeafDistance = 0;
       
   552             }
       
   553         else
       
   554             {
       
   555             IAUPDATE_TRACE("[IAUPDATE] Use current best match item if available");
       
   556             // If currentBestMatch is not NULL, the best dependency node was found.
       
   557             // If currentBestMatch is NULL, the best dependency node was not found.
       
   558             // So, just set the best match information accordingly.
       
   559             aDependency.SetBestMatch( currentBestMatch );
       
   560             if ( currentBestMatch )
       
   561                 {
       
   562                 IAUPDATE_TRACE("[IAUPDATE] Current best match item is available");
       
   563 
       
   564                 // Notice, that UpdateNodeDependenciesL checks and prevents looping.
       
   565                 // So, no need to do it here. AddDependant now, that we found the
       
   566                 // best match. Notice, we only want to insert dependant information
       
   567                 // to the correct item not to possible choices. So, that is why we
       
   568                 // do it here, not inside the for-loop above.
       
   569                 currentBestMatch->AddDependantL( aNode );
       
   570 
       
   571                 // Because node depth has not been set yet, update it now.
       
   572                 // Notice, we update the depth here because then the depth
       
   573                 // will be updated only to the best match node. In other words, 
       
   574                 // the depth is updated only to the nodes that will be used.
       
   575                 // So, depths of other nodes that are skipped are not updated. 
       
   576                 // This way the depth information will be correct if different
       
   577                 // nodes required alternative dependency hierarchies from some
       
   578                 // content.
       
   579                 currentBestMatch->
       
   580                     UpdateDependencyDepthsL( aDependencyDepth );
       
   581                 }
       
   582             }
       
   583         }
       
   584 
       
   585     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::FindBestMatchL() end: %d",
       
   586                      totalLeafDistance);
       
   587             
       
   588     return totalLeafDistance;
       
   589     }
       
   590 
       
   591 
       
   592 void CIAUpdateNodeContainer::FindMatchesL( RPointerArray< CIAUpdateNode >& aNodes, 
       
   593                                            const CIAUpdateNodeDependency& aDependency )
       
   594     {
       
   595     // Find all the matching nodes from the node list.    
       
   596     for( TInt i = 0; i < iNodes.Count(); ++i )
       
   597         {
       
   598         CIAUpdateNode& node( *iNodes[ i ] );
       
   599         // Check if the node matches the given dependency.
       
   600         if( node.Uid() == aDependency.Uid() 
       
   601             && node.Version() >= aDependency.VersionFloor() 
       
   602             && node.Version() <= aDependency.VersionRoof()
       
   603             && InstallCheckL( node ) )
       
   604             {
       
   605             // Append the matching node into the given list.
       
   606             aNodes.AppendL( &node );
       
   607             }
       
   608         }
       
   609     }
       
   610 
       
   611 
       
   612 void CIAUpdateNodeContainer::ManageHeaderNodesL()
       
   613     {
       
   614     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ManageHeaderNodesL() begin");
       
   615 
       
   616     for ( TInt i = iNodes.Count() - 1; i >= 0; --i )
       
   617         {
       
   618         CIAUpdateNode& node( *iNodes[ i ] );
       
   619         if ( node.DependencyCheckStatus() 
       
   620              != CIAUpdateNode::EDependencyCheckPassed )
       
   621             {
       
   622             // The node dependency chain has either failed 
       
   623             // or the nodes are not needed
       
   624             // because their dependency status has not been set.
       
   625             // So, remove these nodes from the node list.
       
   626             IAUPDATE_TRACE_2("[IAUPDATE] Node dependency chain broken or node not needed: %S, %S",
       
   627                              &node.MetaNamespace(), &node.MetaId());
       
   628             delete iNodes[ i ];
       
   629             iNodes[ i ] = NULL;
       
   630             iNodes.Remove( i );
       
   631             }
       
   632         else
       
   633             {
       
   634             // Notice, that dependencies have been handled 
       
   635             // for every item previously. So, now we can choose 
       
   636             // the header nodes whose dependencies are intact. 
       
   637             // Update the header list to contain newer version 
       
   638             // of nodes whose contents have not been installed yet.
       
   639             UpdateHeadNodeListL( node );                        
       
   640             }
       
   641         }    
       
   642         
       
   643     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ManageHeaderNodesL() end");
       
   644     }
       
   645     
       
   646 
       
   647 void CIAUpdateNodeContainer::UpdateHeadNodeListL( CIAUpdateNode& aNode )
       
   648     {
       
   649     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateHeadNodeListL() begin");
       
   650     
       
   651     // All nodes that are not installed yet are possible head nodes.
       
   652     // The final list will contain head nodes that are most recent 
       
   653     // versions of nodes that can be downloaded and/or installed.
       
   654     
       
   655     if( !aNode.IsInstalled() )
       
   656         {
       
   657         IAUPDATE_TRACE("[IAUPDATE] Not installed yet.");
       
   658 
       
   659         // Only consider the highest version of nodes as head nodes.
       
   660 
       
   661         // This flag informs if the node should be appended into the list
       
   662         // because it was not inserted in the for-loop
       
   663         // or if the correct node was already in the list.
       
   664         TBool alreadyIncluded( EFalse );
       
   665         
       
   666         for ( TInt i = 0; i < iHeadNodes.Count(); ++i )
       
   667             {
       
   668             CIAUpdateNode& tmpNode( *iHeadNodes[ i ] );            
       
   669             if( aNode.Uid() == tmpNode.Uid() && aNode.Type() != MIAUpdateNode::EPackageTypeServicePack ) //MTA: Changed!!!
       
   670                 {
       
   671                 IAUPDATE_TRACE("[IAUPDATE] Head node already in the list.");
       
   672                 
       
   673                 // Node for the corresponding content already exists in the list.
       
   674                 // Replace node from the list if the new node is better choice.
       
   675                 if ( ReplaceRecommendedL( tmpNode, aNode ) )
       
   676                     {
       
   677                     IAUPDATE_TRACE("[IAUPDATE] Replace existing head node");
       
   678                     iHeadNodes[ i ] = &aNode;
       
   679                     // Because the old node was removed from the head list,
       
   680                     // it is not head node anymore. Set it as hidden. So,
       
   681                     // it will be handled correctly when downloading 
       
   682                     // and installing is done. For example, if the new node 
       
   683                     // depends on the older version.
       
   684                     tmpNode.ForceHidden( ETrue );
       
   685                     }
       
   686                 else
       
   687                     {
       
   688                     IAUPDATE_TRACE("[IAUPDATE] Existing head node stays in head list");
       
   689                     // The existing head node is newer. So, the recommended new node
       
   690                     // will not be head node. Make sure that it is set as hidden
       
   691                     // because hidden value is used to check if the node is head node
       
   692                     // or not.
       
   693                     aNode.ForceHidden( ETrue );
       
   694                     }
       
   695 
       
   696                 // We found a corresponding item from the head list.
       
   697                 // Now, the correct node is in the list.
       
   698                 alreadyIncluded = ETrue;
       
   699                 break;
       
   700                 }
       
   701             }
       
   702             
       
   703         if( !alreadyIncluded )
       
   704             {            
       
   705             // The given node was not inserted above. 
       
   706             // So, append it now to the end of the list.
       
   707             // Notice, that here we still may append hidden node into the head
       
   708             // list. This way, the newest node is always in the head list when
       
   709             // comparison is done. Later RemoveHiddenNodesFromHeadList 
       
   710             // is called. If the head node is hidden, it will be removed from 
       
   711             // the head list. This way we can be sure that head list contains
       
   712             // only newest nodes and no visible head node version is older than 
       
   713             // some hidden one.
       
   714             IAUPDATE_TRACE("[IAUPDATE] Add new head node into the list.");
       
   715             iHeadNodes.AppendL( &aNode );            
       
   716             }            
       
   717         }
       
   718         
       
   719     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::UpdateHeadNodeListL() begin");
       
   720     }
       
   721     
       
   722     
       
   723 TBool CIAUpdateNodeContainer::ReplaceRecommendedL(
       
   724     const CIAUpdateNode& aCurrentNode,
       
   725     const CIAUpdateNode& aNewNode ) const
       
   726     {
       
   727     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ReplaceRecommendedL() begin");
       
   728     
       
   729     if ( aCurrentNode.Uid() != aNewNode.Uid() )
       
   730         {
       
   731         IAUPDATE_TRACE("[IAUPDATE] LEAVE: Nodes do not match.");
       
   732         User::Leave( KErrArgument );
       
   733         }
       
   734     
       
   735     // New node is recommended if encountered node has higher version, 
       
   736     // or if the version is equal but current node packet type is 
       
   737     // not preferred. Also, the leaf distance of dependency chain is checked
       
   738     // because long dependency chains should be avoided.
       
   739     // The content package order is: (first) PU, SP, SA
       
   740     // Notice, that PU and SP require already installed version of
       
   741     // the application but this was already checked when node were added
       
   742     // into the array.
       
   743     if ( aNewNode.Version() > aCurrentNode.Version() 
       
   744          || aNewNode.Version() == aCurrentNode.Version() 
       
   745             && aNewNode.LeafDistance() <= aCurrentNode.LeafDistance()
       
   746             && ( aNewNode.Type() == aCurrentNode.Type()
       
   747                  || aNewNode.Type() != MIAUpdateNode::EPackageTypeSA
       
   748                     && aCurrentNode.Type() == MIAUpdateNode::EPackageTypeSA
       
   749                  || aNewNode.Type() == MIAUpdateNode::EPackageTypePU 
       
   750                     && aCurrentNode.Type() == MIAUpdateNode::EPackageTypeSP ) )
       
   751         {
       
   752         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ReplaceRecommendedL() end: ETrue");
       
   753         return ETrue;
       
   754         }
       
   755     else
       
   756         {
       
   757         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::ReplaceRecommendedL() end: EFalse");
       
   758         return EFalse;
       
   759         }
       
   760     }
       
   761 
       
   762 
       
   763 TBool CIAUpdateNodeContainer::PackageTypeAcceptedL( 
       
   764     const CIAUpdateNode& aNode ) const
       
   765     {
       
   766     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::PackageTypeAcceptedL() begin");
       
   767     
       
   768     if ( aNode.Type() == MIAUpdateNode::EPackageTypeServicePack
       
   769          || aNode.Type() == MIAUpdateNode::EPackageTypeSA )
       
   770         {
       
   771         // Service packs and SA type always accepted.
       
   772         IAUPDATE_TRACE("[IAUPDATE] Upgrade packet type SA or node is service pack");
       
   773         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::PackageTypeAcceptedL() end: ETrue");
       
   774         return ETrue;
       
   775         }
       
   776 
       
   777     TBool accepted( EFalse );
       
   778         
       
   779     // The PU and SP packet types are accepted only if 
       
   780     // the content that will be updated already exists in the phone. 
       
   781     // Otherwise, the SA should be used.
       
   782     RPointerArray< CIAUpdateNodeDependency > dependencies;
       
   783     CleanupClosePushL( dependencies );
       
   784     
       
   785     aNode.Details().GetDependenciesL( dependencies );
       
   786     
       
   787     for ( TInt i = 0; i < dependencies.Count(); ++i )
       
   788         {
       
   789         CIAUpdateNodeDependency* dep( dependencies[ i ] );
       
   790         if ( aNode.Uid() == dep->Uid() )   
       
   791             {
       
   792             // This dependency describes the upgrade dependency
       
   793             // because the UIDs match. So, now we check if 
       
   794             // the upgrade dependency content is available in the phone.
       
   795             TIAUpdateVersion version;
       
   796             
       
   797             // Check if the dependency file has already been installed 
       
   798             // and get the version of the application if it has been installed.
       
   799             TBool installed = 
       
   800                 IAUpdateUtils::IsAppInstalledL( dep->Uid(), version );
       
   801             
       
   802             if ( installed  
       
   803                  && version >= dep->VersionFloor()
       
   804                  && version <= dep->VersionRoof() )
       
   805                 {
       
   806                 // The content was already installed and its version belonged 
       
   807                 // to the required version range. So, upgrade content is accepted.
       
   808                 IAUPDATE_TRACE("[IAUPDATE] Accepted");
       
   809                 accepted = ETrue;
       
   810                 break;        
       
   811                 }
       
   812             }
       
   813         }
       
   814 
       
   815     // If dependencies to the previous versions of 
       
   816     // the same content were not found, PU and SP are not accepted.
       
   817     CleanupStack::PopAndDestroy( &dependencies );
       
   818 
       
   819     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::PackageTypeAcceptedL() end: %d",
       
   820                      accepted);
       
   821     
       
   822     return accepted;
       
   823     }
       
   824 
       
   825 
       
   826 TBool CIAUpdateNodeContainer::NodeAlreadyExists( const CIAUpdateNode& aNode ) const
       
   827     {
       
   828     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::NodeAlreadyExists() begin");
       
   829     
       
   830     CIAUpdateNode* node( NULL );
       
   831     for ( TInt i = 0; i < iNodes.Count(); ++i )
       
   832         {
       
   833         node = iNodes[ i ];
       
   834         if ( node->Equals( aNode ) )
       
   835             {
       
   836             IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::NodeAlreadyExists() end: ETrue");
       
   837             return ETrue;
       
   838             }
       
   839         }
       
   840 
       
   841     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::NodeAlreadyExists() end: EFalse");
       
   842 
       
   843     return EFalse;
       
   844     }
       
   845 
       
   846 
       
   847 void CIAUpdateNodeContainer::CreateSelfUpdateBundleL()
       
   848     {
       
   849     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::CreateSelfUpdateBundleL() begin");
       
   850     
       
   851     // Check if IAD exists and if self updater and NCD exist.
       
   852     // Mark self updater and NCD hidden if necessary.
       
   853     // Then, RemoveHiddenNodesFromHeadList will handle rest
       
   854     // when it is called later in the head list creation process.
       
   855 
       
   856     CIAUpdateNode* iad( NULL );
       
   857     CIAUpdateNode* ncd( NULL );
       
   858     CIAUpdateNode* selfUpdater( NULL );
       
   859     
       
   860     for ( TInt i = 0; i < iHeadNodes.Count(); ++i )
       
   861         {
       
   862         CIAUpdateNode* node( iHeadNodes[ i ] );
       
   863         const TUid& nodeUid( node->Uid() );
       
   864 
       
   865         if ( IAUpdateNodeFactory::IsIad( nodeUid ) )
       
   866             {
       
   867             iad = node;
       
   868             }
       
   869         else if ( IAUpdateNodeFactory::IsNcd( nodeUid ) )
       
   870             {
       
   871             ncd = node;
       
   872             }
       
   873         else if ( IAUpdateNodeFactory::IsUpdater( nodeUid ) )
       
   874             {
       
   875             selfUpdater = node;
       
   876             }
       
   877         }
       
   878 
       
   879     // If IAD is given, then other self update related items should
       
   880     // be set hidden.
       
   881     if ( iad )
       
   882         {
       
   883         IAUPDATE_TRACE("[IAUPDATE] IAD");
       
   884         // Because IAD is given, the possible NCD and self updater nodes
       
   885         // should be set hidden and dependencies should be created for
       
   886         // self update bundle.
       
   887         // Notice, here we create the forced dependencies only from IAD.
       
   888         if ( ncd )
       
   889             {
       
   890             IAUPDATE_TRACE("[IAUPDATE] NCD");
       
   891             // Make NCD hidden and force IAD to depend on it.
       
   892             ncd->ForceHidden( ETrue );
       
   893             // SetExcessDependencyL will also update the dependant info
       
   894             // for the dependency node.
       
   895             iad->SetExcessDependencyL( *ncd, ETrue );
       
   896 
       
   897             // Because there is possibility that some service pack items
       
   898             // depend on NCD but do not depend on IAD we need to force
       
   899             // the dependency to IAD. This way if that service pack is
       
   900             // chosen, the IAD that is visible in UI will also be chosen
       
   901             // in UI and the flow can continue correctly. If IAD would not
       
   902             // be forced, then NCD would not be installed because at the
       
   903             // moment service packs do not support self update in IAD Engine
       
   904             // side. If IAD does not exist, then NCD will be shown in UI
       
   905             // and it would be selected if dependency requires that.
       
   906             TInt ncdDependantCount( ncd->DependantNodes().Count() );
       
   907             const RPointerArray< CIAUpdateNode >& ncdDependants(
       
   908                 ncd->DependantNodes() );
       
   909             IAUPDATE_TRACE_1("[IAUPDATE] Ncd dependant count: %d",    
       
   910                              ncdDependantCount);
       
   911             for ( TInt i = 0; i < ncdDependantCount; ++i )
       
   912                 {
       
   913                 CIAUpdateNode* ncdDependantNode( 
       
   914                     ncdDependants[ i ] );
       
   915                 if ( iad != ncdDependantNode )
       
   916                     {
       
   917                     IAUPDATE_TRACE("[IAUPDATE] NCD dependant gets IAD as dependency");
       
   918                     // The dependant was not iad itself.
       
   919                     // Force dependant to depend also from iad.
       
   920                     ncdDependantNode->SetExcessDependencyL( *iad, ETrue );
       
   921                     }
       
   922                 }
       
   923             }
       
   924         if ( selfUpdater )
       
   925             {
       
   926             IAUPDATE_TRACE("[IAUPDATE] Selfupdater");
       
   927             // Make selfupdater hidden and force IAD to depend on it.
       
   928             selfUpdater->ForceHidden( ETrue );
       
   929             // SetExcessDependencyL will also update the dependant info
       
   930             // for the dependency node.
       
   931             iad->SetExcessDependencyL( *selfUpdater, ETrue );
       
   932             }
       
   933         }
       
   934 
       
   935     // Above, dependencies were forced to make sure that self update
       
   936     // bunlde is created and the self udpate flow will handle the items
       
   937     // in correct order. Now, make sure that self updater depth and
       
   938     // leaf distance are correct if both ncd and self updater exist.
       
   939     // There is at least some sort of dependency also between them.
       
   940     if ( selfUpdater && ncd )
       
   941         {
       
   942         IAUPDATE_TRACE("[IAUPDATE] Self updater dependency for NCD");
       
   943         // Because NCD also requires self updater for its install,
       
   944         // set the dependency depth and leaf distances also here. 
       
   945         // Then, the update flow will always try to install self
       
   946         // updater before NCD. Notice, if server has not defined 
       
   947         // the dependency between selfupdater and NCD, then do not
       
   948         // force the dependency here either.
       
   949         // In case of IAD, the items will be hidden from UI.
       
   950         // Then, forced dependency chains will not change functionality
       
   951         // in UI. But, if IAD was missing and only NCD and selfupdater would
       
   952         // exist, NCD and self updater should be shown in UI themselves. Then,
       
   953         // UI side should not force dependency between those items, unless 
       
   954         // dependency is given in metadata. That is why we do not force
       
   955         // excess dependency into the dependency chain here. Notice, that
       
   956         // if IAD exists, then selfupdater is forced to its dependency above.
       
   957         // So, self updater is part of the IAD bundle then.
       
   958         ncd->SetExcessDependencyL( *selfUpdater, EFalse );
       
   959         }
       
   960 
       
   961     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::CreateSelfUpdateBundleL() end");
       
   962     }
       
   963 
       
   964 
       
   965 void CIAUpdateNodeContainer::RemoveHiddenNodesFromHeadList()
       
   966     {
       
   967     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::RemoveHiddenNodesFromHeadList() begin");
       
   968     
       
   969     TInt count( iHeadNodes.Count() );
       
   970     for ( TInt i = count - 1; i >= 0; --i )
       
   971         {
       
   972         CIAUpdateNode* node( iHeadNodes[ i ] );
       
   973         if ( node->Hidden() )
       
   974             {
       
   975             // Node is not deleted here because it is still part of the
       
   976             // iNodes list that contains all the nodes.
       
   977             IAUPDATE_TRACE("[IAUPDATE] Remove node");
       
   978             iHeadNodes.Remove( i );
       
   979             }
       
   980         }
       
   981 
       
   982     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::RemoveHiddenNodesFromHeadList() begin");
       
   983     }
       
   984 
       
   985 
       
   986 void CIAUpdateNodeContainer::HandleServicePacksL()
       
   987     {
       
   988     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HandleServicePacksL() begin");
       
   989 
       
   990     // This array will contain the nodes that belong to
       
   991     // the dependency hierarchy of the service pack.
       
   992     RPointerArray< CIAUpdateNode > servicePackNodes;
       
   993     CleanupClosePushL( servicePackNodes );
       
   994 
       
   995     // Notice, here that we will force all the items under the found service pack
       
   996     // as hidden. The main service pack will be shown in UI and possible service packs
       
   997     // in dependencies will be hidden.
       
   998 
       
   999     for ( TInt i = 0; i < iNodes.Count(); ++i )
       
  1000         {
       
  1001         CIAUpdateNode& node( *iNodes[ i ] );
       
  1002         if ( node.Type() == MIAUpdateNode::EPackageTypeServicePack )
       
  1003             {
       
  1004             IAUPDATE_TRACE("[IAUPDATE] Service pack node found");
       
  1005 
       
  1006             if ( node.IsInstalled() )
       
  1007                 {
       
  1008                 IAUPDATE_TRACE("[IAUPDATE] Force service pack hidden");
       
  1009                 // Because service pack is already installed, set
       
  1010                 // it as hidden itself. Do not delete it because
       
  1011                 // there may be some dependencies set to it before
       
  1012                 // from other service packs. By setting node hidden,
       
  1013                 // it will not be included into the main list.
       
  1014                 node.ForceHidden( ETrue );
       
  1015                 }
       
  1016             
       
  1017             // Nodes of service pack are set to hidden. 
       
  1018             // These nodes itself may have dependencies, but they are not forced hidden. 
       
  1019             //
       
  1020             node.GetDependencyNodesL( servicePackNodes, ETrue );
       
  1021             for ( TInt j = 0; j < servicePackNodes.Count(); ++j )
       
  1022                 {
       
  1023                 CIAUpdateNode& servicePackNode( *servicePackNodes[ j ] );
       
  1024                 if ( !servicePackNode.IsSelfUpdate() )
       
  1025                     {
       
  1026                     servicePackNode.ForceHidden( ETrue );
       
  1027                     }
       
  1028                 }
       
  1029             // Reset the array, because we may use the array in 
       
  1030             // next loops.
       
  1031             servicePackNodes.Reset();
       
  1032             }
       
  1033         }
       
  1034 
       
  1035     CleanupStack::PopAndDestroy( &servicePackNodes );
       
  1036 
       
  1037     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::HandleServicePacksL() end");
       
  1038     }
       
  1039 
       
  1040 
       
  1041 TBool CIAUpdateNodeContainer::InstallCheckL( CIAUpdateNode& aNode ) const
       
  1042     {
       
  1043     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNodeContainer::InstallCheckL() begin");
       
  1044     
       
  1045     TBool checkPassed( ETrue );
       
  1046 
       
  1047     // Notice, that service packs are accepted even if they
       
  1048     // would be already installed. This is because service
       
  1049     // packs themselves contain dependencies and these dependencies
       
  1050     // may not be set yet. So, after all the nodes are available,
       
  1051     // the service packs can be checked separately.
       
  1052     if ( aNode.Type() != MIAUpdateNode::EPackageTypeServicePack )
       
  1053         {
       
  1054         IAUPDATE_TRACE("[IAUPDATE] Not a service pack");
       
  1055 
       
  1056         TIAUpdateVersion installedVersion;
       
  1057         TBool installed( 
       
  1058             IAUpdateUtils::IsAppInstalledL( aNode.Uid(), installedVersion ) );
       
  1059         // Notice that here we let the check pass also if node has the same version
       
  1060         // as the installed content. By accepting same version, the dependency chains
       
  1061         // will contain the currently installed node dependency information. Then,
       
  1062         // if newer dependencies are provided for the already installed content,
       
  1063         // they will be handled correctly for example inside service packs.
       
  1064         if ( installed )
       
  1065             {
       
  1066             IAUPDATE_TRACE("[IAUPDATE] Content installed");
       
  1067             if ( installedVersion > aNode.Version() )
       
  1068                 {
       
  1069                 IAUPDATE_TRACE("[IAUPDATE] Newer version already installed.");
       
  1070                 // If the installed version is newer, then think the node as
       
  1071                 // installed.
       
  1072                 checkPassed = EFalse;
       
  1073                 }
       
  1074             else if ( installedVersion == aNode.Version() )
       
  1075                 {
       
  1076                 IAUPDATE_TRACE("[IAUPDATE] Force node hidden");
       
  1077                 // Node is already installed but we still want to include
       
  1078                 // it into the dependency chain. But, node should not be
       
  1079                 // shown in the UI. So, force the installed node as hidden.
       
  1080                 aNode.ForceHidden( ETrue );
       
  1081                 }
       
  1082             }
       
  1083         }
       
  1084 
       
  1085     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNodeContainer::InstallCheckL() end: %d",
       
  1086                      checkPassed);
       
  1087 
       
  1088     return checkPassed;
       
  1089     }