iaupdate/IAD/engine/controller/src/iaupdatecontrollerimpl.cpp
changeset 0 ba25891c3a9e
equal deleted inserted replaced
-1:000000000000 0:ba25891c3a9e
       
     1 /*
       
     2 * Copyright (c) 2007-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:   This module contains the implementation of 
       
    15 *                CIAUpdateController class member functions.
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 
       
    21 // For the NCD Engine ECOM session closing.
       
    22 #include <ecom/ecom.h>
       
    23 
       
    24 #include <catalogsuids.h>
       
    25 #include <catalogsutils.h>
       
    26 #include <catalogsengine.h>
       
    27 #include <ncdprovider.h>
       
    28 #include <ncdutils.h>
       
    29 #include <ncdconfigurationkeys.h>
       
    30 #include <ncdcapabilities.h>
       
    31 #include <ncdprogress.h>
       
    32 #include <ncdnode.h>
       
    33 #include <ncdnodecontainer.h>
       
    34 #include <ncdconnectionmethod.h>
       
    35 #include <ncdserverreportoperation.h>
       
    36 #include <ncdserverreportmanager.h>
       
    37 #include <ncdquery.h>
       
    38 #include <ncdpurchasehistory.h>
       
    39 #include <ncdutils.h>
       
    40 #include <ncdprovideroptions.h>
       
    41 #include <ncdoperation.h>
       
    42 #include <ncddownloadoperation.h>
       
    43 #include <ncderrors.h>
       
    44 
       
    45 // Required for NCD debug logging.
       
    46 #include <catalogsdebug.h>
       
    47 
       
    48 #include "iaupdatecontrollerimpl.h"
       
    49 #include "iaupdateloader.h"
       
    50 #include "iaupdatenodecontainer.h"
       
    51 #include "iaupdatenodefactory.h"
       
    52 #include "iaupdatenodeimpl.h"
       
    53 #include "iaupdatefwnodeimpl.h"
       
    54 #include "iaupdateutils.h"
       
    55 #include "iaupdatehistoryimpl.h"
       
    56 #include "iaupdateenginexmlparser.h"
       
    57 #include "iaupdateengineconfigdata.h"
       
    58 #include "iaupdatectrlconsts.h"
       
    59 #include "iaupdateprotocolconsts.h"
       
    60 #include "iaupdatectrlfileconsts.h"
       
    61 #include "iaupdateselfupdaterctrl.h"
       
    62 #include "iaupdatecontentoperationmanager.h"
       
    63 #include "iaupdatecachecleaner.h"
       
    64 #include "iaupdatecontrollerfile.h"
       
    65 #include "iaupdateridentifier.h"
       
    66 #include "iaupdateerrorcodes.h"
       
    67 #include "iaupdatetimer.h"
       
    68 #include "iaupdatedebug.h"
       
    69 
       
    70 
       
    71 // -----------------------------------------------------------------------------
       
    72 // CIAUpdateController::NewLC
       
    73 // Two-phased constructor.
       
    74 // -----------------------------------------------------------------------------
       
    75 // 
       
    76 CIAUpdateController* CIAUpdateController::NewLC( 
       
    77     const TUid& aFamilyUid, 
       
    78     MIAUpdateControllerObserver& aObserver )
       
    79     {
       
    80     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NewLC() begin");
       
    81     CIAUpdateController* self = 
       
    82         new( ELeave ) CIAUpdateController( aFamilyUid, aObserver );
       
    83     CleanupStack::PushL(self);
       
    84     self->ConstructL();
       
    85     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NewLC end");
       
    86     return self;
       
    87     }
       
    88 
       
    89 
       
    90 // -----------------------------------------------------------------------------
       
    91 // CIAUpdateController::NewL
       
    92 // Two-phased constructor.
       
    93 // -----------------------------------------------------------------------------
       
    94 //    
       
    95 CIAUpdateController* CIAUpdateController::NewL( 
       
    96     const TUid& aFamilyUid, 
       
    97     MIAUpdateControllerObserver& aObserver )
       
    98     {
       
    99     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NewL() begin");
       
   100     CIAUpdateController* self = 
       
   101         CIAUpdateController::NewLC( aFamilyUid, aObserver );
       
   102     CleanupStack::Pop( self );
       
   103     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NewL end");
       
   104     return self;
       
   105     }
       
   106 
       
   107 
       
   108 // -----------------------------------------------------------------------------
       
   109 // CIAUpdateController::CIAUpdateController
       
   110 // C++ default constructor can NOT contain any code, that
       
   111 // might leave.
       
   112 // -----------------------------------------------------------------------------
       
   113 //
       
   114 CIAUpdateController::CIAUpdateController( 
       
   115     const TUid& aFamilyUid,
       
   116     MIAUpdateControllerObserver& aObserver ) 
       
   117 : CActive( CActive::EPriorityStandard ),
       
   118   iFamilyUid( aFamilyUid ),
       
   119   iObserver( aObserver ),
       
   120   iControllerState( ENotRunning )
       
   121     {
       
   122     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CIAUpdateController() begin");
       
   123 
       
   124     // Required for NCD debug logging.
       
   125     DLINIT;
       
   126 
       
   127     CActiveScheduler::Add( this );
       
   128 
       
   129     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CIAUpdateController() end");
       
   130     }
       
   131 
       
   132 
       
   133 // -----------------------------------------------------------------------------
       
   134 // CIAUpdateController::ConstructL
       
   135 // Symbian 2nd phase constructor can leave.
       
   136 // -----------------------------------------------------------------------------
       
   137 //
       
   138 void CIAUpdateController::ConstructL()
       
   139     {
       
   140     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ConstructL() begin");
       
   141     
       
   142     iEngine = CCatalogsEngine::NewL( *this );
       
   143 
       
   144     if ( !iEngine )
       
   145         {
       
   146         IAUPDATE_TRACE("[IAUPDATE] !iEngine");
       
   147         User::Leave( KErrNotFound );
       
   148         }
       
   149     
       
   150     iNodeContainer = CIAUpdateNodeContainer::NewL( *this );
       
   151     
       
   152     iSelfUpdaterCtrl = CIAUpdateSelfUpdaterCtrl::NewL( *this );
       
   153     iContentOperationManager = CIAUpdateContentOperationManager::NewL();
       
   154 
       
   155     // Notice, that this will read the data from the file 
       
   156     // and adjust variables from the file if the file exists.
       
   157     iCacheClearFile =
       
   158         CIAUpdateControllerFile::NewL( 
       
   159             IAUpdateCtrlFileConsts::KCacheClearFile );
       
   160     
       
   161     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ConstructL() end");
       
   162     }    
       
   163    
       
   164     
       
   165 // -----------------------------------------------------------------------------
       
   166 // CIAUpdateController::~CIAUpdateController
       
   167 // Destructor
       
   168 // -----------------------------------------------------------------------------
       
   169 //    
       
   170 CIAUpdateController::~CIAUpdateController()
       
   171     {
       
   172     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::~CIAUpdateController() begin");
       
   173 
       
   174     // This is always a good thing to do with active objects.
       
   175     Cancel();
       
   176     
       
   177     // Also cancel possible report operation.
       
   178     CancelReporting();
       
   179 
       
   180     delete iReportTimer;
       
   181     delete iContentOperationManager;
       
   182     delete iLoader;    
       
   183     delete iNodeContainer;
       
   184     delete iCacheCleaner;
       
   185     delete iCacheClearFile;
       
   186         
       
   187     // Before releasing engine, be sure to release or
       
   188     // delete all other objects that may contain connetions
       
   189     // to the engine.
       
   190     
       
   191     // History uses the services that are provided throught the provider.
       
   192     // So, delete history here before releasing the provider and closing
       
   193     // the engine.
       
   194     delete iHistory;
       
   195     
       
   196     // Do not delete the contents here.
       
   197     // This array does not own the content.
       
   198     iNodes.Reset();
       
   199 
       
   200     delete iSelfUpdaterCtrl;
       
   201 
       
   202     if ( iServerReportManager )
       
   203         {
       
   204         iServerReportManager->Release();
       
   205         }
       
   206 
       
   207     if ( iProvider )
       
   208         {
       
   209         iProvider->Release();
       
   210         }
       
   211 
       
   212     if ( iBaseProvider )
       
   213         {
       
   214         iBaseProvider->Release();
       
   215         }
       
   216          
       
   217     if ( iEngine )
       
   218         {
       
   219         iEngine->Close();
       
   220         delete iEngine;
       
   221         }    
       
   222 
       
   223     // Make sure that the NCD Engine ECOM session is closed. 
       
   224     // SKD help describes this:
       
   225     // Direct users of ECOM plugins must call this method when all 
       
   226     // implementations they have created have been destroyed and they 
       
   227     // are finished using ECOM e.g. library shutdown. It will garbage 
       
   228     // collect the last previously destroyed implementation and close 
       
   229     // the REComSession if no longer in use.
       
   230     REComSession::FinalClose();
       
   231 
       
   232     // Required for NCD debug logging.
       
   233     DLUNINIT;
       
   234 
       
   235     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::~CIAUpdateController() end");
       
   236     }
       
   237 
       
   238 
       
   239 // -----------------------------------------------------------------------------
       
   240 // CIAUpdateController::FamilyUid
       
   241 //
       
   242 // -----------------------------------------------------------------------------
       
   243 //    
       
   244 const TUid& CIAUpdateController::FamilyUid() const
       
   245     {
       
   246     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::FamilyUid()");
       
   247     IAUPDATE_TRACE_1("[IAUPDATE] family uid: %x", iFamilyUid.iUid );
       
   248     return iFamilyUid;
       
   249     }
       
   250 
       
   251 
       
   252 // -----------------------------------------------------------------------------
       
   253 // CIAUpdateController::ProviderL
       
   254 // 
       
   255 // -----------------------------------------------------------------------------
       
   256 //
       
   257 MNcdProvider& CIAUpdateController::ProviderL()
       
   258     {
       
   259     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ProviderL() begin");
       
   260 
       
   261     if ( !iProvider )
       
   262         {
       
   263         User::Leave( KErrNotFound );
       
   264         }
       
   265 
       
   266     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ProviderL() end");
       
   267 
       
   268     return *iProvider;
       
   269     }
       
   270 
       
   271 
       
   272 // -----------------------------------------------------------------------------
       
   273 // CIAUpdateController::SelfUpdaterCtrl
       
   274 // 
       
   275 // -----------------------------------------------------------------------------
       
   276 //
       
   277 CIAUpdateSelfUpdaterCtrl& CIAUpdateController::SelfUpdaterCtrl()
       
   278     {
       
   279     return *iSelfUpdaterCtrl;
       
   280     }
       
   281 
       
   282 
       
   283 // -----------------------------------------------------------------------------
       
   284 // CIAUpdateController::ContentOperationManager
       
   285 // 
       
   286 // -----------------------------------------------------------------------------
       
   287 //
       
   288 CIAUpdateContentOperationManager& CIAUpdateController::ContentOperationManager()
       
   289     {
       
   290     return *iContentOperationManager;
       
   291     }
       
   292 
       
   293 
       
   294 // -----------------------------------------------------------------------------
       
   295 // CIAUpdateController::Startup
       
   296 // 
       
   297 // -----------------------------------------------------------------------------
       
   298 //
       
   299 TInt CIAUpdateController::Startup()
       
   300     {
       
   301     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::Startup() begin");
       
   302 
       
   303     if ( iControllerState == EStarting )
       
   304         {
       
   305         IAUPDATE_TRACE("[IAUPDATE] Error code: KErrInUse");        
       
   306         return KErrInUse;
       
   307         }
       
   308     else if ( iControllerState != ENotRunning )
       
   309         {
       
   310         IAUPDATE_TRACE("[IAUPDATE] Error code: KErrAlreadyExists");
       
   311         return KErrAlreadyExists;
       
   312         }
       
   313     
       
   314     // Turn off the cache cleaner because we do not want it to remove any items
       
   315     // even if allowed db size is exceeded.
       
   316     // Make sure that IMEI is send in server requests.
       
   317     // Disable HEAD requests for optimization. With SISX content this is 
       
   318     // safe to do.
       
   319     TUint32 providerOptions( ENcdProviderDisableNodeCacheCleaner
       
   320                              | ENcdProviderSendImei
       
   321                              | ENcdProviderDisableHttpHeadRequest );
       
   322     
       
   323     TInt connectErr = iEngine->Connect( FamilyUid() );
       
   324     if ( connectErr != KErrNone )
       
   325         {
       
   326         return connectErr;
       
   327         }
       
   328     
       
   329     TRAPD ( err, 
       
   330             iEngine->CreateProviderL( KNcdProviderUid, 
       
   331                                       iBaseProvider, 
       
   332                                       iStatus, 
       
   333                                       providerOptions ) );
       
   334     IAUPDATE_TRACE_1("[IAUPDATE] error code: %d", err );        
       
   335     if ( err != KErrNone )
       
   336         {
       
   337         return err;
       
   338         }
       
   339     
       
   340     SetActive();
       
   341 
       
   342     iControllerState = EStarting;
       
   343 
       
   344     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::Startup() end");
       
   345 
       
   346     return KErrNone;
       
   347     }
       
   348  
       
   349     
       
   350 // -----------------------------------------------------------------------------
       
   351 // CIAUpdateController::StartRefreshL
       
   352 //
       
   353 // -----------------------------------------------------------------------------
       
   354 //
       
   355 void CIAUpdateController::StartRefreshL( TBool aAllowNetConnection )
       
   356     {
       
   357     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::StartRefreshL() begin");
       
   358     IAUPDATE_TRACE_2("[IAUPDATE] iControllerState %d allow net connection %d", iControllerState, aAllowNetConnection );
       
   359 
       
   360     if ( iControllerState == ENotRunning )
       
   361         {
       
   362         User::Leave( KErrNotReady );
       
   363         }
       
   364     else if ( iControllerState != EIdle )
       
   365         {
       
   366         User::Leave( KErrInUse );
       
   367         }
       
   368 
       
   369     if ( !iLoader )
       
   370         {
       
   371         IAUPDATE_TRACE("[IAUPDATE] Create loader");
       
   372         iLoader = CIAUpdateLoader::NewL( *iProvider, *this );
       
   373         // For optimization reasons, skip child count refreshes.
       
   374         iLoader->SetSkipChildCountRefresh( ETrue );       
       
   375         }
       
   376 
       
   377     // Reset the node list. New one will be created when this completes. 
       
   378     // Notice, that the array content is not owned by this array.
       
   379     iNodeContainer->Clear();
       
   380     iNodes.Reset();
       
   381         
       
   382     if ( aAllowNetConnection )
       
   383         {
       
   384         IAUPDATE_TRACE("[IAUPDATE] Net connection allowed");
       
   385 
       
   386         if ( iLoader->RootExpiredL() )
       
   387             {
       
   388             IAUPDATE_TRACE("[IAUPDATE] Root has expired");
       
   389 
       
   390             // Notice, that we will clean the cache only if the
       
   391             // root load is required. Otherwise, if cache was cleaned,
       
   392             // the root would be reloaded also. Then, unwanted
       
   393             // CDB connections would occur.
       
   394             
       
   395             // Update the data from the file just in case.
       
   396             // Actually the data was already read when the object
       
   397             // was created if the file exists. But, this way we
       
   398             // can be sure that the data matches the file even if
       
   399             // in some situation the write operation has failed
       
   400             // and the object data could not be synchronized into
       
   401             // the file.
       
   402             iCacheClearFile->ReadControllerDataL();
       
   403 
       
   404             TLanguage currentLanguage = User::Language();
       
   405             TLanguage lastTimeLanguage = iCacheClearFile->Language();
       
   406             TTime lastClearTime( iCacheClearFile->RefreshTime() );
       
   407             const TTimeIntervalDays KCacheClearInterval( 
       
   408                 IAUpdateCtrlConsts::KCacheClearIntervalDays );
       
   409             TTime expireTime( lastClearTime + KCacheClearInterval );
       
   410             TTime universalTime;
       
   411             universalTime.UniversalTime();
       
   412 
       
   413             if ( currentLanguage != lastTimeLanguage
       
   414                  || expireTime < universalTime
       
   415                  || lastClearTime > universalTime  )
       
   416                 {
       
   417                 IAUPDATE_TRACE("[IAUPDATE] Clear cache");
       
   418                 // Database is expired because languages do not match
       
   419                 // or current time has passed the expiration time. 
       
   420                 // Also, sanity check is made. If last refresh time is larger 
       
   421                 // than current time, then the last refresh value has been set wrong, 
       
   422                 // and the database can be thought as expired. This might be the case 
       
   423                 // if the user has changed the time in the phone.
       
   424 
       
   425                 // Before starting to load data from the net,
       
   426                 // clear an old cache. This way files related to unfinished
       
   427                 // updates will be deleted and there is no danger of them becoming
       
   428                 // hanging data that can not be handled when old nodes are removed.
       
   429                 if ( !iCacheCleaner )
       
   430                     {
       
   431                     iCacheCleaner = CIAUpdateCacheCleaner::NewL( *iProvider );
       
   432                     }
       
   433                 iCacheCleaner->ClearL( iStatus );
       
   434                 SetActive();
       
   435                 iControllerState = EInClearCache;
       
   436                 }
       
   437             }
       
   438 
       
   439         if ( iControllerState == EIdle )
       
   440             {
       
   441             IAUPDATE_TRACE("[IAUPDATE] Refresh directly from net");
       
   442             // Because controller state is still idle, we did not start
       
   443             // cache cleaning above.
       
   444             // There is no need to clean the cache here. 
       
   445             // So, skip that step and start loading directly.     
       
   446             // This starts an asynchronous operation which will end
       
   447             // when callback is called.
       
   448             iLoader->LoadNodesL();
       
   449             iControllerState = EInLoadOperation;
       
   450             }
       
   451         }
       
   452     else
       
   453         {
       
   454         IAUPDATE_TRACE("[IAUPDATE] Start local refresh");
       
   455         // Load should be done locally.
       
   456         // So, just delegate the thing to the RunL which will handle
       
   457         // the local getting of the data in a next asynchronous step.
       
   458         iStatus = KRequestPending;
       
   459         SetActive();
       
   460         TRequestStatus* ptrStatus = &iStatus;
       
   461         User::RequestComplete( ptrStatus, KErrNone );
       
   462         iControllerState = EInLocalLoadOperation;
       
   463         }
       
   464 
       
   465     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::StartRefreshL() end");    
       
   466     }
       
   467 
       
   468         
       
   469 // -----------------------------------------------------------------------------
       
   470 // CIAUpdateController::CancelRefresh
       
   471 //
       
   472 // -----------------------------------------------------------------------------
       
   473 //
       
   474 void CIAUpdateController::CancelRefresh()
       
   475     {
       
   476     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateController::CancelRefresh() begin: %d",
       
   477                      iControllerState);
       
   478 
       
   479     switch ( iControllerState )
       
   480         {
       
   481         case EInClearCache:
       
   482             // Cache cleaner is responsible of this operation.
       
   483             iCacheCleaner->Cancel();
       
   484             break;
       
   485 
       
   486         case EInLoadOperation:
       
   487             // Loader is responsible of this operation.
       
   488             iLoader->Cancel();
       
   489             break;
       
   490 
       
   491         case EInLocalLoadOperation:
       
   492             // Use the normal cancellation of this active class because 
       
   493             // these operations are handled by this active object itself.
       
   494             Cancel();
       
   495             break;
       
   496 
       
   497         default:
       
   498             break;
       
   499         }
       
   500 
       
   501     // New state should be idle.
       
   502     iControllerState = EIdle;
       
   503 
       
   504     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CancelRefresh() end");
       
   505     }
       
   506 
       
   507 
       
   508 // -----------------------------------------------------------------------------
       
   509 // CIAUpdateController::CancelReporting
       
   510 //
       
   511 // -----------------------------------------------------------------------------
       
   512 //
       
   513 void CIAUpdateController::CancelReporting()
       
   514     {
       
   515     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CancelReport() begin");
       
   516 
       
   517     // Because report operation is cancelled, no need for the timer
       
   518     // anymore. So, delete timer if it exists. Deletion will automatically
       
   519     // cancel the timer operation. The timer may be started for some special
       
   520     // cases even if report operation was not created. So, try to delete it
       
   521     // here just in case.
       
   522     delete iReportTimer;
       
   523     iReportTimer = NULL;
       
   524 
       
   525     if ( iReportOperation )
       
   526         {
       
   527         // Set this for the callback because operation call operation complete
       
   528         // when the operation is cancelled. We do not want to call ui callback there.
       
   529         iCancellingReportOperation = ETrue;
       
   530 
       
   531         iReportOperation->CancelOperation();
       
   532 
       
   533         // Notice, that the operation complete will release the operation and set the
       
   534         // operation pointer to NULL. Do not do it here.
       
   535 
       
   536         // Set the cancelling flag to EFalse because cancell operation is finished.
       
   537         iCancellingReportOperation = EFalse;
       
   538         }
       
   539 
       
   540     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CancelReport() end");
       
   541     }
       
   542     
       
   543     
       
   544 // -----------------------------------------------------------------------------
       
   545 // CIAUpdateController::HistoryL
       
   546 //
       
   547 // -----------------------------------------------------------------------------
       
   548 //    
       
   549 MIAUpdateHistory& CIAUpdateController::HistoryL()
       
   550     {
       
   551     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::HistoryL() begin");
       
   552 
       
   553     if ( !iHistory )
       
   554         {
       
   555         iHistory = 
       
   556             CIAUpdateHistory::NewL( FamilyUid(), ProviderL() );
       
   557         }
       
   558 
       
   559     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::HistoryL() end");
       
   560 
       
   561     return *iHistory;
       
   562     }
       
   563 
       
   564 
       
   565 // -----------------------------------------------------------------------------
       
   566 // CIAUpdateController::SetDefaultConnectionMethodL
       
   567 //
       
   568 // -----------------------------------------------------------------------------
       
   569 //
       
   570 void CIAUpdateController::SetDefaultConnectionMethodL( 
       
   571     const TIAUpdateConnectionMethod& aMethod )
       
   572     {
       
   573     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::SetDefaultAccessPointL begin");
       
   574     IAUPDATE_TRACE_1("[IAUPDATE] access point: %d", aMethod.iId );
       
   575 
       
   576     if ( !iProvider )
       
   577         {
       
   578         User::Leave( KErrNotFound );
       
   579         }
       
   580 
       
   581     TNcdConnectionMethodType type( ENcdConnectionMethodTypeAlwaysAsk );
       
   582     switch ( aMethod.iType )
       
   583         {
       
   584         case TIAUpdateConnectionMethod::EConnectionMethodTypeAlwaysAsk:
       
   585             type = ENcdConnectionMethodTypeAlwaysAsk;
       
   586             break;
       
   587 
       
   588         case TIAUpdateConnectionMethod::EConnectionMethodTypeDestination:
       
   589             type = ENcdConnectionMethodTypeDestination;
       
   590             break;
       
   591 
       
   592         case TIAUpdateConnectionMethod::EConnectionMethodTypeAccessPoint:
       
   593             type = ENcdConnectionMethodTypeAccessPoint;
       
   594             break;
       
   595 
       
   596         case TIAUpdateConnectionMethod::EConnectionMethodTypeDefault:
       
   597             type = ENcdConnectionMethodTypeDefault;
       
   598             break;
       
   599 
       
   600         default:
       
   601             User::Leave( KErrNotSupported );
       
   602             break;
       
   603         }
       
   604         
       
   605     TNcdConnectionMethod method( aMethod.iId, type );
       
   606     iProvider->SetDefaultConnectionMethodL( method );
       
   607 
       
   608     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::SetDefaultAccessPointL end");
       
   609     }
       
   610 
       
   611 
       
   612 // -----------------------------------------------------------------------------
       
   613 // CIAUpdateController::SelfUpdateDataExists
       
   614 //
       
   615 // -----------------------------------------------------------------------------
       
   616 //
       
   617 TBool CIAUpdateController::SelfUpdateDataExists() const
       
   618     {
       
   619     return iSelfUpdaterCtrl->DataExists();
       
   620     }
       
   621 
       
   622 
       
   623 // -----------------------------------------------------------------------------
       
   624 // CIAUpdateController::StartPossibleSelfUpdateL
       
   625 //
       
   626 // -----------------------------------------------------------------------------
       
   627 //
       
   628 TBool CIAUpdateController::StartPossibleSelfUpdateL( 
       
   629     TInt aIndex, 
       
   630     TInt aTotalCount,
       
   631     const RPointerArray< MIAUpdateNode >& aPendingNodes,
       
   632     TBool aSilent )
       
   633     {
       
   634     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::StartPossibleSelfUpdateL");
       
   635     return SelfUpdaterCtrl().StartL( aIndex, aTotalCount, aPendingNodes, aSilent );
       
   636     }
       
   637 
       
   638 
       
   639 // -----------------------------------------------------------------------------
       
   640 // CIAUpdateController::ResetSelfUpdate
       
   641 //
       
   642 // -----------------------------------------------------------------------------
       
   643 //
       
   644 void CIAUpdateController::ResetSelfUpdate()
       
   645     {
       
   646     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ResetSelfUpdate() begin");
       
   647 
       
   648     SelfUpdaterCtrl().Reset();
       
   649 
       
   650     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ResetSelfUpdate() end");
       
   651     }
       
   652 
       
   653 
       
   654 // -----------------------------------------------------------------------------
       
   655 // CIAUpdateController::SelfUpdateRestartInfo
       
   656 //
       
   657 // -----------------------------------------------------------------------------
       
   658 //
       
   659 CIAUpdateRestartInfo* CIAUpdateController::SelfUpdateRestartInfo()
       
   660     {
       
   661     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::SelfUpdateRestartInfo");
       
   662     return SelfUpdaterCtrl().SelfUpdateRestartInfo();    
       
   663     }
       
   664 
       
   665 
       
   666 // -----------------------------------------------------------------------------
       
   667 // CIAUpdateController::NodeL
       
   668 //
       
   669 // -----------------------------------------------------------------------------
       
   670 //
       
   671 MIAUpdateNode& CIAUpdateController::NodeL( 
       
   672     const CIAUpdaterIdentifier& aIdentifier )
       
   673     {
       
   674     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeL begin");
       
   675 
       
   676     CIAUpdateNode* node( NULL );
       
   677 
       
   678     for ( TInt i = 0; i < iNodeContainer->AllNodes().Count(); ++i )
       
   679         {
       
   680         CIAUpdateNode* tmpNode( iNodeContainer->AllNodes()[ i ] );
       
   681         if ( tmpNode->MetaNamespace() == aIdentifier.Namespace()
       
   682              && tmpNode->MetaId() == aIdentifier.Id() ) 
       
   683             {
       
   684             node = tmpNode;
       
   685             break;
       
   686             }
       
   687         }
       
   688 
       
   689     if ( !node )
       
   690         {
       
   691         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeL node was not in the list");
       
   692         for ( TInt i = 0; i < iNodeContainer->ExcessNodes().Count(); ++i )
       
   693             {
       
   694             CIAUpdateNode* tmpNode( iNodeContainer->ExcessNodes()[ i ] );
       
   695             if ( tmpNode->MetaNamespace() == aIdentifier.Namespace()
       
   696                  && tmpNode->MetaId() == aIdentifier.Id() ) 
       
   697                 {
       
   698                 IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeL excess node found");
       
   699                 node = tmpNode;
       
   700                 break;
       
   701                 }
       
   702             }        
       
   703         }
       
   704 
       
   705     if ( node == NULL )
       
   706         {
       
   707         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeL create excess node");
       
   708         MNcdNode* ncdNode( NodeFromPurchaseHistoryL( aIdentifier ) );
       
   709         node = IAUpdateNodeFactory::CreateNodeLC( ncdNode, *this );
       
   710         iNodeContainer->AddExcessNodeL( node );
       
   711         CleanupStack::Pop( node );
       
   712         }
       
   713 
       
   714     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeL end");
       
   715 
       
   716     return *node;        
       
   717     }
       
   718 
       
   719 
       
   720 // -----------------------------------------------------------------------------
       
   721 // CIAUpdateController::StartingUpdatesL
       
   722 //
       
   723 // -----------------------------------------------------------------------------
       
   724 //
       
   725 void CIAUpdateController::StartingUpdatesL()
       
   726     {
       
   727     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::StartingUpdatesL begin");
       
   728 
       
   729     if ( !iServerReportManager )
       
   730         {
       
   731         IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::StartingUpdatesL not found");
       
   732         User::Leave( KErrNotFound );
       
   733         }    
       
   734 
       
   735     // Start collecting server reports because updates are going to be downloaded
       
   736     // and installed.
       
   737     // Set the reporting method to the manager method instead of letting NCD Engine
       
   738     // do sending automatically. 
       
   739     // After we have manually sent the reports, we may change the method back to 
       
   740     // automatic and let the NCD Engine to do its thing as it seems best.
       
   741     // The reason why to set the reporting method here when the updates start is that
       
   742     // if for some reason the application was not able to send all the reports last time,
       
   743     // in background mode they will be sent automatically when there is process time
       
   744     // for that, for example before starting to do new updates.
       
   745     iServerReportManager->SetReportingMethodL( MNcdServerReportManager::EReportingManaged );
       
   746 
       
   747     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::StartingUpdatesL end");
       
   748     }
       
   749 
       
   750 
       
   751 // -----------------------------------------------------------------------------
       
   752 // CIAUpdateController::FinishedUpdatesL
       
   753 //
       
   754 // -----------------------------------------------------------------------------
       
   755 //
       
   756 void CIAUpdateController::FinishedUpdatesL( 
       
   757     TBool aOperationsAllowed, TInt aMaxWaitTime )
       
   758     {
       
   759     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::FinishedUpdatesL begin");
       
   760 
       
   761     if ( !iProvider )
       
   762         {
       
   763         IAUPDATE_TRACE("[IAUPDATE] ERROR: Provider not found");
       
   764         User::Leave( KErrNotFound );
       
   765         }
       
   766 
       
   767     // Reset the timer related flag. 
       
   768     iReportTimerCompleted = EFalse;
       
   769         
       
   770     if ( aOperationsAllowed ) 
       
   771         {
       
   772         IAUPDATE_TRACE("[IAUPDATE] Operations allowed");
       
   773         if ( !iReportOperation )
       
   774             {
       
   775             IAUPDATE_TRACE("[IAUPDATE] Create operation");
       
   776             // Send the reports that have been collected.
       
   777             // Notice, that the created operation needs to be released
       
   778             // at some point.
       
   779             MNcdServerReportOperation* tmpOperation(
       
   780                 iServerReportManager->SendL( *this ) );
       
   781             if ( tmpOperation )
       
   782                 {
       
   783                 IAUPDATE_TRACE("[IAUPDATE] Start operation");
       
   784 
       
   785                 // Make sure that if the starting of the operation
       
   786                 // leaves, then the operation will be released correctly.
       
   787                 CleanupReleasePushL( *tmpOperation );
       
   788 
       
   789                 // Start the operation
       
   790                 tmpOperation->StartOperationL();
       
   791 
       
   792                 CleanupStack::Pop( tmpOperation );
       
   793 
       
   794                 // Because operation was successfully started,
       
   795                 // it can now be inserted to memeber variable.
       
   796                 iReportOperation = tmpOperation;
       
   797 
       
   798                 // Notice, that we do not Release the operation here. 
       
   799                 // We release it when the operation has finished and
       
   800                 // the callback is called.
       
   801                 }
       
   802             }
       
   803         }
       
   804 
       
   805     if ( !iReportOperation )
       
   806         {
       
   807         IAUPDATE_TRACE("[IAUPDATE] Operation was not created");
       
   808         // Set aMaxWaitTime as one. Then, we will get the timer
       
   809         // to do only one quick asynchronous loop and callback
       
   810         // is called after that. This way we make sure that
       
   811         // callback is always called even if operation is not
       
   812         // created here.
       
   813         aMaxWaitTime = 0;
       
   814         }
       
   815 
       
   816     // Create timer if needed.
       
   817     if ( aMaxWaitTime >= 0 )
       
   818         {
       
   819         IAUPDATE_TRACE_1("[IAUPDATE] Max wait time: %d", aMaxWaitTime);
       
   820         if ( !iReportTimer )
       
   821             {
       
   822             IAUPDATE_TRACE("[IAUPDATE] Create timer");
       
   823             // Timer does not exist yet. So, create new one.
       
   824             iReportTimer = CIAUpdateTimer::NewL( *this );
       
   825             }
       
   826         else
       
   827             {
       
   828             IAUPDATE_TRACE("[IAUPDATE] Cancel timer");
       
   829             // Timer already exists.
       
   830             // Cancel possible already ongoing operation
       
   831             // before starting the new one.
       
   832             iReportTimer->Cancel();
       
   833             }
       
   834         IAUPDATE_TRACE("[IAUPDATE] Start timer");
       
   835         iReportTimer->After( aMaxWaitTime );
       
   836         }
       
   837 
       
   838     // Because operation has now been started there is nothing to manage anymore.
       
   839     // So, set the NCD Engine to automatic mode. Then, if there is something to do later
       
   840     // in the background, the engine can do it when it suits it best.
       
   841     iServerReportManager->SetReportingMethodL( MNcdServerReportManager::EReportingBackground );
       
   842        
       
   843     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::FinishedUpdatesL end");
       
   844     }
       
   845 
       
   846 
       
   847 // -----------------------------------------------------------------------------
       
   848 // CIAUpdateController::LoadComplete
       
   849 //
       
   850 // -----------------------------------------------------------------------------
       
   851 //
       
   852 void CIAUpdateController::LoadComplete( TInt aError )
       
   853     {
       
   854     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::LoadComplete begin");
       
   855     IAUPDATE_TRACE_1("[IAUPDATE] error code: %d", aError );
       
   856 
       
   857     // Because node hierarchy is now concidered up-to-date,
       
   858     // get all the required nodes from the local cache to the
       
   859     // head node list that will be given to the observer.
       
   860 
       
   861     TRAPD ( trapError, LocalLoadL() );
       
   862     if ( trapError != KErrNone )
       
   863         {
       
   864         aError = trapError;        
       
   865         }
       
   866 
       
   867     // Update the state, now that everything has been done.
       
   868     iControllerState = EIdle;
       
   869 
       
   870     // Inform, the observer.            
       
   871     iObserver.RefreshComplete( iNodes, aError );
       
   872 
       
   873     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::LoadComplete end");
       
   874     }
       
   875 
       
   876 
       
   877 // -----------------------------------------------------------------------------
       
   878 // CIAUpdateController::SelfUpdaterComplete
       
   879 //
       
   880 // -----------------------------------------------------------------------------
       
   881 //
       
   882 void CIAUpdateController::SelfUpdaterComplete( TInt aErrorCode )
       
   883     {
       
   884     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateController::SelfUpdaterComplete() error code: %d", aErrorCode );
       
   885     iObserver.SelfUpdaterComplete( aErrorCode );
       
   886     }
       
   887 
       
   888 
       
   889 // -----------------------------------------------------------------------------
       
   890 // CIAUpdateController::
       
   891 //
       
   892 // -----------------------------------------------------------------------------
       
   893 //
       
   894 void CIAUpdateController::CatalogsEngineShutdown()
       
   895     {
       
   896     // IAD handles self updates in its own updater.
       
   897     // Therefore, self updates are not started by NCD Engine itself.
       
   898     // So, this callback function should be never called.  
       
   899     }
       
   900 
       
   901 
       
   902 // -----------------------------------------------------------------------------
       
   903 // CIAUpdateController::CatalogsUpdateNotification
       
   904 //
       
   905 // -----------------------------------------------------------------------------
       
   906 //
       
   907 void CIAUpdateController::CatalogsUpdateNotification( 
       
   908     const TDesC& /*aTarget*/, 
       
   909     const TDesC& /*aId*/,
       
   910     const TDesC& /*aVersion*/,
       
   911     const TDesC& /*aUri*/,
       
   912     TBool /*aForce*/ )
       
   913     {
       
   914     // Called when a Catalogs OTA update is available.
       
   915     // IAD handles self updates in its own updater.    
       
   916     // This callback function should be never called.
       
   917     }
       
   918 
       
   919 
       
   920 // -----------------------------------------------------------------------------
       
   921 // CIAUpdateController::CatalogsConnectionEvent
       
   922 //
       
   923 // -----------------------------------------------------------------------------
       
   924 //
       
   925 void CIAUpdateController::CatalogsConnectionEvent( 
       
   926     TBool /*aConnectionActive*/ )
       
   927     {
       
   928     // This callback function is called when data is transferred in the
       
   929     // network connections. IAD does not use this information for now.
       
   930     }    
       
   931 
       
   932 
       
   933 // -----------------------------------------------------------------------------
       
   934 // CIAUpdateController::ForceExpirationInformationReceived
       
   935 //
       
   936 // -----------------------------------------------------------------------------
       
   937 //
       
   938 void CIAUpdateController::ForceExpirationInformationReceived( 
       
   939     RCatalogsArray< MNcdNode >& /*aExpiredNodes*/ )
       
   940     {
       
   941     // IAD UI is not forced to be updated by the server side.
       
   942     // It is up to the UI to decide when to update its content.
       
   943     }
       
   944 
       
   945 
       
   946 // -----------------------------------------------------------------------------
       
   947 // CIAUpdateController::LocalizeString
       
   948 //
       
   949 // -----------------------------------------------------------------------------
       
   950 //
       
   951 HBufC* CIAUpdateController::LocalizeString( 
       
   952     const TDesC& /*aLocalizationKey*/ )
       
   953     {
       
   954     return NULL;
       
   955     }
       
   956 
       
   957 
       
   958 // ---------------------------------------------------------------------------
       
   959 // CIAUpdateController::ReportProgress
       
   960 // 
       
   961 // ---------------------------------------------------------------------------
       
   962 //
       
   963 void CIAUpdateController::ReportProgress( 
       
   964     MNcdServerReportOperation& /*aOperation*/, 
       
   965     TNcdProgress /*aProgress*/ )
       
   966     {
       
   967     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::ReportProgress()");
       
   968     }
       
   969 
       
   970 
       
   971 // ---------------------------------------------------------------------------
       
   972 // CIAUpdateController::QueryReceived
       
   973 // 
       
   974 // ---------------------------------------------------------------------------
       
   975 //
       
   976 void CIAUpdateController::QueryReceived( 
       
   977     MNcdServerReportOperation& aOperation, 
       
   978     MNcdQuery* aQuery )
       
   979     {
       
   980     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::QueryReceived() begin");
       
   981 
       
   982     // Install query received.
       
   983     // Always accept queries.
       
   984     // Queries should not be requested from this client.
       
   985     TInt trapError( KErrNone );
       
   986     if ( aQuery )
       
   987         {
       
   988         TRAP ( trapError, 
       
   989                aQuery->SetResponseL( MNcdQuery::EAccepted );
       
   990                aOperation.CompleteQueryL( *aQuery ); );
       
   991         // Release needs to be called to the query after it is not used.
       
   992         aQuery->Release();        
       
   993         }
       
   994 
       
   995     if ( ( trapError != KErrNone ) || ( !aQuery ) )
       
   996         {
       
   997         // Error occurred when query was handled.
       
   998         // So, operation can not continue.
       
   999         // Cancel operation. Notice, that OperationComplete will be called
       
  1000         // by the operation when cancel is called.
       
  1001         aOperation.CancelOperation();
       
  1002         }
       
  1003 
       
  1004     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::QueryReceived() end");
       
  1005     }
       
  1006 
       
  1007 
       
  1008 // ---------------------------------------------------------------------------
       
  1009 // CIAUpdateController::OperationComplete
       
  1010 // 
       
  1011 // ---------------------------------------------------------------------------
       
  1012 //
       
  1013 void CIAUpdateController::OperationComplete( 
       
  1014     MNcdServerReportOperation& aOperation, 
       
  1015     TInt aError )
       
  1016     {
       
  1017     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::OperationComplete() begin");
       
  1018 
       
  1019     // Report operation has completed.
       
  1020     
       
  1021     if ( &aOperation == iReportOperation )
       
  1022         {
       
  1023         IAUPDATE_TRACE("[IAUPDATE] Acceptable server report operation");
       
  1024 
       
  1025         // We should always come here
       
  1026         // because only one operation at a time is going on.
       
  1027 
       
  1028         // Release the operation because we do not need it anymore
       
  1029         // and because operation reference count was increased when
       
  1030         // it was created for this class object.        
       
  1031         iReportOperation->Release();
       
  1032         iReportOperation = NULL;
       
  1033 
       
  1034         // By checking if the timer has completed its job, we know if
       
  1035         // the observer should be informed about the completion of the
       
  1036         // operation. This way we will avoid duplicate callbacks, for example,
       
  1037         // after timer completion has called callback and the report operation
       
  1038         // completes after that.
       
  1039         if ( !iReportTimerCompleted )
       
  1040             {
       
  1041             IAUPDATE_TRACE("[IAUPDATE] Timer has not informed observer yet");
       
  1042 
       
  1043             // Because operation is completed, no need for the timer anymore.
       
  1044             // So, delete timer if it exists. Deletion will automatically
       
  1045             // cancel the timer operation.
       
  1046             delete iReportTimer;
       
  1047             iReportTimer = NULL;
       
  1048 
       
  1049             // Do not call callback function if cancel was started by user. 
       
  1050             if ( !iCancellingReportOperation )
       
  1051                 {
       
  1052                 IAUPDATE_TRACE("[IAUPDATE] Inform observer.");
       
  1053                 iObserver.ServerReportSent( aError );        
       
  1054                 }
       
  1055             }
       
  1056         }
       
  1057 
       
  1058     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::OperationComplete() end");
       
  1059     }
       
  1060 
       
  1061 
       
  1062 // ---------------------------------------------------------------------------
       
  1063 // CIAUpdateController::TimerComplete
       
  1064 // 
       
  1065 // ---------------------------------------------------------------------------
       
  1066 //
       
  1067 void CIAUpdateController::TimerComplete( TInt aError )
       
  1068     {
       
  1069     IAUPDATE_TRACE_1("[IAUPDATE] CIAUpdateController::TimerComplete() begin: %d",
       
  1070                      aError);
       
  1071 
       
  1072     // If we come here it means that timer has completed before
       
  1073     // the reports were actually sent and before the operation is released. 
       
  1074 
       
  1075     // Timer has done its job. So delete it.
       
  1076     delete iReportTimer;
       
  1077     iReportTimer = NULL;
       
  1078 
       
  1079     // Set the flag. Then, observer will not be informed twice when the
       
  1080     // report operation is actually completed.
       
  1081     iReportTimerCompleted = ETrue;
       
  1082 
       
  1083     // Inform the observer that it should continue even if reports are still
       
  1084     // being sent in the background. Notice, that the report operation most likely
       
  1085     // will complete later and then OperationComplete will be called.
       
  1086     iObserver.ServerReportSent( aError );
       
  1087 
       
  1088     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::TimerComplete() end");
       
  1089     }
       
  1090 
       
  1091 
       
  1092 // -----------------------------------------------------------------------------
       
  1093 // CIAUpdateController::DoCancel
       
  1094 //
       
  1095 // -----------------------------------------------------------------------------
       
  1096 //
       
  1097 void CIAUpdateController::DoCancel()
       
  1098     {
       
  1099     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::DoCancel() begin");
       
  1100     IAUPDATE_TRACE_1("[IAUPDATE] ControllerState: %d", iControllerState );
       
  1101 
       
  1102     switch ( iControllerState )
       
  1103         {
       
  1104         case EStarting:
       
  1105             {
       
  1106             // This controller is trying to create the 
       
  1107             // provider. Cancel that.
       
  1108             iEngine->CancelProviderCreation();
       
  1109             iControllerState = ENotRunning;            
       
  1110             }
       
  1111             break;
       
  1112 
       
  1113         case EInLocalLoadOperation:
       
  1114             {
       
  1115             // Local loading was cancelled. 
       
  1116             // Nothing to cancel, because complete of the request already issued
       
  1117             iControllerState = EIdle;
       
  1118             }
       
  1119             break;
       
  1120 
       
  1121         default:
       
  1122             // We should never come here.
       
  1123             break;
       
  1124         }
       
  1125 
       
  1126     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::DoCancel() end");
       
  1127     }
       
  1128 
       
  1129 
       
  1130 // -----------------------------------------------------------------------------
       
  1131 // CIAUpdateController::RunL
       
  1132 //
       
  1133 // -----------------------------------------------------------------------------
       
  1134 //
       
  1135 void CIAUpdateController::RunL()
       
  1136     {
       
  1137     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::RunL() begin");
       
  1138     IAUPDATE_TRACE_1("[IAUPDATE] ControllerState: %d", iControllerState);
       
  1139     IAUPDATE_TRACE_1("[IAUPDATE] Error code: %d", iStatus.Int());        
       
  1140 
       
  1141     // If we were trying to start the provider we may get different
       
  1142     // error codes that are still acceptable. For example, the DB may have
       
  1143     // been cleaned because of some error situation. But, then we just have
       
  1144     // to continue after that normally. 
       
  1145     // In other cases, KErrNone will inform about success.
       
  1146     // Possible feedback from the provider contains the following error
       
  1147     // codes that are interpreted as success: 
       
  1148     // KErrNone, KNcdDatabasesClearedAfterCrash, KNcdPurchaseHistoryVersionMismatch,
       
  1149     // KNcdGeneralDatabaseVersionMismatch. 
       
  1150     // Notice, that the actual error code can be a combination of these numbers.
       
  1151 
       
  1152     // Get the error code.
       
  1153     TInt errorCode( iStatus.Int() );
       
  1154  
       
  1155     // This will leave if error code is negative. 
       
  1156     // KErrNone and positive error codes are interpreted as success.
       
  1157     // If leave occurs, let RunError handle it.
       
  1158     User::LeaveIfError( errorCode );
       
  1159 
       
  1160     switch ( iControllerState )
       
  1161         {
       
  1162         case EStarting:
       
  1163             {
       
  1164             if ( !iBaseProvider )
       
  1165                 {
       
  1166                 User::Leave( KErrGeneral );
       
  1167                 }
       
  1168 
       
  1169             // Change the error code to iaupdate specific if necessary.
       
  1170             if ( errorCode > 0 )
       
  1171                 {
       
  1172                 IAUPDATE_TRACE("[IAUPDATE] NCD cache cleared. Change error code to iaupdate specific.");
       
  1173                 errorCode = IAUpdateErrorCodes::KErrCacheCleared;        
       
  1174                 }
       
  1175                 
       
  1176             iProvider = iBaseProvider->QueryInterfaceL<MNcdProvider>();
       
  1177             iProvider->SetObserver( this );
       
  1178             iProvider->SetStringLocalizer( *this );
       
  1179             
       
  1180             SetupConfigurationL();
       
  1181 
       
  1182             iServerReportManager = 
       
  1183                 iProvider->QueryInterfaceL<MNcdServerReportManager>();
       
  1184             // Because we want to send S60 error codes instead of general
       
  1185             // codes into the server, set the style here.
       
  1186             iServerReportManager->
       
  1187                 SetReportingStyleL( 
       
  1188                     MNcdServerReportManager::EReportingStyleS60 );
       
  1189 
       
  1190             // Cancel possible paused operations.
       
  1191             // So, they do not prevent others to start their operations.
       
  1192             CancelPausedOperationsL();
       
  1193             
       
  1194             // Everything was handled correctly. So, set the state and
       
  1195             // inform observer.
       
  1196             iControllerState = EIdle;            
       
  1197             iObserver.StartupComplete( errorCode );
       
  1198             }
       
  1199             break;
       
  1200 
       
  1201         case EInClearCache:
       
  1202             {
       
  1203             IAUPDATE_TRACE("[IAUPDATE] Load nodes from net.");
       
  1204             // Cache has been cleaned.
       
  1205 
       
  1206             // Save the current information to clear file.
       
  1207             iCacheClearFile->SetCurrentData();
       
  1208             iCacheClearFile->WriteControllerDataL();
       
  1209 
       
  1210             // Next, load necessary nodes from the net.
       
  1211             // This starts an asynchronous operation which will end
       
  1212             // when callback is called.
       
  1213             iLoader->LoadNodesL();
       
  1214 
       
  1215             iControllerState = EInLoadOperation;
       
  1216             }
       
  1217             break;
       
  1218 
       
  1219         case EInLocalLoadOperation:
       
  1220             {
       
  1221             // Nodes should be gotten from the local database instead of 
       
  1222             // from the internet.
       
  1223             LocalLoadL();
       
  1224                 
       
  1225             // New state should be idle because after this function
       
  1226             // everything is done and observer is informed.
       
  1227             // Notice, that the state is inserted here after all the other
       
  1228             // functionality has been handeled because if the code above leaves,
       
  1229             // then RunError will be able to check the state and handle things 
       
  1230             // correctly.
       
  1231             iControllerState = EIdle;
       
  1232 
       
  1233             // Inform, the observer.            
       
  1234             iObserver.RefreshComplete( iNodes, KErrNone );            
       
  1235             }
       
  1236             break;
       
  1237         
       
  1238         default:
       
  1239             break;
       
  1240         }
       
  1241 
       
  1242     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::RunL() end");
       
  1243     }
       
  1244   
       
  1245     
       
  1246 // -----------------------------------------------------------------------------
       
  1247 // CIAUpdateController::RunError
       
  1248 //
       
  1249 // -----------------------------------------------------------------------------
       
  1250 //    
       
  1251 TInt CIAUpdateController::RunError( TInt aError )
       
  1252     {
       
  1253     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::RunError() begin");
       
  1254     IAUPDATE_TRACE_1("[IAUPDATE] ControllerState: %d", iControllerState );
       
  1255 
       
  1256     switch ( iControllerState )
       
  1257         {
       
  1258         case EStarting:
       
  1259             iControllerState = ENotRunning;
       
  1260             iObserver.StartupComplete( aError );
       
  1261             break;
       
  1262 
       
  1263         case EInLocalLoadOperation:
       
  1264         case EInClearCache:
       
  1265             // Local load left in RunL.
       
  1266             iControllerState = EIdle;
       
  1267             iObserver.RefreshComplete( iNodes, aError );
       
  1268             break;
       
  1269 
       
  1270         default:
       
  1271             // We should not come here.
       
  1272             break;
       
  1273         }
       
  1274 
       
  1275     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::RunError() end");    
       
  1276 
       
  1277     return KErrNone;
       
  1278     }
       
  1279  
       
  1280 
       
  1281 // -----------------------------------------------------------------------------
       
  1282 // CIAUpdateController::LocalLoadL()
       
  1283 //
       
  1284 // -----------------------------------------------------------------------------
       
  1285 // 
       
  1286 void CIAUpdateController::LocalLoadL()
       
  1287     {
       
  1288     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::LocalLoadL() begin");
       
  1289 
       
  1290     MNcdNode* rootNode( iProvider->RootNodeL() );
       
  1291     if ( !rootNode )
       
  1292         {
       
  1293         IAUPDATE_TRACE("[IAUPDATE] ERROR: NULL root was given.");
       
  1294         User::Leave( KErrNotFound );
       
  1295         }
       
  1296 
       
  1297     if ( rootNode->State() == MNcdNode::EStateNotInitialized )
       
  1298         {
       
  1299         IAUPDATE_TRACE("[IAUPDATE] Root node uninitialized. Do not continue local load.");
       
  1300         rootNode->Release();
       
  1301         return;
       
  1302         }
       
  1303 
       
  1304     CleanupReleasePushL( *rootNode );
       
  1305 
       
  1306     MNcdNodeContainer* rootContainer = 
       
  1307         rootNode->QueryInterfaceLC< MNcdNodeContainer >();
       
  1308     if ( !rootContainer )
       
  1309         {
       
  1310         IAUPDATE_TRACE("[IAUPDATE] ERROR: NULL container for root.");
       
  1311         // Root should always have container interface.
       
  1312         User::Leave( KErrNotFound );
       
  1313         }
       
  1314 
       
  1315     // The given node was root node.
       
  1316 
       
  1317     LocalContainerLoadL( *rootContainer );
       
  1318 
       
  1319     CleanupStack::PopAndDestroy( rootContainer );
       
  1320     rootContainer = NULL;
       
  1321             
       
  1322     CleanupStack::PopAndDestroy( rootNode );
       
  1323     rootNode = NULL;
       
  1324 
       
  1325     // The iNodeContainer now contains all the necessary nodes.
       
  1326     // Get the nodes from the iNodeContainer.
       
  1327     // Make sure that the array is clean before adding new items.
       
  1328     iNodes.Reset();
       
  1329 
       
  1330     // Get references to the node arrays.
       
  1331     const RPointerArray< CIAUpdateFwNode >& fwNodes = 
       
  1332         iNodeContainer->FwNodes();
       
  1333     const RPointerArray< CIAUpdateNode >& headNodes = 
       
  1334         iNodeContainer->HeadNodesL();
       
  1335 
       
  1336     // Make sure we have enough memory for the array.
       
  1337     TInt fwNodeCount( fwNodes.Count() );
       
  1338     TInt headNodeCount( headNodes.Count() );
       
  1339     iNodes.ReserveL( fwNodeCount + headNodeCount );
       
  1340 
       
  1341     // Insert the firmware nodes into the beginning of the array.
       
  1342     for ( TInt i = 0; i < fwNodeCount; ++i )
       
  1343         {
       
  1344         // Notice, that the ownership is not transferred here.
       
  1345         MIAUpdateAnyNode* anyNode( fwNodes[ i ] );
       
  1346         iNodes.AppendL( anyNode );
       
  1347         }
       
  1348 
       
  1349     // Insert the head nodes into the array.
       
  1350     for ( TInt i = 0; i < headNodeCount; ++i )
       
  1351         {
       
  1352         // Notice, that the ownership is not transferred here.
       
  1353         MIAUpdateAnyNode* anyNode( headNodes[ i ] );
       
  1354         iNodes.AppendL( anyNode );
       
  1355         }
       
  1356 
       
  1357     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::LocalLoadL() end");
       
  1358     }
       
  1359 
       
  1360     
       
  1361 // -----------------------------------------------------------------------------
       
  1362 // CIAUpdateController::LocalContainerLoadL
       
  1363 //
       
  1364 // -----------------------------------------------------------------------------
       
  1365 //   
       
  1366 void CIAUpdateController::LocalContainerLoadL( 
       
  1367     MNcdNodeContainer& aContainer )
       
  1368     {
       
  1369     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::LocalContainerLoadL() begin");
       
  1370 
       
  1371     // Insert all the item children (that are not uninitilized) 
       
  1372     // from the container node into the iNodeContainer. 
       
  1373     // So, iNodeContainer will have all the item children in its list.
       
  1374     
       
  1375     TInt childCount( aContainer.ChildCount() );	        
       
  1376     IAUPDATE_TRACE_1("[IAUPDATE] childcount: %d", childCount);	        
       
  1377 
       
  1378     for ( TInt i = 0; i < childCount; ++i )
       
  1379         {
       
  1380         IAUPDATE_TRACE_1("[IAUPDATE] child index: %d", i );
       
  1381         
       
  1382         // This call increases the reference count of the child.
       
  1383         MNcdNode* child( aContainer.ChildL( i ) );
       
  1384 
       
  1385         if ( child )
       
  1386             {
       
  1387             // Notice, that we need to check if the child really exists.
       
  1388             // If a container has been loaded from the net, it has 
       
  1389             // its child count. But, children may have not been loaded.
       
  1390             IAUPDATE_TRACE("[IAUPDATE] Child was loaded.");
       
  1391             if ( child->State() == MNcdNode::EStateNotInitialized )
       
  1392                 {
       
  1393                 IAUPDATE_TRACE("[IAUPDATE] Skip uninitialized child.");
       
  1394                 // Skip uninitialized child.
       
  1395                 // Remember to release it here.
       
  1396                 child->Release();
       
  1397                 child = NULL;
       
  1398                 }
       
  1399             else
       
  1400                 {
       
  1401                 // Insert child into the cleanup stack. 
       
  1402                 // So, if functions leave, it will be released.
       
  1403                 CleanupReleasePushL( *child );
       
  1404 
       
  1405                 // Notice, that this has to be released.
       
  1406                 MNcdNodeContainer* childContainer( 
       
  1407                     child->QueryInterfaceL< MNcdNodeContainer >() );
       
  1408 
       
  1409                 if ( !childContainer )
       
  1410                     {
       
  1411                     IAUPDATE_TRACE("[IAUPDATE] Item node");            
       
  1412 
       
  1413                     TBool isFwNode( 
       
  1414                         IAUpdateNodeFactory::IsFwUpdateL( *child ) ); 
       
  1415 
       
  1416                     // Because the factory takes care of the deletion of the child object,
       
  1417                     // just pop it from the cleanup stack here. So, no release is called here.
       
  1418                     CleanupStack::Pop( child );
       
  1419 
       
  1420                     if ( isFwNode  && !IAUpdateUtils::IsFirmwareChangedL() ) 
       
  1421                         {
       
  1422                         // if phone's firmware changed after previous successfull network refresh,
       
  1423                         // firmware nodes are skipped. That's a workaround to hide them from UI just after 
       
  1424                         // firmware update. 
       
  1425                                       
       
  1426                         // Notice, that the IAUpdateNodeFactory and CIAUpdateNodeContainer 
       
  1427                         // take the ownership and release the node if the creation leaves.
       
  1428                         CIAUpdateFwNode* node( NULL );
       
  1429                         // Trap error here. 
       
  1430                         // If one node fails, others may still be created.
       
  1431                         TRAP_IGNORE( 
       
  1432                             node = IAUpdateNodeFactory::CreateFwNodeL( child, *this ) );
       
  1433                         if ( node )
       
  1434                             {
       
  1435                             IAUPDATE_TRACE("[IAUPDATE] Fw node created successfully");
       
  1436                             // If leave occurs, then AddNodeL will itself delete the created node.
       
  1437                             // So, do not insert the node into the cleanup stack here.
       
  1438                             iNodeContainer->AddFwNodeL( node );
       
  1439                             }
       
  1440                         }
       
  1441                     else
       
  1442                         {
       
  1443                         // Notice, that the IAUpdateNodeFactory and CIAUpdateNodeContainer 
       
  1444                         // take the ownership and release the node if the creation leaves.
       
  1445                         CIAUpdateNode* node( NULL );
       
  1446                         // Trap error here. 
       
  1447                         // If one node fails, others may still be created.
       
  1448                         TRAP_IGNORE( 
       
  1449                             node = IAUpdateNodeFactory::CreateNodeL( child, *this ) );
       
  1450                         if ( node )
       
  1451                             {
       
  1452                             IAUPDATE_TRACE("[IAUPDATE] Node created successfully");
       
  1453                             // If leave occurs, then AddNodeL will itself delete the created node.
       
  1454                             // So, do not insert the node into the cleanup stack here.
       
  1455                             iNodeContainer->AddNodeL( node );
       
  1456                             }
       
  1457                         }
       
  1458                     }
       
  1459                 else
       
  1460                     {
       
  1461                     IAUPDATE_TRACE("[IAUPDATE] Container node");
       
  1462 
       
  1463                     // The ownership of the child was not transferred to
       
  1464                     // anybody, the node has to be released here.
       
  1465                     CleanupStack::PopAndDestroy( child );
       
  1466 
       
  1467                     CleanupReleasePushL( *childContainer );
       
  1468 
       
  1469                     // Because this is a container, use recursion to insert its
       
  1470                     // child items into the node container.
       
  1471                     LocalContainerLoadL( *childContainer );
       
  1472 
       
  1473                     CleanupStack::PopAndDestroy( childContainer );
       
  1474                     }
       
  1475                 }
       
  1476             }
       
  1477         }
       
  1478     
       
  1479     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::LocalContainerLoadL() begin");
       
  1480     }
       
  1481 
       
  1482 
       
  1483 // -----------------------------------------------------------------------------
       
  1484 // CIAUpdateController::SetupConfigurationL
       
  1485 //
       
  1486 // -----------------------------------------------------------------------------
       
  1487 // 
       
  1488 void CIAUpdateController::SetupConfigurationL()
       
  1489     {
       
  1490     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::SetupConfigurationL() begin");
       
  1491 
       
  1492     CIAUpdateEngineXmlParser* parser( CIAUpdateEngineXmlParser::NewLC() );
       
  1493     parser->ParseL();
       
  1494     const CIAUpdateEngineConfigData& data( parser->ConfigData() );
       
  1495 
       
  1496     CNcdKeyValuePair* pair( NULL );
       
  1497     
       
  1498 
       
  1499     // Master server (CDB) uri
       
  1500     IAUPDATE_TRACE_1("[IAUPDATE] master server: %S", &data.MasterServerUri() );
       
  1501     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KMasterServer(), 
       
  1502                                     data.MasterServerUri() );
       
  1503     iProvider->AddConfigurationL( *pair );
       
  1504     CleanupStack::PopAndDestroy( pair );
       
  1505         
       
  1506     // Max storage size
       
  1507     // Notice, this value does not have any effect if the cache cleaner is
       
  1508     // turned off when provider is created.
       
  1509     const TDesC& storageMaxSize( data.StorageMaxSize() );
       
  1510     if ( storageMaxSize == KNullDesC )
       
  1511         {
       
  1512         IAUPDATE_TRACE("[IAUPDATE] Use default storage max size");
       
  1513         pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KMaxStorageSize(), 
       
  1514                                         IAUpdateCtrlConsts::KDefaultStorageMaxSize() );
       
  1515         }
       
  1516     else
       
  1517         {
       
  1518         IAUPDATE_TRACE("[IAUPDATE] Use config file storage max size");
       
  1519         pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KMaxStorageSize(), 
       
  1520                                         storageMaxSize );        
       
  1521         }
       
  1522     iProvider->AddConfigurationL( *pair );
       
  1523     CleanupStack::PopAndDestroy( pair );
       
  1524 
       
  1525     // Software version
       
  1526     // Notice, that here we use the hardcoded value instead of parsing the data
       
  1527     // from the configuration XML file. This should be hardcoded value because the
       
  1528     // version number is strictly related to the version of the engine. So, the version
       
  1529     // should not be altered by different configuration files.
       
  1530     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KSoftwareVersion(), 
       
  1531                                     IAUpdateCtrlConsts::KSoftwareVersion() );
       
  1532     iProvider->AddConfigurationL( *pair );
       
  1533     CleanupStack::PopAndDestroy( pair );
       
  1534     
       
  1535     // Software type
       
  1536     // Notice, that here we use the hardcoded value instead of parsing the data
       
  1537     // from the configuration XML file. This should be hardcoded value because the
       
  1538     // software type is always same for the engine. It should not be allowed to
       
  1539     // change by defining new value in config file.
       
  1540     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KSoftwareType(), 
       
  1541                                     IAUpdateCtrlConsts::KSoftwareType() );
       
  1542     iProvider->AddConfigurationL( *pair );
       
  1543     CleanupStack::PopAndDestroy( pair );
       
  1544 
       
  1545     // Provisioning
       
  1546     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KProvisioning(), 
       
  1547                                     data.Provisioning() );
       
  1548     iProvider->AddConfigurationL( *pair );
       
  1549     CleanupStack::PopAndDestroy( pair );
       
  1550 
       
  1551     // Client role
       
  1552     // This value is used in the server requests.
       
  1553     pair = CNcdKeyValuePair::NewLC( IAUpdateProtocolConsts::KIAClientRole(), 
       
  1554                                     data.ClientRole() );
       
  1555     iProvider->AddConfigurationL( *pair );
       
  1556     CleanupStack::PopAndDestroy( pair );
       
  1557     iObserver.ClientRole( data.ClientRole() );
       
  1558 
       
  1559 
       
  1560     // No need for the parser anymore.
       
  1561     CleanupStack::PopAndDestroy( parser );
       
  1562     parser = NULL;
       
  1563 
       
  1564     
       
  1565     // Language
       
  1566     TLanguage language( User::Language() );
       
  1567     HBufC* languageDes( HBufC::NewLC( 32 ) );
       
  1568     TPtr languagePtr( languageDes->Des() );
       
  1569     languagePtr.AppendNum( language );
       
  1570     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KSoftwareLanguage(), 
       
  1571                                     languagePtr );
       
  1572     iProvider->AddConfigurationL( *pair );
       
  1573     CleanupStack::PopAndDestroy( pair );
       
  1574     CleanupStack::PopAndDestroy( languageDes );
       
  1575 
       
  1576 
       
  1577     // Capabilities accepted by the client.
       
  1578     // These capabilities define actions between the client and the server.
       
  1579     
       
  1580     // Download report
       
  1581     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KCapability(),
       
  1582                                     NcdCapabilities::KDownloadReport() );
       
  1583     iProvider->AddConfigurationL( *pair );
       
  1584     CleanupStack::PopAndDestroy( pair );
       
  1585     
       
  1586     // Install report
       
  1587     pair = CNcdKeyValuePair::NewLC( NcdConfigurationKeys::KCapability(),
       
  1588                                     NcdCapabilities::KInstallationReport() );
       
  1589     iProvider->AddConfigurationL( *pair );
       
  1590     CleanupStack::PopAndDestroy( pair );
       
  1591 
       
  1592     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::SetupConfigurationL() end");
       
  1593     }
       
  1594 
       
  1595 
       
  1596 // -----------------------------------------------------------------------------
       
  1597 // CIAUpdateController::NodeFromPurchaseHistoryL
       
  1598 //
       
  1599 // -----------------------------------------------------------------------------
       
  1600 //
       
  1601 MNcdNode* CIAUpdateController::NodeFromPurchaseHistoryL( 
       
  1602     const CIAUpdaterIdentifier& aIdentifier )
       
  1603     {
       
  1604     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeFromPurchaseHistoryL() begin");
       
  1605 
       
  1606     // This will contain the correct details object.
       
  1607     CNcdPurchaseDetails* details( NULL );
       
  1608 
       
  1609     // Create filter. So, we will get
       
  1610     // all the purchase history items.
       
  1611     CNcdPurchaseHistoryFilter* filter =
       
  1612         CNcdPurchaseHistoryFilter::NewLC();
       
  1613     filter->SetNamespaceL( aIdentifier.Namespace() );
       
  1614     filter->SetEntityIdL( aIdentifier.Id() );
       
  1615     
       
  1616     // Add family uid to the filter
       
  1617     RArray< TUid > uids;
       
  1618     CleanupClosePushL( uids );
       
  1619     uids.AppendL( FamilyUid() );
       
  1620     filter->SetClientUids( uids.Array() );
       
  1621     CleanupStack::PopAndDestroy( &uids );
       
  1622 
       
  1623     MNcdPurchaseHistory* history( ProviderL().PurchaseHistoryL() );
       
  1624     CleanupReleasePushL( *history );
       
  1625     
       
  1626     // Get the ids. So, we can next get all the corresponding
       
  1627     // details.
       
  1628     RArray< TUint > ids = history->PurchaseIdsL( *filter );
       
  1629     // Temporarily remove history from cleanup stack
       
  1630     CleanupStack::Pop( history );
       
  1631     CleanupStack::PopAndDestroy( filter );
       
  1632     CleanupReleasePushL( *history );
       
  1633     CleanupClosePushL( ids );
       
  1634     
       
  1635     if ( ids.Count() > 0 )
       
  1636         {
       
  1637         // If purchase details exist, then use the most up-to-date one.
       
  1638         details = 
       
  1639             history->PurchaseDetailsL( ids[ 0 ], EFalse );
       
  1640         }
       
  1641     
       
  1642     CleanupStack::PopAndDestroy( &ids );
       
  1643     CleanupStack::PopAndDestroy( history );
       
  1644     
       
  1645     if ( details == NULL )
       
  1646         {
       
  1647         User::Leave( KErrNotFound );
       
  1648         }
       
  1649     else
       
  1650         {
       
  1651         // The details was created but not inserted into
       
  1652         // the cleanup stack there. Insert it into the cleanupstack now.
       
  1653         CleanupStack::PushL( details );
       
  1654         }
       
  1655 
       
  1656     MNcdNode* node( ProviderL().NodeL( *details ) );
       
  1657     if ( node == NULL )
       
  1658         {
       
  1659         User::Leave( KErrNotFound );
       
  1660         }
       
  1661 
       
  1662     CleanupStack::PopAndDestroy( details );
       
  1663 
       
  1664     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::NodeFromPurchaseHistoryL() end");
       
  1665 
       
  1666     return node;
       
  1667     }
       
  1668 
       
  1669 
       
  1670 // -----------------------------------------------------------------------------
       
  1671 // CIAUpdateController::NodeFromPurchaseHistoryL
       
  1672 //
       
  1673 // -----------------------------------------------------------------------------
       
  1674 //
       
  1675 void CIAUpdateController::CancelPausedOperationsL()
       
  1676     {
       
  1677     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CancelPausedOperationsL() begin");
       
  1678     
       
  1679     // Cancel possible paused operations here.
       
  1680     // IAD Engine does not itself pause operations. 
       
  1681     // But, in some error cases download operation may have become paused.
       
  1682     // By cancelling a paused operation, we can avoid locking if multiple IAD UIs 
       
  1683     // are opened. Else, the paused operations that belong to first opened UI 
       
  1684     // will block the starting of the operations from another IAD UIs.
       
  1685     // Because these operations are created for the one IAD, 
       
  1686     // they will be blocking other UI operations because multiple 
       
  1687     // simultaneous operations are not allowed for same metadata content.
       
  1688     // When the IAD is started, the operations that are paused will be
       
  1689     // created in the NCD Provider and they are part of that IAD UI via NCD
       
  1690     // Provider Proxy.
       
  1691     
       
  1692     // Notice, Release needs to be called for array elements.
       
  1693     RCatalogsArray< MNcdOperation > operations = 
       
  1694         iProvider->OperationsL();
       
  1695 
       
  1696     // Push the array into the cleanupstack. So, PopAndDestroy will
       
  1697     // call Release to the array items and finally reset the array.
       
  1698     CleanupResetAndDestroyPushL( operations );
       
  1699         
       
  1700     TInt count( operations.Count() );
       
  1701     IAUPDATE_TRACE_1("[IAUPDATE] Pending operation count: %d", count);
       
  1702     for ( TInt i = 0; i < count; ++i )
       
  1703         {
       
  1704         MNcdOperation* operation( operations[ i ] );
       
  1705         MNcdDownloadOperation* download( 
       
  1706             operation->QueryInterfaceLC< MNcdDownloadOperation >() );
       
  1707         if ( download && download->IsPaused() )
       
  1708             {
       
  1709             // A download operation has been left hanging as paused.
       
  1710             // Just, cancel it. So, it will not prevent possible other
       
  1711             // download attempts from other IAD UIs. We cancel this operations
       
  1712             // already now, because we may not actually start it later in this
       
  1713             // UI.
       
  1714             IAUPDATE_TRACE_1("[IAUPDATE] Cancel paused operation: %d", i);
       
  1715             operation->CancelOperation();
       
  1716             CleanupStack::PopAndDestroy( download );
       
  1717             }
       
  1718         }
       
  1719     
       
  1720     // This will Release array elements and reset the array.
       
  1721     CleanupStack::PopAndDestroy( &operations );
       
  1722 
       
  1723     IAUPDATE_TRACE("[IAUPDATE] CIAUpdateController::CancelPausedOperationsL() begin");
       
  1724     }