iaupdate/IAD/engine/controller/src/iaupdatecontentoperationmanager.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2007-2008 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:   CIAUpdateContentOperationManager 
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <ncdpurchasedetails.h>
       
    21 
       
    22 #include "iaupdatecontentoperationmanager.h"
       
    23 #include "iaupdatenodeimpl.h"
       
    24 #include "iaupdateoperation.h"
       
    25 #include "iaupdatepurchaseoperation.h"
       
    26 #include "iaupdatedownloadoperation.h"
       
    27 #include "iaupdateinstalloperation.h"
       
    28 #include "iaupdateselfupdateinitoperation.h"
       
    29 #include "iaupdatectrlnodeconsts.h"
       
    30 #include "iaupdatenodefactory.h"
       
    31 
       
    32 #include "iaupdatedebug.h"
       
    33 
       
    34 
       
    35 // Const value for the progress init value.
       
    36 const TInt KInitProgress( 0 );
       
    37 
       
    38 
       
    39 // This is a static function that is used with RPointerArray::Sort to sort
       
    40 // the nodes according to their node depths.
       
    41 TInt NodeArraySorter( const CIAUpdateNode& aNode1, const CIAUpdateNode& aNode2 )
       
    42     {
       
    43     // The leaf should be in the end of the array and the root in the beginning.
       
    44     // The depth value informs how deep in the hierarchy the node is. A depth
       
    45     // value zero means that the node is a root. If multiple branches lead to
       
    46     // a same node, then the greatest depth value is used for the node.
       
    47     return ( aNode1.Depth() - aNode2.Depth() );
       
    48     }
       
    49 
       
    50 
       
    51 // ---------------------------------------------------------------------------
       
    52 // CIAUpdateContentOperationManager::::NewL
       
    53 // 
       
    54 // ---------------------------------------------------------------------------
       
    55 // 
       
    56 CIAUpdateContentOperationManager* CIAUpdateContentOperationManager::NewL()
       
    57     {
       
    58     CIAUpdateContentOperationManager* self = 
       
    59         CIAUpdateContentOperationManager::NewLC();
       
    60     CleanupStack::Pop( self );
       
    61     return self;
       
    62     }
       
    63     
       
    64     
       
    65 // ---------------------------------------------------------------------------
       
    66 // CIAUpdateContentOperationManager::::NewLC
       
    67 // 
       
    68 // ---------------------------------------------------------------------------
       
    69 // 
       
    70 CIAUpdateContentOperationManager* CIAUpdateContentOperationManager::NewLC()
       
    71     {
       
    72     CIAUpdateContentOperationManager* self =
       
    73         new( ELeave ) CIAUpdateContentOperationManager();
       
    74     CleanupStack::PushL( self );
       
    75     self->ConstructL();
       
    76     return self;
       
    77     }
       
    78 
       
    79 
       
    80 // ---------------------------------------------------------------------------
       
    81 // CIAUpdateContentOperationManager::CIAUpdateContentOperationManager
       
    82 // 
       
    83 // ---------------------------------------------------------------------------
       
    84 // 
       
    85 CIAUpdateContentOperationManager::CIAUpdateContentOperationManager()
       
    86 : CActive( CActive::EPriorityStandard )
       
    87     {
       
    88     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CIAUpdateContentOperationManager");
       
    89     }
       
    90 
       
    91 
       
    92 // ---------------------------------------------------------------------------
       
    93 // CIAUpdateContentOperationManager::ConstructL
       
    94 // 
       
    95 // ---------------------------------------------------------------------------
       
    96 // 
       
    97 void CIAUpdateContentOperationManager::ConstructL()
       
    98     {
       
    99     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ConstructL begin");
       
   100 
       
   101     CActiveScheduler::Add( this );
       
   102 
       
   103     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ConstructL end");
       
   104     }
       
   105 
       
   106 
       
   107 // ---------------------------------------------------------------------------
       
   108 // CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager
       
   109 // 
       
   110 // ---------------------------------------------------------------------------
       
   111 // 
       
   112 CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager()
       
   113     {
       
   114     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager begin");
       
   115 
       
   116     // It is always good to call this in active object destructor 
       
   117     // to be sure that no operations are left hanging. 
       
   118     // This will also reset and delete all the necessary data if needed.
       
   119     Cancel();
       
   120 
       
   121     // Reset the array to be sure.
       
   122     // If the operation has left during startup, the array may not be reseted.
       
   123     iNodes.Reset();
       
   124 
       
   125     // Delete operation to make sure that it is also deleted.
       
   126     delete iOperation;
       
   127 
       
   128     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::~CIAUpdateContentOperationManager end");
       
   129     }
       
   130 
       
   131 
       
   132 // ---------------------------------------------------------------------------
       
   133 // CIAUpdateContentOperationManager::CheckErrorCode
       
   134 // 
       
   135 // ---------------------------------------------------------------------------
       
   136 // 
       
   137 TInt CIAUpdateContentOperationManager::CheckErrorCode( TInt aError )
       
   138     {
       
   139     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode begin: %d",
       
   140                      aError);
       
   141     
       
   142     if ( aError > ( IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
       
   143                     - IAUpdateCtrlNodeConsts::KErrBaseRange ) 
       
   144          && aError <= IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall )
       
   145         {
       
   146         IAUPDATE_TRACE("[IAUPDATE] Service pack install");
       
   147         aError -= IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall;
       
   148         }
       
   149     else if ( aError > IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
       
   150               && aError <= IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload )
       
   151         {
       
   152         IAUPDATE_TRACE("[IAUPDATE] Service pack download");
       
   153         aError -= IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload;
       
   154         }
       
   155 
       
   156     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode end: %d",
       
   157                      aError);
       
   158 
       
   159     return aError;
       
   160     }
       
   161 
       
   162 
       
   163 // ---------------------------------------------------------------------------
       
   164 // CIAUpdateContentOperationManager::CheckErrorCode
       
   165 // 
       
   166 // ---------------------------------------------------------------------------
       
   167 // 
       
   168 CIAUpdateContentOperationManager::TContentOperationType 
       
   169     CIAUpdateContentOperationManager::ServicePackOperationType( 
       
   170         MNcdPurchaseDetails& aNodeDetails )
       
   171     {
       
   172     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode begin");
       
   173 
       
   174     if ( !IAUpdateNodeFactory::IsServicePack( 
       
   175             aNodeDetails.AttributeString( 
       
   176                 MNcdPurchaseDetails::EPurchaseAttributeContentMimeType ) ) )
       
   177         {
       
   178         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode end: ENoContentOperation");
       
   179         return ENoContentOperation;
       
   180         }
       
   181     
       
   182     TContentOperationType type( EPurchaseOperation );
       
   183     
       
   184     TInt errorCode( aNodeDetails.LastOperationErrorCode() );
       
   185 
       
   186     if ( errorCode > ( IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
       
   187                        - IAUpdateCtrlNodeConsts::KErrBaseRange ) 
       
   188          && errorCode <= IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall )
       
   189         {
       
   190         IAUPDATE_TRACE("[IAUPDATE] Service pack install");
       
   191         type = EInstallOperation;
       
   192         }
       
   193     else if ( errorCode > IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall 
       
   194               && errorCode <= IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload )
       
   195         {
       
   196         IAUPDATE_TRACE("[IAUPDATE] Service pack download");
       
   197         type = EDownloadOperation;
       
   198         }
       
   199 
       
   200     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckErrorCode end: %d",
       
   201                      type);
       
   202 
       
   203     return type;     
       
   204     }
       
   205 
       
   206 
       
   207 // ---------------------------------------------------------------------------
       
   208 // CIAUpdateContentOperationManager::SortNodeArray
       
   209 // 
       
   210 // ---------------------------------------------------------------------------
       
   211 // 
       
   212 void CIAUpdateContentOperationManager::SortNodeArray( 
       
   213     RPointerArray< CIAUpdateNode >& aNodes )
       
   214     {
       
   215     // Use that static function to sort the array.
       
   216     aNodes.Sort( TLinearOrder< CIAUpdateNode >( &NodeArraySorter ) );
       
   217     }
       
   218 
       
   219 
       
   220 // ---------------------------------------------------------------------------
       
   221 // CIAUpdateContentOperationManager::GetOperationNodesL
       
   222 // 
       
   223 // ---------------------------------------------------------------------------
       
   224 // 
       
   225 void CIAUpdateContentOperationManager::GetOperationNodesL( 
       
   226     const CIAUpdateNode& aNode, RPointerArray< CIAUpdateNode >& aNodes,
       
   227     TBool aAcceptHiddenDependencyNodes, TBool aAcceptVisibleDependencyNodes )
       
   228     {
       
   229     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationNodeArrayL() begin");
       
   230     
       
   231     // Reset the array.
       
   232     // So, new nodes can be inserted into it.
       
   233     aNodes.Reset();
       
   234 
       
   235     // We need to get the array of the nodes that this node depends on.
       
   236     // Notice, that here we just want the specific type of nodes that belong 
       
   237     // to this node. If another dependency node does not match the criteria then 
       
   238     // ignore that branch starting from that node.
       
   239     HandleDependenciesL( aNode, aNodes,
       
   240                          aAcceptHiddenDependencyNodes, 
       
   241                          aAcceptVisibleDependencyNodes );
       
   242 
       
   243     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationNodeArrayL() end");
       
   244     }
       
   245 
       
   246 
       
   247 // ---------------------------------------------------------------------------
       
   248 // CIAUpdateContentOperationManager::TotalContentSizeL
       
   249 // 
       
   250 // ---------------------------------------------------------------------------
       
   251 //     
       
   252 TInt CIAUpdateContentOperationManager::TotalContentSizeL( 
       
   253     const CIAUpdateNode& aNode,
       
   254     TBool aIncludeDownloaded,
       
   255     TBool aIncludeInstalled,
       
   256     TBool aAcceptHiddenDependencyNodes,
       
   257     TBool aAcceptVisibleDependencyNodes )
       
   258     {
       
   259     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNode::TotalContentSizeL() begin");
       
   260 
       
   261     RPointerArray< CIAUpdateNode > nodes;
       
   262     CleanupClosePushL( nodes );
       
   263     GetOperationNodesL( 
       
   264         aNode, nodes,
       
   265         aAcceptHiddenDependencyNodes, 
       
   266         aAcceptVisibleDependencyNodes );
       
   267     TInt totalContentSize( 
       
   268         ArrayTotalContentSizeL( 
       
   269             nodes, aIncludeDownloaded, aIncludeInstalled ) );
       
   270     CleanupStack::PopAndDestroy( &nodes );
       
   271 
       
   272     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNode::TotalContentSizeL() end: %d",
       
   273                      totalContentSize);
       
   274 
       
   275     return totalContentSize;
       
   276     }
       
   277 
       
   278 
       
   279 // ---------------------------------------------------------------------------
       
   280 // CIAUpdateContentOperationManager::StartL
       
   281 // 
       
   282 // ---------------------------------------------------------------------------
       
   283 //     
       
   284 void CIAUpdateContentOperationManager::StartL( 
       
   285     MIAUpdateContentOperationObserver& aObserver,
       
   286     const CIAUpdateContentOperationManager::TContentOperationType& aOperationType,
       
   287     CIAUpdateNode& aNode )
       
   288     {
       
   289     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::StartL begin");
       
   290 
       
   291     if ( iOperation || IsActive() )
       
   292         {
       
   293         IAUPDATE_TRACE("[IAUPDATE] ERROR Operation already existed");
       
   294         User::Leave( KErrInUse );
       
   295         }
       
   296     else if ( aNode.Hidden()  )
       
   297         {
       
   298         // The main node is not allowed to be hidden.
       
   299         IAUPDATE_TRACE("[IAUPDATE] ERROR: Hidden node given");
       
   300         User::Leave( KErrArgument );
       
   301         }
       
   302     else if ( aOperationType != EPurchaseOperation
       
   303               && aOperationType != EDownloadOperation
       
   304               && aOperationType != EInstallOperation )
       
   305         {
       
   306         // The main node is not allowed to be hidden.
       
   307         IAUPDATE_TRACE("[IAUPDATE] ERROR Operation type not supported");
       
   308         User::Leave( KErrNotSupported );
       
   309         }
       
   310 
       
   311     // Reset member variables
       
   312     iSuccessCount = 0;
       
   313 
       
   314     // Set progress values to defaults.
       
   315     ResetProgress();
       
   316     
       
   317     // Notice, that this will also set the main node.
       
   318     SetNodeArrayL( aNode );
       
   319 
       
   320     // Progress values were resetted above.
       
   321     // Now, set the expected total maximum value for the progress.
       
   322     InitTotalMaxProgressL( aOperationType );
       
   323 
       
   324     // Set the observer
       
   325     iObserver = &aObserver;
       
   326     
       
   327     // Set the operation type
       
   328     iOperationType = aOperationType;
       
   329 
       
   330     // Start the operation by calling the first round for active loop.
       
   331     iStatus = KRequestPending;
       
   332     SetActive();
       
   333     TRequestStatus* ptrStatus = &iStatus;
       
   334     User::RequestComplete( ptrStatus, KErrNone );                
       
   335 
       
   336     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::StartL end");
       
   337     }
       
   338     
       
   339 
       
   340 // ---------------------------------------------------------------------------
       
   341 // CIAUpdateContentOperationManager::OperationType
       
   342 // 
       
   343 // ---------------------------------------------------------------------------
       
   344 // 
       
   345 const CIAUpdateContentOperationManager::TContentOperationType& 
       
   346     CIAUpdateContentOperationManager::OperationType() const
       
   347     {
       
   348     return iOperationType;
       
   349     }
       
   350 
       
   351 
       
   352 // ---------------------------------------------------------------------------
       
   353 // CIAUpdateContentOperationManager::ContentOperationComplete
       
   354 // 
       
   355 // ---------------------------------------------------------------------------
       
   356 //
       
   357 void CIAUpdateContentOperationManager::ContentOperationComplete( 
       
   358     CIAUpdateBaseNode& /*aNode*/,
       
   359     TInt aError )
       
   360     {
       
   361     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationComplete() begin");
       
   362 
       
   363     // Content operation has completed.
       
   364     // In normal cases, start new active loop. So, RunL will be called.
       
   365     // Notice, that if Cancel was called, this callback function is called from the
       
   366     // operation when its cancel is synchronously completed. Because Cancel is waiting 
       
   367     // for DoCancel function to complete the request, let it complete here. So, 
       
   368     // actual cancel can finish its job. We do not want to call callbacks of the observer 
       
   369     // of this operation manager after Cancel.
       
   370 
       
   371     if ( aError == KErrNone )
       
   372         {
       
   373         ++iSuccessCount;
       
   374         IAUPDATE_TRACE_1("[IAUPDATE] Successfull operation: %d",
       
   375                          iSuccessCount); 
       
   376 
       
   377         // Check that the node MIME is set correctly.
       
   378         // Then, the history will be shown also correctly for the nodes.
       
   379         // By updating the purchase history, also the correct MIME type
       
   380         // is set, for example, if node is hidden.
       
   381         IAUPDATE_TRACE("[IAUPDATE] Update purchase history for current node.");
       
   382         UpdatePurchaseHistory( *iCurrentNode, aError );
       
   383         }
       
   384 
       
   385     TRequestStatus* ptrStatus = &iStatus;
       
   386     User::RequestComplete( ptrStatus, aError );
       
   387     
       
   388     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationComplete() end");
       
   389     }
       
   390 
       
   391 
       
   392 // ---------------------------------------------------------------------------
       
   393 // CIAUpdateContentOperationManager::ContentOperationProgress
       
   394 // 
       
   395 // ---------------------------------------------------------------------------
       
   396 //
       
   397 void CIAUpdateContentOperationManager::ContentOperationProgress( 
       
   398     CIAUpdateBaseNode& /*aNode*/, 
       
   399     TInt aProgress, 
       
   400     TInt aMaxProgress )
       
   401     {
       
   402     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationProgress() begin");
       
   403 
       
   404     UpdateProgress( aProgress, aMaxProgress );
       
   405 
       
   406     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::ContentOperationProgress() end");
       
   407     }
       
   408 
       
   409 
       
   410 // ---------------------------------------------------------------------------
       
   411 // CIAUpdateContentOperationManager::DoCancel
       
   412 // 
       
   413 // ---------------------------------------------------------------------------
       
   414 // 
       
   415 void CIAUpdateContentOperationManager::DoCancel()
       
   416     {
       
   417     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::DoCancel() begin");
       
   418     
       
   419     // If we are here, then there should always be an operation going on.
       
   420 
       
   421     // Notice, that if disclaimers are shown, for example,
       
   422     // when installing, then the KErrCancel can be gotten from
       
   423     // the operation even if the cancellation was not started from here.
       
   424     // But, then the RunL is called and the operation is finished correctly.
       
   425     // But, if cancellation is started here, the RunL is not called and the 
       
   426     // cancellation proceedes correctly. Instead then, operations call directly
       
   427     // ContentOperationComplete callback function that completes the request that
       
   428     // active object Cancel is listening to complete its actions.
       
   429     
       
   430     // Cancel the current operation by deleting it.
       
   431     delete iOperation;
       
   432     iOperation = NULL;
       
   433 
       
   434     // No need for the observer anymore.
       
   435     iObserver = NULL;
       
   436 
       
   437 
       
   438     // Because, the main node is the one that is visible, its error code
       
   439     // needs to be updated here separately. Also, the current node needs
       
   440     // to be updated. So, set them by hand. If other nodes were not operated,
       
   441     // no need to update their info to purchase history because they should
       
   442     // not be shown in the history view anyways.
       
   443     // Notice, that even if the operations may have updated the purchase history
       
   444     // by themselves in NCD Engine side, the purchase history MIME type may
       
   445     // need to be updated according to the IAD node values. So, that is why
       
   446     // we update the purchase history here one more time.
       
   447     // Notice, that in case of service packs and other service packs 
       
   448     // inside them, also then just set the purchase history for the head
       
   449     // service pack.
       
   450 
       
   451     if ( iNode != iCurrentNode )
       
   452         {
       
   453         IAUPDATE_TRACE("[IAUPDATE] Update current node purchase history with KErrCancel");
       
   454         UpdatePurchaseHistory( *iCurrentNode, KErrCancel );
       
   455         }
       
   456 
       
   457     IAUPDATE_TRACE("[IAUPDATE] Update head node purchase history with KErrCancel");
       
   458     UpdatePurchaseHistory( *iNode, KErrCancel );
       
   459 
       
   460 
       
   461     // No need for nodes
       
   462     iNodes.Reset();
       
   463     iNode = NULL;
       
   464     iCurrentNode = NULL;
       
   465 
       
   466     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::DoCancel() end");
       
   467     }
       
   468     
       
   469 
       
   470 // ---------------------------------------------------------------------------
       
   471 // CIAUpdateContentOperationManager::RunL
       
   472 // 
       
   473 // ---------------------------------------------------------------------------
       
   474 //     
       
   475 void CIAUpdateContentOperationManager::RunL()
       
   476     {
       
   477     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::RunL() begin");
       
   478 
       
   479     // Reset progress for current operation.
       
   480     ResetCurrentProgress();
       
   481 
       
   482     // Delete old operation.
       
   483     // Later a new and correct type of operation will be created for
       
   484     // the new node if one is found.
       
   485     delete iOperation;
       
   486     iOperation = NULL;
       
   487 
       
   488     // When the operation flow is started, the error code is always KErrNone.    
       
   489     // We only get errors to status if content operation is going on.
       
   490     User::LeaveIfError( iStatus.Int() );
       
   491     
       
   492     // Handle the next content in the array.
       
   493     if ( iNodes.Count() > 0 )
       
   494         {
       
   495         // Handle next node.
       
   496         SetCurrentNodeL();
       
   497 
       
   498         if ( IsServicePack( *iNode ) 
       
   499              && iCurrentNode->IsSelfUpdate() )
       
   500             {
       
   501             // Because operation was created, it means that the self update inside
       
   502             // the service pack is not installed yet. Because we do not support
       
   503             // self updates inside service packs, leave from here.
       
   504             
       
   505             // Note for future improvements: 
       
   506             // If service packs support for self update is added, remove
       
   507             // the if clause and always append nodes.
       
   508             // Also, remember to update CIAUpdateServicePackNode::IsSelfUpdate 
       
   509             // function if UI side should know about the self updates inside
       
   510             // the service pack. Then, most likely service pack should be thought 
       
   511             // as self update if any of the items gotten in the dependency hierarchy
       
   512             // is a self update.
       
   513 
       
   514             IAUPDATE_TRACE("[IAUPDATE] Service pack does not support self updates");
       
   515             User::Leave( KErrNotSupported );
       
   516             }
       
   517 
       
   518 
       
   519         // Notice, that in case of service packs, the operation is not created.
       
   520         // Skip, service pack items themself and only handle operations for 
       
   521         // their dependencies.
       
   522 
       
   523         TBool operationStarted( EFalse );      
       
   524 
       
   525         iOperation = CreateOperationL( iOperationType, *iCurrentNode );
       
   526 
       
   527         if ( iOperation )
       
   528             {
       
   529             IAUPDATE_TRACE("[IAUPDATE] Operation existed");
       
   530             operationStarted = iOperation->StartOperationL();
       
   531             if ( !operationStarted )
       
   532                 {
       
   533                 IAUPDATE_TRACE("[IAUPDATE] Operation already completed successfully");
       
   534                 // Notice, we increase iSuccessCount value here
       
   535                 // even if the operation has already been finished.
       
   536                 // This is because in CompleteOperation function success count is
       
   537                 // checked to give a correct error code to observer. If we do not
       
   538                 // count already completed successes and for some reason a next type of
       
   539                 // operation in the flow is stopped (for example cancelled), then
       
   540                 // the continuation of the flow in a new try of the flow may be prevented.
       
   541                 // For example, some of the items are downloaded and some had errors. But,
       
   542                 // flow continues to install which is then cancelled. So, not all items
       
   543                 // are installed. Then flow is started again, but no new items can be
       
   544                 // downloaded because of errors. Then we need to count also previous
       
   545                 // successess to make the flow to continue to the install operations of
       
   546                 // previously cancelled items. 
       
   547                 // So, by also counting previous successes we ensure that the flow 
       
   548                 // will continue in all the cases. The downside of this is that in 
       
   549                 // some cases the flow will continue even if there is nothing to do
       
   550                 // in next type of operation, but it is better than let the flow 
       
   551                 // been locked.
       
   552                 ++iSuccessCount;
       
   553                 }
       
   554             }
       
   555 
       
   556         // Make the active object to listen operation completion.
       
   557         iStatus = KRequestPending;
       
   558         SetActive();            
       
   559 
       
   560         if ( !operationStarted )
       
   561             {
       
   562             IAUPDATE_TRACE("[IAUPDATE] Operation was not started");
       
   563             // Complete the active request now. 
       
   564             // This way a new active loop will continue.
       
   565             // We come hear when a service pack has been already fully handled,
       
   566             // or if the item operation was already finished before.
       
   567             // There should be no need to update the progress here because
       
   568             // the node operation were already done. When the total progress
       
   569             // variables were initialized during the start of the operation, 
       
   570             // already handled items were skipped also then.
       
   571             // So, skip progress handling for them also now. 
       
   572             TRequestStatus* ptrStatus = &iStatus;
       
   573             User::RequestComplete( ptrStatus, KErrNone );                        
       
   574             }
       
   575         }
       
   576     else
       
   577         {
       
   578         // No other node content to handle.
       
   579         // So, complete the whole operation.
       
   580         CompleteOperation( KErrNone );
       
   581         }
       
   582 
       
   583     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::RunL() end");
       
   584     }
       
   585     
       
   586 
       
   587 // ---------------------------------------------------------------------------
       
   588 // CIAUpdateContentOperationManager::RunError
       
   589 // 
       
   590 // ---------------------------------------------------------------------------
       
   591 // 
       
   592 TInt CIAUpdateContentOperationManager::RunError( TInt aError )
       
   593     {
       
   594     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::RunError() begin: %d",
       
   595                      aError);
       
   596 
       
   597     // By updating the purchase history here, the correct MIME type
       
   598     // is set, for example, if node is hidden. NCD Engine sets the
       
   599     // purchase history details already in its own operations but
       
   600     // we need to be sure that MIME type is set correctly according
       
   601     // to the IAD node values. Update current notde only if it was
       
   602     // not skipped.
       
   603     if ( iCurrentNode != iNode
       
   604          && aError != IAUpdateCtrlNodeConsts::KErrSkipNode )
       
   605         {
       
   606         IAUPDATE_TRACE("[IAUPDATE] Update purchase history for current node.");
       
   607         UpdatePurchaseHistory( *iCurrentNode, aError );
       
   608         }
       
   609 
       
   610     // Because, the main node is the one that is visible, its error code
       
   611     // needs to be updated here separately. So, set it by hand. If other
       
   612     // nodes were not handled, no need to update their info to purchase
       
   613     // history because they should not be shown in the history view
       
   614     // anyways.
       
   615     // Notice, that in case of service packs and other service packs 
       
   616     // inside them, also then just set the purchase history for the head
       
   617     // service pack.
       
   618     // Do not update the purchase history if the node has been skipped
       
   619     // inside a service pack. If node has been skipped during normal
       
   620     // dependency chain, then most likely UI tries to operate normal 
       
   621     // visible node whose dependency has not been completed before in
       
   622     // the update flow. Notice, that also in this case there may be some
       
   623     // hidden nodes that are installed before the main node. So, skipping
       
   624     // may also start from those hidden nodes.
       
   625     if ( aError != IAUpdateCtrlNodeConsts::KErrSkipNode
       
   626          || !IsServicePack( *iNode ) )
       
   627         {
       
   628         IAUPDATE_TRACE("[IAUPDATE] Update purchase history for main node.");
       
   629         UpdatePurchaseHistory( *iNode, aError );
       
   630         }
       
   631 
       
   632     // If the head node is service pack,
       
   633     // one error does not prevent the whole head 
       
   634     // service pack operation.
       
   635     // If the head node is not a service pack, then the operation
       
   636     // will end here. 
       
   637     // Also, do not continue with service packs either if no node
       
   638     // is left in the node array.
       
   639 
       
   640     if ( iNodes.Count() > 0 && IsServicePack( *iNode ) )
       
   641         {
       
   642         IAUPDATE_TRACE("[IAUPDATE] Service pack error accepted");
       
   643 
       
   644         // Because we are still going to continue the operation,
       
   645         // update the progrees for the error node.
       
   646         if ( !IsServicePack( *iCurrentNode ) )
       
   647             {
       
   648             // Skip service packs because their own size is zero.
       
   649             // In the progress bar point of view, just increase the
       
   650             // progress in a same way as if the operation had been completed
       
   651             // correctly.
       
   652             TInt newProgress( iCurrentMaxProgress );
       
   653             if ( newProgress == KInitProgress )
       
   654                 {
       
   655                 if ( iOperationType == EDownloadOperation )
       
   656                     {
       
   657                     TRAP_IGNORE ( newProgress += iCurrentNode->OwnContentSizeL() );
       
   658                     }
       
   659                 else
       
   660                     {
       
   661                     ++newProgress;
       
   662                     }
       
   663                 }
       
   664             // Update progress with new max values.
       
   665             // Notice, that if newProgress was left to KInitProgress,
       
   666             // the this function call will immediately return.
       
   667             UpdateProgress( newProgress, newProgress );  
       
   668             }
       
   669 
       
   670         // Continue to the next branch now that error is handled.
       
   671         IAUPDATE_TRACE("[IAUPDATE] Start new loop");
       
   672         iStatus = KRequestPending;
       
   673         SetActive();
       
   674         TRequestStatus* ptrStatus = &iStatus;
       
   675         User::RequestComplete( ptrStatus, KErrNone );
       
   676         }
       
   677     else
       
   678         {
       
   679         CompleteOperation( aError );       
       
   680         }
       
   681 
       
   682     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::RunError() end");
       
   683     
       
   684     // Return KErrNone. So, the application will not panic.
       
   685     return KErrNone;
       
   686     }
       
   687 
       
   688 
       
   689 // ---------------------------------------------------------------------------
       
   690 // CIAUpdateContentOperationManager::UpdateProgress
       
   691 // 
       
   692 // ---------------------------------------------------------------------------
       
   693 // 
       
   694 void CIAUpdateContentOperationManager::UpdateProgress( 
       
   695     TInt aProgress, TInt aMaxProgress )
       
   696     {
       
   697     IAUPDATE_TRACE_2("[IAUPDATE] CIAUpdateContentOperationManager::UpdateProgress() begin: %d, %d",
       
   698                      aProgress, aMaxProgress);
       
   699 
       
   700     if ( aProgress < 0 
       
   701          || aMaxProgress <= 0
       
   702          || ( aProgress == iCurrentProgress && aMaxProgress == iCurrentMaxProgress ) )
       
   703         {
       
   704         // Do not proceed if progress is negative or max progress is zero or less.
       
   705         // Also, do not proceed if nothing has changed.
       
   706         IAUPDATE_TRACE("[IAUPDATE] Progress values negative or zero or no changes. Return.");
       
   707         return;
       
   708         }
       
   709 
       
   710     TInt currentDif( aProgress - iCurrentProgress );
       
   711     if ( currentDif != 0 )
       
   712         {
       
   713         // Progress has occurred.
       
   714         IAUPDATE_TRACE_2("[IAUPDATE] New value for current: %d . Dif: %d", 
       
   715                          aProgress, currentDif);
       
   716         iTotalProgress += currentDif;
       
   717         IAUPDATE_TRACE_1("[IAUPDATE] New total current. Dif: %d", iTotalProgress);
       
   718         }
       
   719 
       
   720     iCurrentProgress = aProgress;
       
   721     iCurrentMaxProgress = aMaxProgress;
       
   722     if ( iCurrentProgress > iCurrentMaxProgress )
       
   723         {
       
   724         // A sanity check to be sure that max progress is at least as great as the
       
   725         // current progress.
       
   726         IAUPDATE_TRACE("[IAUPDATE] Progress was greater than max progress.");
       
   727         iCurrentMaxProgress = iCurrentProgress;
       
   728         }
       
   729 
       
   730     if ( iCurrentMaxProgress > iTotalMaxProgress )
       
   731         {
       
   732         // It seems that the total max progress has been set to too little value.
       
   733         // Update it to match the given data.
       
   734         iTotalMaxProgress = iCurrentMaxProgress;
       
   735         IAUPDATE_TRACE_1("[IAUPDATE] Current max greater than total max: %d", 
       
   736                          iTotalMaxProgress);
       
   737         }
       
   738 
       
   739     if ( iTotalProgress > iTotalMaxProgress )
       
   740         {
       
   741         // It seems that the total max progress has been set to too little value.
       
   742         // Update it to match the possible pending progress.
       
   743         iTotalMaxProgress = iTotalProgress + iCurrentMaxProgress - iCurrentProgress; 
       
   744         IAUPDATE_TRACE_1("[IAUPDATE] New total max: %d", iTotalMaxProgress);
       
   745         }
       
   746 
       
   747     IAUPDATE_TRACE("[IAUPDATE] Progress updated. Call observer.");
       
   748     iObserver->ContentOperationProgress( 
       
   749         *iCurrentNode, iTotalProgress, iTotalMaxProgress );
       
   750 
       
   751     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::UpdateProgress() end");
       
   752     }
       
   753 
       
   754 
       
   755 // ---------------------------------------------------------------------------
       
   756 // CIAUpdateContentOperationManager::CompleteOperation
       
   757 // 
       
   758 // ---------------------------------------------------------------------------
       
   759 // 
       
   760 void CIAUpdateContentOperationManager::CompleteOperation( TInt aError )
       
   761     {
       
   762     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CompleteOperation() begin: %d",
       
   763                      aError);
       
   764 
       
   765     // First do service pack related checks and settings.
       
   766     if ( IsServicePack( *iNode ) )
       
   767         {
       
   768         IAUPDATE_TRACE("[IAUPDATE] Head node is service pack");
       
   769         // Because node is a service pack, the error code that will be 
       
   770         // returned to observer needs to be checked. Notice, that if
       
   771         // an error occurred, then purchase history already contains
       
   772         // correct error code for the service pack. If everything was
       
   773         // a success, then update purchase history for the main service
       
   774         // pack. UI may use that function to get the last error value if
       
   775         // necessary. But, use KErrNone for callback parameter in all the 
       
   776         // cases. Then, the value suggests that UI may try to continue
       
   777         // the update flow.
       
   778         // Notice, here we also check self updates because they should be
       
   779         // handled from the UI before other items, such as service packs
       
   780         // are handled.
       
   781         if ( CheckNode( *iNode, ETrue ) )
       
   782             {
       
   783             IAUPDATE_TRACE("[IAUPDATE] Service pack thought as success");
       
   784             // Because no error occurred, the service pack error code
       
   785             // has not been yet set to the purchase history. So, it
       
   786             // needs to be set now.
       
   787             aError = KErrNone;
       
   788             UpdatePurchaseHistory( *iNode, aError );
       
   789             }
       
   790         else if ( iSuccessCount > 0 )
       
   791             {
       
   792             IAUPDATE_TRACE("[IAUPDATE] Some of operations were success");
       
   793             // If at least one item was successfully handled,
       
   794             // then return KErrNone in the callback function.
       
   795             // So, observer knows that update flow may continue
       
   796             // at least for some items.
       
   797             aError = KErrNone;
       
   798             }
       
   799         else
       
   800             {
       
   801             IAUPDATE_TRACE("[IAUPDATE] All item operations failed.");
       
   802             // All operations that were tried at this operation flow were failures.
       
   803             // Notice, that in preivous flows something may have been completed
       
   804             // but not now. So, set the current error code for the callback.
       
   805             // Here, use the function that gives the decoded error value
       
   806             // of the error that has been saved to purchase history for the
       
   807             // service pack.
       
   808             // The parameter value of aError is not accepted
       
   809             // because it may not give the service pack specific error
       
   810             // but, for example, the skip error of dependency chain skips.
       
   811             TRAPD ( trapError, 
       
   812                     aError = iNode->LastUpdateErrorCodeL() );
       
   813             if ( trapError != KErrNone )
       
   814                 {
       
   815                 IAUPDATE_TRACE_1("[IAUPDATE] Trap error: %d", trapError);
       
   816                 // Something failed with the error code. Maybe out of memory.
       
   817                 // So, use the trapError after this.
       
   818                 aError = trapError;
       
   819                 }
       
   820             else if ( aError == KErrNone )
       
   821                 {
       
   822                 IAUPDATE_TRACE("[IAUPDATE] Change error to KErrGeneral");
       
   823                 // Use KErrGeneral as default if the correct
       
   824                 // error code can not be gotten from the history.
       
   825                 // Also, we do not return the possible trapError.
       
   826                 // Instead, in this case, just give a vague error.
       
   827                 aError = KErrGeneral;
       
   828 
       
   829                 // Because error code was read from the history successfully
       
   830                 // to aError but it was KErrNone, try to update the history
       
   831                 // also here with the KErrGeneral.
       
   832                 UpdatePurchaseHistory( *iNode, aError );
       
   833                 }
       
   834             }
       
   835         }
       
   836 
       
   837     // Reset and set everything before calling observer complete because
       
   838     // the observer may delete this object immediately. So, take temporary
       
   839     // information for the function call.
       
   840     MIAUpdateContentOperationObserver* tmpObserver( iObserver );
       
   841     CIAUpdateNode* tmpNode( iNode );    
       
   842     
       
   843     // Observer is not needed anymore
       
   844     iObserver = NULL;    
       
   845 
       
   846     // No need for the operation anymore.
       
   847     delete iOperation;
       
   848     iOperation = NULL;
       
   849 
       
   850     // Reset the array because operations will not continue.
       
   851     iNodes.Reset();
       
   852 
       
   853     // Node not needed anymore.
       
   854     iNode = NULL;
       
   855     iCurrentNode = NULL;
       
   856 
       
   857     // Inform the observer about the completion of the operation. 
       
   858     // Give the main node as a parameter.
       
   859     tmpObserver->ContentOperationComplete( *tmpNode, aError );
       
   860 
       
   861     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CompleteOperation() end");
       
   862     }
       
   863 
       
   864 
       
   865 // ---------------------------------------------------------------------------
       
   866 // CIAUpdateContentOperationManager::ResetProgress
       
   867 // 
       
   868 // ---------------------------------------------------------------------------
       
   869 // 
       
   870 void CIAUpdateContentOperationManager::ResetProgress()
       
   871     {
       
   872     ResetCurrentProgress();
       
   873     iTotalMaxProgress = KInitProgress;
       
   874     iTotalProgress = KInitProgress;
       
   875     }
       
   876 
       
   877     
       
   878 // ---------------------------------------------------------------------------
       
   879 // CIAUpdateContentOperationManager::ResetCurrentProgress
       
   880 // 
       
   881 // ---------------------------------------------------------------------------
       
   882 // 
       
   883 void CIAUpdateContentOperationManager::ResetCurrentProgress()
       
   884     {
       
   885     iCurrentMaxProgress = KInitProgress;
       
   886     iCurrentProgress = KInitProgress;    
       
   887     }
       
   888 
       
   889 
       
   890 // ---------------------------------------------------------------------------
       
   891 // CIAUpdateContentOperationManager::InitTotalMaxProgressL
       
   892 // 
       
   893 // ---------------------------------------------------------------------------
       
   894 // 
       
   895 void CIAUpdateContentOperationManager::InitTotalMaxProgressL( 
       
   896     const CIAUpdateContentOperationManager::TContentOperationType& aOperationType )
       
   897     {
       
   898     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::InitTotalMaxProgressL() begin");
       
   899                      
       
   900     // For download operation use the given content size for expected progress values.
       
   901     // For other operations just use the node count.
       
   902     if ( aOperationType == CIAUpdateContentOperationManager::EDownloadOperation )
       
   903         {
       
   904         IAUPDATE_TRACE("[IAUPDATE] Download operation");
       
   905         // Notice, that here we do not want to include already downloaded 
       
   906         // or installed nodes into the total contant size.
       
   907         iTotalMaxProgress = 
       
   908             ArrayTotalContentSizeL( iNodes, EFalse, EFalse );
       
   909         }
       
   910     else
       
   911         {
       
   912         IAUPDATE_TRACE("[IAUPDATE] Not download operation");
       
   913         iTotalMaxProgress = iNodes.Count();        
       
   914         }
       
   915 
       
   916     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::InitTotalMaxProgressL() end: %d",
       
   917                      iTotalMaxProgress);
       
   918     }
       
   919 
       
   920 
       
   921 // ---------------------------------------------------------------------------
       
   922 // CIAUpdateContentOperationManager::ArrayTotalContentSizeL
       
   923 // 
       
   924 // ---------------------------------------------------------------------------
       
   925 //     
       
   926 TInt CIAUpdateContentOperationManager::ArrayTotalContentSizeL( 
       
   927     const RPointerArray< CIAUpdateNode >& aNodes,
       
   928     TBool aIncludeDownloaded,
       
   929     TBool aIncludeInstalled )
       
   930     {
       
   931     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateNode::ArrayTotalContentSizeL() begin");
       
   932 
       
   933     TInt totalContentSize( 0 );
       
   934 
       
   935     TInt count( aNodes.Count() );
       
   936     IAUPDATE_TRACE_1("[IAUPDATE] Node count: %d", count);
       
   937     for ( TInt i = 0; i < count; ++i )
       
   938         {
       
   939         CIAUpdateNode& node( *aNodes[ i ] );
       
   940         TBool skipNode( !aIncludeDownloaded && node.IsDownloaded()
       
   941                         || !aIncludeInstalled && node.IsInstalled()
       
   942                         || IsServicePack( node ) );
       
   943         if ( !skipNode )
       
   944             {
       
   945             IAUPDATE_TRACE_1("[IAUPDATE] Node accepted: %d", i);
       
   946             totalContentSize += node.OwnContentSizeL();           
       
   947             }
       
   948         }
       
   949 
       
   950     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateNode::ArrayTotalContentSizeL() end: %d",
       
   951                      totalContentSize);
       
   952 
       
   953     return totalContentSize;
       
   954     }
       
   955 
       
   956 
       
   957 // ---------------------------------------------------------------------------
       
   958 // CIAUpdateContentOperationManager::SetNodeArrayL
       
   959 // 
       
   960 // ---------------------------------------------------------------------------
       
   961 // 
       
   962 void CIAUpdateContentOperationManager::SetNodeArrayL( CIAUpdateNode& aNode )
       
   963     {
       
   964     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::SetNodeArrayL() begin");
       
   965     
       
   966     // Reset and put required nodes into the node array.
       
   967     // Only accept hidden dependency nodes. Skip visible nodes.
       
   968     GetOperationNodesL( aNode, iNodes, ETrue, EFalse );
       
   969 
       
   970     // Sort the created node array according to the
       
   971     // node depths. This way the operation can just use the
       
   972     // last node and there is no need to check dependencies
       
   973     // because the leaf nodes are in the end of the array after sorting.
       
   974     // This provides some what optimized way to handle things later.
       
   975     // Also, note that here trust that no loops will be in the dependency
       
   976     // chains. If loops may occur, then the depths of the nodes may not be
       
   977     // correct because in a loop there is now way to decide what is first and
       
   978     // what is last.
       
   979     SortNodeArray( iNodes );
       
   980 
       
   981     // Ownership is not taken.
       
   982     iNode = &aNode;
       
   983     iCurrentNode = NULL;
       
   984 
       
   985     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::SetNodeArrayL() end");
       
   986     }
       
   987 
       
   988 
       
   989 // ---------------------------------------------------------------------------
       
   990 // CIAUpdateContentOperationManager::HandleDependenciesL
       
   991 // 
       
   992 // ---------------------------------------------------------------------------
       
   993 // 
       
   994 void CIAUpdateContentOperationManager::HandleDependenciesL( 
       
   995     const CIAUpdateNode& aNode,
       
   996     RPointerArray< CIAUpdateNode >& aNodes,
       
   997     TBool aAcceptHiddenDependencyNodes,
       
   998     TBool aAcceptVisibleDependencyNodes )
       
   999     {
       
  1000     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::HandleDependenciesL() begin");
       
  1001     
       
  1002     if ( !aAcceptHiddenDependencyNodes && !aAcceptVisibleDependencyNodes
       
  1003          || aNodes.Find( &aNode ) != KErrNotFound )
       
  1004         {
       
  1005         // Nothing is accepted. So, no need to do anything.
       
  1006         // Or the node has already been inserted into the array, which means that
       
  1007         // branch has already been handled.
       
  1008         IAUPDATE_TRACE("[IAUPDATE] Nothing to do for this branch");
       
  1009         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::HandleDependenciesL() end");
       
  1010         return;
       
  1011         }
       
  1012 
       
  1013     // Insert all the required nodes into the array.
       
  1014     // Here we know, that the given node should be inserted into the array.
       
  1015     aNodes.AppendL( &aNode );
       
  1016 
       
  1017     // Create temporary array for the nodes that current node depends on.
       
  1018     RPointerArray< CIAUpdateNode > dependencyNodes;
       
  1019     CleanupClosePushL( dependencyNodes );
       
  1020 
       
  1021     // Get nodes that this node depends on into the temporary list.
       
  1022     aNode.GetDependencyNodesL( dependencyNodes, ETrue );
       
  1023     for ( TInt i = 0; i < dependencyNodes.Count(); ++i )
       
  1024         {
       
  1025         CIAUpdateNode& node( *dependencyNodes[ i ] );
       
  1026         if ( aAcceptHiddenDependencyNodes && node.Hidden() 
       
  1027              || aAcceptVisibleDependencyNodes && !node.Hidden() )
       
  1028             {
       
  1029             // Because node fills the criteria, handle the tree below it
       
  1030             // to get all the nodes of the dependencies.
       
  1031             HandleDependenciesL( node, aNodes, 
       
  1032                                  aAcceptHiddenDependencyNodes, 
       
  1033                                  aAcceptVisibleDependencyNodes );
       
  1034             }
       
  1035         }
       
  1036 
       
  1037     CleanupStack::PopAndDestroy( &dependencyNodes );
       
  1038 
       
  1039     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::HandleDependenciesL() end");
       
  1040     }
       
  1041 
       
  1042 
       
  1043 // ---------------------------------------------------------------------------
       
  1044 // CIAUpdateContentOperationManager::CreateOperationL
       
  1045 // 
       
  1046 // ---------------------------------------------------------------------------
       
  1047 // 
       
  1048 MIAUpdateOperation* CIAUpdateContentOperationManager::CreateOperationL(
       
  1049     const CIAUpdateContentOperationManager::TContentOperationType& aOperationType,
       
  1050     CIAUpdateNode& aNode )
       
  1051     {
       
  1052     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationL() begin");
       
  1053     
       
  1054     if ( IsServicePack( aNode ) )
       
  1055         {
       
  1056         // Because node is a service pack, no operations are
       
  1057         // created for it. So, just return the NULL value.
       
  1058         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationL() end: NULL");
       
  1059         return NULL;
       
  1060         }
       
  1061 
       
  1062     MIAUpdateOperation* operation( NULL );
       
  1063 
       
  1064     switch ( aOperationType )
       
  1065         {
       
  1066         case EPurchaseOperation:
       
  1067             operation = 
       
  1068                 CIAUpdatePurchaseOperation::NewL( aNode, *this );
       
  1069             break;
       
  1070 
       
  1071         case EDownloadOperation:
       
  1072             if ( IsServicePack( *iNode ) && !aNode.IsPurchased() )
       
  1073                 {
       
  1074                 // Already previous operation has failed.
       
  1075                 // So, skip the operation for this node.
       
  1076                 IAUPDATE_TRACE("[IAUPDATE] Skip download because not purhcased, KErrSkipNode"); 
       
  1077                 User::Leave( IAUpdateCtrlNodeConsts::KErrSkipNode );
       
  1078                 }
       
  1079             operation = 
       
  1080                 CIAUpdateDownloadOperation::NewL( aNode, *this );
       
  1081             break;
       
  1082 
       
  1083         case EInstallOperation:
       
  1084             if ( IsServicePack( *iNode ) && !aNode.IsDownloaded() )
       
  1085                 {
       
  1086                 // Already previous operation has failed.
       
  1087                 // So, skip the operation for this node.
       
  1088                 IAUPDATE_TRACE("[IAUPDATE] Skip install because not downloaded, KErrSkipNode"); 
       
  1089                 User::Leave( IAUpdateCtrlNodeConsts::KErrSkipNode );
       
  1090                 } 
       
  1091             if ( aNode.IsSelfUpdate() )
       
  1092                 {
       
  1093                 operation = 
       
  1094                     CIAUpdateSelfUpdateInitOperation::NewL( aNode, *this );
       
  1095                 }
       
  1096             else
       
  1097                 {
       
  1098                 operation = 
       
  1099                     CIAUpdateInstallOperation::NewL( aNode, *this );
       
  1100                 }
       
  1101             break;
       
  1102 
       
  1103         case ENoContentOperation:
       
  1104             // Let it be NULL.
       
  1105             // Should not ever come here.
       
  1106             break;
       
  1107 
       
  1108         default:
       
  1109             // Let it be NULL.
       
  1110             // Should not ever come here.
       
  1111             User::Leave( KErrNotSupported );
       
  1112             break;
       
  1113         }
       
  1114 
       
  1115     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CreateOperationL() end");
       
  1116 
       
  1117     return operation;
       
  1118     }
       
  1119 
       
  1120 
       
  1121 // ---------------------------------------------------------------------------
       
  1122 // CIAUpdateContentOperationManager::UpdatePurchaseHistory
       
  1123 // 
       
  1124 // ---------------------------------------------------------------------------
       
  1125 // 
       
  1126 void CIAUpdateContentOperationManager::UpdatePurchaseHistory( 
       
  1127     CIAUpdateNode& aNode, TInt aError ) const
       
  1128     {
       
  1129     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::UpdatePurchaseHistory() begin: %d",
       
  1130                      aError);
       
  1131 
       
  1132     if ( IsServicePack( aNode ) )
       
  1133         {
       
  1134         IAUPDATE_TRACE("[IAUPDATE] Is service pack");
       
  1135         // Because NCD API does not provide means to update the purchase details
       
  1136         // type, it is always EStatePurchased. So, here we edit the error code.
       
  1137         // Later, by checking the base code of the error, the correct operation
       
  1138         // can be concluded.
       
  1139         switch ( iOperationType )
       
  1140             {
       
  1141             case EDownloadOperation:
       
  1142                 IAUPDATE_TRACE("[IAUPDATE] Download operation");    
       
  1143                 aError += IAUpdateCtrlNodeConsts::KErrBaseServicePackDownload;
       
  1144                 break;
       
  1145 
       
  1146             case EInstallOperation:
       
  1147                 IAUPDATE_TRACE("[IAUPDATE] Install operation");
       
  1148                 aError += IAUpdateCtrlNodeConsts::KErrBaseServicePackInstall;
       
  1149                 break;
       
  1150 
       
  1151             default:
       
  1152                 // For purchase operations just use the default value.
       
  1153                 IAUPDATE_TRACE("[IAUPDATE] Default");
       
  1154                 break;
       
  1155             }
       
  1156         }
       
  1157 
       
  1158     // In normal cases, just update the history error value.
       
  1159     // If service pack is handled, then the error code is edited above
       
  1160     // to make it a correct value.
       
  1161     IAUPDATE_TRACE_1("[IAUPDATE] Set error to history: %d", aError);
       
  1162     TRAP_IGNORE ( aNode.SetIdleErrorToPurchaseHistoryL( aError, EFalse ) );
       
  1163 
       
  1164     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::UpdatePurchaseHistory() end");
       
  1165     }
       
  1166 
       
  1167 
       
  1168 // ---------------------------------------------------------------------------
       
  1169 // CIAUpdateContentOperationManager::IsServicePack
       
  1170 // 
       
  1171 // ---------------------------------------------------------------------------
       
  1172 // 
       
  1173 TBool CIAUpdateContentOperationManager::IsServicePack( 
       
  1174     const CIAUpdateNode& aNode )
       
  1175     {
       
  1176     return ( aNode.Type() == MIAUpdateNode::EPackageTypeServicePack );
       
  1177     }
       
  1178 
       
  1179 
       
  1180 
       
  1181 // ---------------------------------------------------------------------------
       
  1182 // CIAUpdateContentOperationManager::SetCurrentNodeL
       
  1183 // 
       
  1184 // ---------------------------------------------------------------------------
       
  1185 //
       
  1186 void CIAUpdateContentOperationManager::SetCurrentNodeL()
       
  1187     {
       
  1188     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager:SetCurrentNodeL() begin");
       
  1189     
       
  1190     // Take the node from the end of the array because root of the dependency
       
  1191     // hierarchy starts from the beginning of the array and leaves are in the end.
       
  1192     TInt index( iNodes.Count() - 1 );
       
  1193     iCurrentNode = iNodes[ index ];
       
  1194     iNodes.Remove( index );
       
  1195 
       
  1196     // In case of service packs an error does not complete the whole operation chain. 
       
  1197     // So, check here if some nodes need to be skipped because their dependencies are 
       
  1198     // not operated correctly.
       
  1199     // Also, this check is needed if UI tries to operate nodes whose dependencies
       
  1200     // were not handled successfully before.
       
  1201 
       
  1202     IAUPDATE_TRACE("[IAUPDATE] Current node is not service pack");
       
  1203 
       
  1204     RPointerArray< CIAUpdateNode > dependencies;
       
  1205     CleanupClosePushL( dependencies );
       
  1206 
       
  1207     iCurrentNode->GetDependencyNodesL( dependencies, ETrue );
       
  1208 
       
  1209     // Check all the dependencies.
       
  1210     for ( TInt i = 0; i < dependencies.Count(); ++i )
       
  1211         {
       
  1212         CIAUpdateNode& dependency( *dependencies[ i ] );
       
  1213         if ( !CheckNode( dependency, EFalse ) )
       
  1214             {
       
  1215             // In normal cases, the flow will be immediately completed 
       
  1216             // if error occurs. If we come here it means that the operation
       
  1217             // has still been continued and we are handling a service pack.
       
  1218             // Because the dependency node is reason of the error for this leaf,
       
  1219             // leave here with the specified skip error. So, later
       
  1220             // we know that the reason of the leave is this skip.
       
  1221             IAUPDATE_TRACE("[IAUPDATE] Error: KErrSkipNode");
       
  1222             User::Leave( IAUpdateCtrlNodeConsts::KErrSkipNode );
       
  1223             }
       
  1224         }
       
  1225 
       
  1226     CleanupStack::PopAndDestroy( &dependencies );        
       
  1227 
       
  1228     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager:SetCurrentNodeL() end");
       
  1229     }
       
  1230 
       
  1231 
       
  1232 // ---------------------------------------------------------------------------
       
  1233 // CIAUpdateContentOperationManager::CheckNode
       
  1234 // 
       
  1235 // ---------------------------------------------------------------------------
       
  1236 //
       
  1237 TBool CIAUpdateContentOperationManager::CheckNode( 
       
  1238     const CIAUpdateNode& aNode,
       
  1239     TBool aCheckSelfUpdate ) const
       
  1240     {
       
  1241     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateContentOperationManager::CheckNode() begin");
       
  1242 
       
  1243     TBool checkPassed( EFalse );
       
  1244 
       
  1245     if ( aNode.Hidden() )
       
  1246         {
       
  1247         IAUPDATE_TRACE("[IAUPDATE] Dependency node is hidden");
       
  1248         // In service packs and in hidden dependency chains, update flow goes 
       
  1249         // so that same operation is done to all of the items in that dependency
       
  1250         // chain before continuing to another type of operation.
       
  1251         // So, check accordingly.
       
  1252         switch ( iOperationType )
       
  1253             {
       
  1254             case EPurchaseOperation:
       
  1255                 if ( aNode.IsPurchased()
       
  1256                      || aNode.IsDownloaded() 
       
  1257                      || aNode.IsInstalled() )
       
  1258                     {
       
  1259                     // Notice, item may be in more advanced state
       
  1260                     // than is required at the moment. If operations
       
  1261                     // have been done from somewhere else. For example,
       
  1262                     // content may have been installed outside of IAD.
       
  1263                     checkPassed = ETrue;
       
  1264                     }
       
  1265                 break;
       
  1266             
       
  1267             case EDownloadOperation:
       
  1268                 if ( aNode.IsDownloaded() 
       
  1269                      || aNode.IsInstalled() )
       
  1270                     {
       
  1271                     // Notice, item may be in more advanced state
       
  1272                     // than is required at the moment. If operations
       
  1273                     // have been done from somewhere else. For example,
       
  1274                     // content may have been installed outside of IAD.
       
  1275                     checkPassed = ETrue;
       
  1276                     }
       
  1277                 break;
       
  1278                 
       
  1279             case EInstallOperation:
       
  1280                 if ( !aCheckSelfUpdate && aNode.IsSelfUpdate() )
       
  1281                     {
       
  1282                     IAUPDATE_TRACE("[IAUPDATE] Always accept self update during install");
       
  1283                     checkPassed = ETrue;
       
  1284                     }
       
  1285                 else
       
  1286                     {
       
  1287                     checkPassed = aNode.IsInstalled();
       
  1288                     }
       
  1289                 break;
       
  1290 
       
  1291             case ENoContentOperation:
       
  1292                 break;
       
  1293                 
       
  1294             default:
       
  1295                 break;
       
  1296             }        
       
  1297         }
       
  1298     else
       
  1299         {
       
  1300         IAUPDATE_TRACE("[IAUPDATE] Dependency node is visible");
       
  1301         // Because dependency node is some visible node, it should have been
       
  1302         // installed before the update flow of this node has been started.
       
  1303         // So, if dependency node is not installed, then check will fail.
       
  1304         if ( !aCheckSelfUpdate && aNode.IsSelfUpdate() )
       
  1305             {
       
  1306             IAUPDATE_TRACE("[IAUPDATE] Always accept self update during install");
       
  1307             checkPassed = ETrue;
       
  1308             }
       
  1309         else
       
  1310             {
       
  1311             checkPassed = aNode.IsInstalled();
       
  1312             }
       
  1313         }
       
  1314 
       
  1315 
       
  1316     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateContentOperationManager::CheckNode() end: %d",
       
  1317                      checkPassed);
       
  1318 
       
  1319     return checkPassed;
       
  1320     }
       
  1321