ncdengine/provider/server/src/ncdreportmanager.cpp
changeset 4 32704c33136d
equal deleted inserted replaced
-1:000000000000 4:32704c33136d
       
     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:   CNcdReportManager implementation
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include "ncdreportmanager.h"
       
    20 
       
    21 #include "ncdoperationobserver.h"
       
    22 
       
    23 // Supported reports
       
    24 #include "ncdreportdownload.h"
       
    25 #include "ncdreportomadownload.h"
       
    26 #include "ncdreportinstall.h"
       
    27 
       
    28 #include "ncdproviderdefines.h"
       
    29 #include "ncdproviderutils.h"
       
    30 #include "ncdpanics.h"
       
    31 #include "ncdnodeidentifier.h"
       
    32 #include "ncdconfigurationmanager.h"
       
    33 #include "ncdserverdetails.h"
       
    34 #include "ncdgeneralmanager.h"
       
    35 
       
    36 // Protocol
       
    37 #include "ncdprotocol.h"
       
    38 #include "ncdrequestgenerator.h"
       
    39 #include "ncdrequestinstallation.h"
       
    40 #include "ncdcapabilities.h"
       
    41 #include "ncdprotocol.h"
       
    42 
       
    43 // Storage
       
    44 #include "ncdstorage.h"
       
    45 #include "ncddatabasestorage.h"
       
    46 #include "ncdstoragemanager.h"
       
    47 #include "ncdstorageitem.h"
       
    48 #include "ncdstoragedataitem.h"
       
    49 
       
    50 #include "catalogscontext.h"
       
    51 #include "catalogsutils.h"
       
    52 
       
    53 // HTTP
       
    54 #include "catalogshttpincludes.h"
       
    55 #include "catalogshttptransaction.h"
       
    56 #include "catalogshttpsessionmanagerimpl.h"
       
    57 #include "catalogsnetworkmanager.h"
       
    58 #include "catalogshttpconnectionmanager.h"
       
    59 
       
    60 #include "catalogsdebug.h"
       
    61 
       
    62 
       
    63 void CNcdReportManager::ReportIdToDescriptor( 
       
    64     const TNcdReportId& aId, TDes& aTarget )
       
    65     {                
       
    66     aTarget.Num( aId );
       
    67     }
       
    68 
       
    69 
       
    70 // ---------------------------------------------------------------------------
       
    71 // NewL
       
    72 // ---------------------------------------------------------------------------
       
    73 CNcdReportManager* CNcdReportManager::NewL(
       
    74     const MCatalogsContext& aContext,   
       
    75     CNcdGeneralManager& aGeneralManager,
       
    76     MCatalogsHttpSession& aHttpSession,
       
    77     TBool aClientCrashed )
       
    78     {
       
    79     CNcdReportManager* self = new(ELeave) CNcdReportManager(
       
    80         aContext,
       
    81         aGeneralManager,
       
    82         aHttpSession,
       
    83         aClientCrashed );
       
    84         
       
    85     CleanupStack::PushL( self );
       
    86     self->ConstructL();
       
    87     CleanupStack::Pop( self );
       
    88     return self;
       
    89     }
       
    90     
       
    91 
       
    92 // ---------------------------------------------------------------------------
       
    93 // Destructor
       
    94 // ---------------------------------------------------------------------------
       
    95 CNcdReportManager::~CNcdReportManager()
       
    96     {
       
    97     DLTRACEIN((""));
       
    98     CancelReportSending();
       
    99     Cancel();
       
   100     
       
   101     iReports.ResetAndDestroy();
       
   102     if ( iNetworkManager )
       
   103         {        
       
   104         iNetworkManager->RemoveObserver( *this );
       
   105         }
       
   106     }
       
   107 
       
   108 
       
   109 // ---------------------------------------------------------------------------
       
   110 //
       
   111 // ---------------------------------------------------------------------------
       
   112 //
       
   113 void CNcdReportManager::SetReportingMethod( const MNcdServerReportManager::TReportingMethod& aMethod )
       
   114     {
       
   115     DLTRACEIN((""));
       
   116     // Here we create a copy of the member variable for later comparison. Notice, that
       
   117     // we crete a copy instead of a reference because if reference was used then the value of the
       
   118     // variable would change when iReporting is changed.
       
   119     MNcdServerReportManager::TReportingMethod tmpMethod( iReportingMethod ); 
       
   120     iReportingMethod = aMethod;
       
   121 
       
   122     if ( tmpMethod != iReportingMethod
       
   123          && iReportingMethod == MNcdServerReportManager::EReportingBackground
       
   124          && iManagerState == ENcdReportManagerIdle
       
   125          && iTransactions.Count() == 0 )
       
   126         {
       
   127         // If reporting method was changed to background method,
       
   128         // then try one loop to send the reports now, instead of waiting for the next report setting.
       
   129         // Also, transactions are checked to be sure that no pending transactions exist and
       
   130         // to check if all HTTP operations are completed yet.
       
   131         // Probably there is not anything to send, but just in case.
       
   132         // This setting will also start the RunL loop for the sending.
       
   133         TRAP_IGNORE( SetManagerStateL( ENcdReportManagerPreparing ) );
       
   134         }
       
   135     }
       
   136     
       
   137     
       
   138 // ---------------------------------------------------------------------------
       
   139 //
       
   140 // ---------------------------------------------------------------------------
       
   141 //
       
   142 const MNcdServerReportManager::TReportingMethod& CNcdReportManager::ReportingMethod() const
       
   143     {
       
   144     DLTRACEIN((""));
       
   145     return iReportingMethod;
       
   146     }
       
   147 
       
   148 
       
   149 // ---------------------------------------------------------------------------
       
   150 //
       
   151 // ---------------------------------------------------------------------------
       
   152 //
       
   153 void CNcdReportManager::SetReportingStyle( const MNcdServerReportManager::TReportingStyle& aStyle )
       
   154     {
       
   155     DLTRACEIN((""));
       
   156     iReportingStyle = aStyle;
       
   157     }
       
   158     
       
   159     
       
   160 // ---------------------------------------------------------------------------
       
   161 //
       
   162 // ---------------------------------------------------------------------------
       
   163 //
       
   164 const MNcdServerReportManager::TReportingStyle& CNcdReportManager::ReportingStyle() const
       
   165     {
       
   166     DLTRACEIN((""));
       
   167     return iReportingStyle;
       
   168     }
       
   169 
       
   170 
       
   171 // ---------------------------------------------------------------------------
       
   172 //
       
   173 // ---------------------------------------------------------------------------
       
   174 //
       
   175 void CNcdReportManager::StartSendReportsL( MNcdOperationObserver& aObserver )
       
   176     {
       
   177     DLTRACEIN((""));
       
   178 
       
   179     if ( iObserver != NULL )
       
   180         {
       
   181         // Operation is already going on and observer is set.
       
   182         User::Leave( KErrInUse );
       
   183         }
       
   184     else if ( iReportingMethod != MNcdServerReportManager::EReportingManaged )
       
   185         {
       
   186         // This function should be called only for managed reports.
       
   187         User::Leave( KErrArgument );
       
   188         }
       
   189     else if ( iManagerState != ENcdReportManagerIdle
       
   190               || iTransactions.Count() > 0 )
       
   191         {
       
   192         // This case may occur if the reporting method has just been changed and
       
   193         // there was still an automated operation pending when sending was asked
       
   194         // by the manager.
       
   195         // Because observer was not set, then set it here.
       
   196         // Observers are set only when reporting is managed.
       
   197         // For automated reporting observers are not used.
       
   198         // Also, transactions are checked to be sure that no pending transactions exist and
       
   199         // to check if all HTTP operations are completed yet.
       
   200         // Notice, that ownership is not transferred here.
       
   201         iObserver = &aObserver;
       
   202         return;
       
   203         }
       
   204     else
       
   205         {
       
   206         // We are having a managed report and operation is in idle state.
       
   207         // So, start the action.
       
   208         SetManagerStateL( ENcdReportManagerPreparing );
       
   209         // Notice, that ownership is not transferred here.
       
   210         iObserver = &aObserver;
       
   211         }
       
   212     }
       
   213 
       
   214 
       
   215 // ---------------------------------------------------------------------------
       
   216 //
       
   217 // ---------------------------------------------------------------------------
       
   218 TNcdReportId CNcdReportManager::RegisterDownloadL(
       
   219     const TDesC& aUri,
       
   220     const CNcdNodeIdentifier& aMetadataId,
       
   221 	const TNcdReportStatusInfo& aStatus, 
       
   222 	const TDesC& aReportUri,
       
   223 	const TDesC& aReportNamespace )
       
   224     {
       
   225     DLTRACEIN(( _L("aUri: %S, aStatus: %d"), &aUri, aStatus.iStatus ));
       
   226 
       
   227     // Check if the download has already been registered
       
   228     CNcdReport* report = FindReport( 
       
   229         aUri, 
       
   230         aMetadataId, 
       
   231         aReportUri,
       
   232         ENcdReportDownload, 
       
   233         iReports );
       
   234 
       
   235     // Use old report only if it can still be updated with a new
       
   236     // status before sending. We don't want to overwrite any pending 
       
   237     // cancellation/failure/success reports
       
   238     if ( report && !report->StatusIsFinal() ) 
       
   239         {
       
   240         DLTRACEOUT(("Download has already been registered"));
       
   241         report->Attributes().SetAttributeL( 
       
   242             ENcdReportAttributeIsUsed, ETrue );
       
   243         
       
   244         return report->ReportId();
       
   245         }
       
   246         
       
   247     report = NULL;
       
   248     
       
   249     TBool serverSupports = ServerSupportsReports( 
       
   250         ENcdReportDownload,
       
   251         aReportUri, 
       
   252         aReportNamespace );
       
   253     
       
   254     if ( serverSupports ) 
       
   255         {        
       
   256         DLTRACE(("Server supports download reports"));
       
   257         report = CNcdReportDownload::NewLC( 
       
   258             *this,
       
   259             aUri, 
       
   260             aMetadataId,
       
   261             aStatus,
       
   262             aReportUri,
       
   263             aReportNamespace );
       
   264 
       
   265         iReports.InsertInOrderAllowRepeatsL( 
       
   266             report, 
       
   267             TLinearOrder<CNcdReport>( CNcdReport::Compare ) );
       
   268 
       
   269         CleanupStack::Pop( report );
       
   270         report->SetReportId( GenerateReportId() );
       
   271         report->Attributes().SetAttributeL( 
       
   272             ENcdReportAttributeIsUsed, ETrue );
       
   273         
       
   274         DLTRACEOUT(("Report added"));        
       
   275         return report->ReportId();
       
   276         }
       
   277 
       
   278     return KNcdReportNotSupported;
       
   279     }
       
   280 
       
   281 
       
   282 // ---------------------------------------------------------------------------
       
   283 //
       
   284 // ---------------------------------------------------------------------------
       
   285 TNcdReportId CNcdReportManager::RegisterOmaDownloadL(
       
   286     const TDesC& aUri,
       
   287     const CNcdNodeIdentifier& aMetadataId,
       
   288 	const TNcdReportStatusInfo& aStatus, 	
       
   289 	const TDesC& aReportUri )
       
   290     {
       
   291     DLTRACEIN(( _L("aUri: %S, aStatus: %d"), &aUri, aStatus.iStatus ));       
       
   292 
       
   293     // Check if the download has already been registered
       
   294     CNcdReport* report = FindReport( 
       
   295         aUri, 
       
   296         aMetadataId, 
       
   297         aReportUri,
       
   298         ENcdReportOmaDownload,
       
   299         iReports );
       
   300     
       
   301     // Use old report only if it can still be updated with a new
       
   302     // status before sending    
       
   303     if ( report && !report->StatusIsFinal() ) 
       
   304         {
       
   305         
       
   306         DLTRACEOUT(("Download has already been registered"));
       
   307         report->Attributes().SetAttributeL( 
       
   308             ENcdReportAttributeIsUsed, ETrue );
       
   309         
       
   310         return report->ReportId();
       
   311         }
       
   312         
       
   313     report = NULL;
       
   314     
       
   315     DLTRACE(("Server supports download reports"));
       
   316     report = CNcdReportOmaDownload::NewLC( 
       
   317         *this,
       
   318         aUri, 
       
   319         aMetadataId,
       
   320         aStatus,
       
   321         aReportUri );
       
   322 
       
   323     iReports.InsertInOrderAllowRepeatsL( 
       
   324         report, 
       
   325         TLinearOrder<CNcdReport>( CNcdReport::Compare ) );
       
   326 
       
   327     CleanupStack::Pop( report );    
       
   328     report->SetReportId( GenerateReportId() );
       
   329     report->Attributes().SetAttributeL( 
       
   330         ENcdReportAttributeIsUsed, ETrue );
       
   331     
       
   332     DLTRACEOUT(("Report added"));
       
   333     return report->ReportId();
       
   334     }
       
   335     
       
   336 
       
   337 // ---------------------------------------------------------------------------
       
   338 //
       
   339 // ---------------------------------------------------------------------------
       
   340 TInt CNcdReportManager::SetDownloadReportAccessPoint( 
       
   341     const TNcdReportId& aReportId,    
       
   342     const TCatalogsConnectionMethod& aAccessPoint )
       
   343     {
       
   344     DLTRACEIN(("aAccessPoint: %d", aAccessPoint.iId ));
       
   345 
       
   346     CNcdReport* report = FindReport( 
       
   347         aReportId,
       
   348         iReports );
       
   349         
       
   350     if ( !report ) 
       
   351         {
       
   352         DLERROR(("Download has not been been registered"));
       
   353         return KErrNotFound;
       
   354         }
       
   355 
       
   356     report->SetAccessPoint( aAccessPoint );
       
   357     
       
   358     DLTRACEOUT(("Access point set successfully"));
       
   359     return KErrNone;
       
   360     }
       
   361 
       
   362 
       
   363 // ---------------------------------------------------------------------------
       
   364 //
       
   365 // ---------------------------------------------------------------------------
       
   366 void CNcdReportManager::ReportDownloadStatusL( 
       
   367     const TNcdReportId& aReportId,
       
   368     const TNcdReportStatusInfo& aStatus,
       
   369     TBool aSendable )
       
   370     {
       
   371     DLTRACEIN(("aStatus: %d", aStatus.iStatus ));
       
   372     
       
   373     CNcdReport* report = FindReport( 
       
   374         aReportId,
       
   375         iReports );
       
   376     
       
   377     if ( !report ) 
       
   378         {
       
   379         DLERROR(("Report not found"));
       
   380         return;
       
   381         }    
       
   382         
       
   383     SetReportStatusL( *report, aStatus, aSendable );
       
   384     }
       
   385 
       
   386 
       
   387 // ---------------------------------------------------------------------------
       
   388 //
       
   389 // ---------------------------------------------------------------------------
       
   390 TNcdReportId CNcdReportManager::RegisterInstallL(
       
   391     const TDesC& aContentIdentifier,
       
   392     const CNcdNodeIdentifier& aMetadataId,
       
   393 	const TNcdReportStatusInfo& aStatus, 
       
   394 	const TDesC& aReportUri,
       
   395 	const TDesC& aReportNamespace )
       
   396     {
       
   397     DLTRACEIN(( _L("aReportUri: %S, aStatus: %d"), &aReportUri, aStatus.iStatus ));
       
   398 
       
   399     // Check if the install has already been registered.
       
   400     CNcdReport* report = FindReport( 
       
   401         aContentIdentifier,
       
   402         aMetadataId, 
       
   403         aReportUri,
       
   404         ENcdReportInstall,
       
   405         iReports );
       
   406         
       
   407     if ( report && !report->StatusIsFinal() ) 
       
   408         {
       
   409         DLTRACEOUT(("Install has already been registered"));
       
   410         report->Attributes().SetAttributeL( 
       
   411             ENcdReportAttributeIsUsed, ETrue );
       
   412         
       
   413         return report->ReportId();
       
   414         }        
       
   415     
       
   416     TBool serverSupports = ServerSupportsReports( 
       
   417         ENcdReportInstall,
       
   418         aReportUri, 
       
   419         aReportNamespace );
       
   420     
       
   421     if ( serverSupports ) 
       
   422         {        
       
   423         DLTRACE(("Server supports install reports"));
       
   424         report = CNcdReportInstall::NewLC( 
       
   425             *this,
       
   426             aContentIdentifier,
       
   427             aMetadataId,
       
   428             aStatus,
       
   429             aReportUri,
       
   430             aReportNamespace );
       
   431 
       
   432         iReports.InsertInOrderAllowRepeatsL( 
       
   433             report, 
       
   434             TLinearOrder<CNcdReport>( CNcdReport::Compare ) );
       
   435 
       
   436         CleanupStack::Pop( report );
       
   437         report->SetReportId( GenerateReportId() );
       
   438         report->Attributes().SetAttributeL( 
       
   439             ENcdReportAttributeIsUsed, ETrue );
       
   440         
       
   441         DLTRACEOUT(("Report added"));        
       
   442         return report->ReportId();
       
   443         }
       
   444 
       
   445     return KNcdReportNotSupported;
       
   446     }
       
   447 
       
   448 
       
   449 // ---------------------------------------------------------------------------
       
   450 //
       
   451 // ---------------------------------------------------------------------------
       
   452 TInt CNcdReportManager::SetInstallReportAccessPoint( 
       
   453     const TNcdReportId& aReportId,    
       
   454     const TCatalogsConnectionMethod& aAccessPoint )
       
   455     {
       
   456     DLTRACEIN(("aAccessPoint: %d", aAccessPoint.iId ));
       
   457 
       
   458     // Same implementation with download and install.
       
   459     TInt error( SetDownloadReportAccessPoint( aReportId, aAccessPoint ) );
       
   460 
       
   461     DLTRACEOUT(("Access point set successfully"));
       
   462     return error;
       
   463     }
       
   464 
       
   465 
       
   466 // ---------------------------------------------------------------------------
       
   467 //
       
   468 // ---------------------------------------------------------------------------
       
   469 void CNcdReportManager::ReportInstallStatusL( 
       
   470     const TNcdReportId& aReportId,
       
   471     const TNcdReportStatusInfo& aStatus )
       
   472     {
       
   473     DLTRACEIN(("aStatus: %d", aStatus.iStatus));
       
   474 
       
   475     // Same implementation with download and install    
       
   476     TBool sendable( EFalse );
       
   477     if ( aStatus.iStatus == ENcdReportSuccess
       
   478          || aStatus.iStatus == ENcdReportCancel
       
   479          || aStatus.iStatus == ENcdReportFail )
       
   480         {
       
   481         sendable = ETrue;
       
   482         }
       
   483     ReportDownloadStatusL( aReportId, aStatus, sendable );
       
   484     }
       
   485 
       
   486     
       
   487 // ---------------------------------------------------------------------------
       
   488 // 
       
   489 // ---------------------------------------------------------------------------
       
   490 void CNcdReportManager::SetReportsAsUsedL( 
       
   491     const CNcdNodeIdentifier& aMetadataId )
       
   492     {
       
   493     DLTRACEIN((""));
       
   494     for ( TInt i = 0; i < iReports.Count(); ++i )
       
   495         {
       
   496         if ( iReports[i]->MetadataId().Equals( aMetadataId ) ) 
       
   497             {
       
   498             DLINFO(("Setting report as used"));       
       
   499             iReports[i]->Attributes().SetAttributeL( 
       
   500                 ENcdReportAttributeIsUsed, ETrue );
       
   501             // No break since there may be other reports with
       
   502             // the same metadata id
       
   503             } 
       
   504         }
       
   505     }
       
   506 
       
   507 
       
   508 // ---------------------------------------------------------------------------
       
   509 //
       
   510 // ---------------------------------------------------------------------------
       
   511 void CNcdReportManager::RemoveUnusedReportsL()
       
   512     {
       
   513     DLTRACEIN((""));
       
   514     for ( TInt i = 0; i < iReports.Count(); ++i )
       
   515         {
       
   516         if ( !iReports[i]->Attributes().AttributeInt32(
       
   517                 ENcdReportAttributeIsUsed ) )
       
   518             {            
       
   519             TNcdReportStatusInfo info( ENcdReportCancel, KErrCancel );
       
   520             SetReportStatusL( *iReports[i], info, ETrue );
       
   521             }
       
   522         }
       
   523     }
       
   524     
       
   525     
       
   526 // ---------------------------------------------------------------------------
       
   527 //
       
   528 // ---------------------------------------------------------------------------
       
   529 void CNcdReportManager::OpenStorageL()
       
   530     {
       
   531     DLTRACEIN((""));
       
   532     iDb = NULL;    
       
   533     
       
   534     HBufC* clientUid = iContext.FamilyId().Name().AllocLC();    
       
   535       
       
   536     // Recreate necessary storage objects. Nothing is created if not necessary
       
   537     MNcdStorage& storage = iStorageManager.CreateOrGetStorageL( 
       
   538         *clientUid, NcdProviderDefines::KDownloadNamespace );
       
   539 
       
   540     CleanupStack::PopAndDestroy( clientUid );    
       
   541     
       
   542     iDb = &storage.DatabaseStorageL( 
       
   543         NcdProviderDefines::KReportDatabaseUid );
       
   544     DLTRACEOUT(("Storage opened, iDb: %x", iDb));
       
   545     }
       
   546     
       
   547     
       
   548 // ---------------------------------------------------------------------------
       
   549 //
       
   550 // ---------------------------------------------------------------------------
       
   551 void CNcdReportManager::CloseStorage()
       
   552     {
       
   553     DLTRACEIN((""));
       
   554     
       
   555     iDb = NULL;
       
   556     }
       
   557 
       
   558     
       
   559 // ---------------------------------------------------------------------------
       
   560 // Loads unfinished reports 
       
   561 // ---------------------------------------------------------------------------    
       
   562 void CNcdReportManager::LoadReportsL()
       
   563     {
       
   564     DLTRACEIN((""));
       
   565    
       
   566     OpenStorageL();
       
   567         
       
   568     DASSERT( iDb );
       
   569     
       
   570     // Get all items from the db
       
   571     RPointerArray<MNcdStorageItem> items;
       
   572     iDb->StorageItemsL( items );
       
   573     CleanupClosePushL( items );
       
   574 
       
   575     for ( TInt i = 0; i < items.Count(); ++i )
       
   576         {
       
   577         items[i]->SetDataItem( this );
       
   578         
       
   579         // This will cause a call to report manager's InternalizeL
       
   580         items[i]->ReadDataL();
       
   581         }
       
   582 
       
   583     CleanupStack::PopAndDestroy( &items );
       
   584     
       
   585     DLTRACEOUT(("Reports loaded"));
       
   586     }        
       
   587     
       
   588 
       
   589 // ---------------------------------------------------------------------------
       
   590 // Saves an individual report to disk
       
   591 // ---------------------------------------------------------------------------
       
   592 void CNcdReportManager::SaveReportL( CNcdReport& aReport )
       
   593     {
       
   594     DLTRACEIN((""));
       
   595     
       
   596     MNcdStorageItem& item( StorageItemForReportL( aReport.ReportId() ) );
       
   597     
       
   598     // Save new item to database
       
   599     item.SetDataItem( &aReport );
       
   600     item.OpenL();
       
   601     
       
   602     // Calls ExternalizeL for the item
       
   603     item.WriteDataL();
       
   604     
       
   605     // Save the item to the database.
       
   606     item.SaveL();      
       
   607     
       
   608     DLTRACEOUT((""));
       
   609     }
       
   610     
       
   611 
       
   612 // ---------------------------------------------------------------------------
       
   613 // Remove report from db
       
   614 // ---------------------------------------------------------------------------
       
   615 void CNcdReportManager::RemoveReportL( const TNcdReportId& aId )
       
   616     {
       
   617     DLTRACEIN((""));
       
   618     
       
   619     MNcdStorageItem& item( StorageItemForReportL( aId ) );
       
   620     item.RemoveFromStorageL();    
       
   621     }
       
   622 
       
   623 
       
   624 // ---------------------------------------------------------------------------
       
   625 // Get a storage item that matches the report id
       
   626 // ---------------------------------------------------------------------------
       
   627 MNcdStorageItem& CNcdReportManager::StorageItemForReportL( 
       
   628     const TNcdReportId& aId )
       
   629     {
       
   630     DLTRACEIN((""));
       
   631     OpenStorageL();
       
   632     
       
   633     DASSERT( iDb );
       
   634     
       
   635     TBuf<KNcdReportIdLength16Bit> id;
       
   636     ReportIdToDescriptor( aId, id );    
       
   637     DLTRACE(( _L("Id: %S"), &id ));
       
   638     DLTRACE(("Getting storage item, iDb: %x", iDb ));
       
   639     // Get/create the storage item where the data is saved
       
   640     // Note: database has the ownership of the item
       
   641     MNcdStorageItem* item = iDb->StorageItemL( id, KNcdReportDataType );    
       
   642     return *item;
       
   643     }
       
   644     
       
   645 
       
   646 // ---------------------------------------------------------------------------
       
   647 // MCatalogsAccessPointObserver
       
   648 // ---------------------------------------------------------------------------
       
   649 
       
   650 // ---------------------------------------------------------------------------
       
   651 //
       
   652 // ---------------------------------------------------------------------------
       
   653 void CNcdReportManager::HandleAccessPointEventL( 
       
   654     const TCatalogsConnectionMethod& aAp,
       
   655     const TCatalogsAccessPointEvent& aEvent )
       
   656     {
       
   657     DLTRACEIN((""));
       
   658     (void) aAp; // suppress warning
       
   659     
       
   660     // Just try to send reports when an AP is opened.
       
   661     if ( aEvent == ECatalogsAccessPointOpened && 
       
   662          iManagerState == ENcdReportManagerIdle &&
       
   663          iReportingMethod == MNcdServerReportManager::EReportingBackground )
       
   664         {
       
   665         DLTRACE(("Ap: %d opened", aAp.iId ));
       
   666         // Notice, that the manager state is set to ENcdReportManagerPreparing 
       
   667         // only if the reporting method should work in the background.
       
   668         // This setting will also start the RunL loop for the sending.
       
   669         SetManagerStateL( ENcdReportManagerPreparing );
       
   670         }
       
   671     }
       
   672 
       
   673 
       
   674 // ---------------------------------------------------------------------------
       
   675 //
       
   676 // ---------------------------------------------------------------------------
       
   677 void CNcdReportManager::HandleHttpEventL( 
       
   678     MCatalogsHttpOperation& aOperation, 
       
   679     TCatalogsHttpEvent aEvent )
       
   680     {
       
   681     DLTRACEIN((""));
       
   682 
       
   683     switch( aEvent.iOperationState ) 
       
   684         {
       
   685         // Handle completed operation
       
   686         case ECatalogsHttpOpCompleted:
       
   687             {
       
   688             DLTRACE(("Operation complete"));
       
   689             // Finish report releases the transaction
       
   690             FinishReportL( aOperation, KErrNone );                                    
       
   691             break;
       
   692             }   
       
   693                  
       
   694         // Handle operation in progress
       
   695         case ECatalogsHttpOpInProgress:
       
   696             {
       
   697             if ( aEvent.iProgressState == 
       
   698                 ECatalogsHttpResponseBodyReceived )
       
   699                 {
       
   700                 DLINFO(("response body=%S", &aOperation.Body() ));
       
   701                 // send received data to parser                
       
   702                 }
       
   703             break;
       
   704             }
       
   705                     
       
   706         default:
       
   707             {
       
   708             break;
       
   709             }
       
   710         }
       
   711         
       
   712     DLTRACEOUT((""));    
       
   713 
       
   714     }
       
   715         
       
   716         
       
   717 // ---------------------------------------------------------------------------
       
   718 //
       
   719 // ---------------------------------------------------------------------------
       
   720 TBool CNcdReportManager::HandleHttpError(
       
   721     MCatalogsHttpOperation& aOperation,
       
   722     TCatalogsHttpError aError )
       
   723     {
       
   724     DLTRACEIN(("Error type: %d, code: %d", aError.iType, aError.iError ));
       
   725     
       
   726     // Can't do anything for the error anyway 
       
   727     // Finish report releases the transaction
       
   728     TRAP_IGNORE( FinishReportL( aOperation, aError.iError ) );      
       
   729     DLTRACEOUT((""));
       
   730     return ETrue;
       
   731 
       
   732     }
       
   733 
       
   734 
       
   735 // ---------------------------------------------------------------------------
       
   736 // Context getter
       
   737 // ---------------------------------------------------------------------------
       
   738 const MCatalogsContext& CNcdReportManager::Context() const
       
   739     {
       
   740     return iContext;
       
   741     }
       
   742 
       
   743 
       
   744 // ---------------------------------------------------------------------------
       
   745 // Cancel ongoing report transactions
       
   746 // ---------------------------------------------------------------------------
       
   747 void CNcdReportManager::CancelReportSending()
       
   748     {
       
   749     DLTRACEIN((""));
       
   750     
       
   751     for ( TInt i = 0; i < iTransactions.Count(); ++i )
       
   752         {
       
   753         iTransactions[i]->Cancel();        
       
   754         }
       
   755     iTransactions.Reset();
       
   756     
       
   757     for ( TInt i = 0; i < iReports.Count(); ++i )
       
   758         {
       
   759         iReports[i]->SetReportTransaction( NULL );
       
   760         }
       
   761 
       
   762     if ( iObserver != NULL )
       
   763         {
       
   764         // Inform the observer about the cancellation.
       
   765         iObserver->OperationComplete( NULL, KErrCancel );
       
   766         iObserver = NULL;
       
   767         }
       
   768     }
       
   769     
       
   770 
       
   771 // ---------------------------------------------------------------------------
       
   772 // 
       
   773 // ---------------------------------------------------------------------------
       
   774 TCatalogsConnectionMethod CNcdReportManager::DefaultConnectionMethod()
       
   775     {
       
   776     DLTRACEIN((""));
       
   777     // APN ID of the current/last opened default accesspoint
       
   778     TUint32 apn = iHttpSession.ConnectionManager().CurrentAccessPoint();
       
   779 
       
   780     // This ensures that reports use the latest connected default accesspoint
       
   781     // or the AP that is set to them. 
       
   782     // Issue: DLEB-140
       
   783     TCatalogsConnectionMethod method( 
       
   784         apn, 
       
   785         ECatalogsConnectionMethodTypeAccessPoint );
       
   786     method.iApnId = apn;
       
   787 
       
   788     return method;
       
   789     }
       
   790 
       
   791 
       
   792 // ---------------------------------------------------------------------------
       
   793 // 
       
   794 // ---------------------------------------------------------------------------
       
   795 CNcdGeneralManager& CNcdReportManager::GeneralManager() const
       
   796     {
       
   797     return iGeneralManager;
       
   798     }
       
   799 
       
   800 
       
   801 // ---------------------------------------------------------------------------
       
   802 // From MNcdStorageDataItem
       
   803 // ---------------------------------------------------------------------------
       
   804 
       
   805 // ---------------------------------------------------------------------------
       
   806 //
       
   807 // ---------------------------------------------------------------------------
       
   808 void CNcdReportManager::ExternalizeL( RWriteStream& /*aStream*/ )
       
   809     {
       
   810     DLTRACEIN((""));
       
   811     // nothing to do
       
   812     }
       
   813 
       
   814 
       
   815 // ---------------------------------------------------------------------------
       
   816 //
       
   817 // ---------------------------------------------------------------------------
       
   818 void CNcdReportManager::InternalizeL( RReadStream& aStream )
       
   819     {
       
   820     DLTRACEIN((""));    
       
   821     
       
   822     TNcdReportType type;
       
   823     InternalizeEnumL( type, aStream );
       
   824     
       
   825     CNcdReport* report( NULL );
       
   826     
       
   827     switch( type )
       
   828         {
       
   829         case ENcdReportDownload:
       
   830             {
       
   831             report = CNcdReportDownload::NewLC( *this, aStream );            
       
   832             break;
       
   833             }
       
   834 
       
   835         case ENcdReportOmaDownload:
       
   836             {
       
   837             report = CNcdReportOmaDownload::NewLC( *this, aStream );            
       
   838             break;
       
   839             }
       
   840             
       
   841         case ENcdReportInstall:
       
   842             {
       
   843             report = CNcdReportInstall::NewLC( *this, aStream );            
       
   844             break;
       
   845             }
       
   846                 
       
   847         default:
       
   848             {
       
   849             NCD_ASSERT_ALWAYS( 0, ENcdPanicIndexOutOfRange );
       
   850             }
       
   851         }
       
   852 
       
   853     CNcdAttributes& att( report->Attributes() );
       
   854 
       
   855     if ( !iClientCrashed ) 
       
   856         {
       
   857         
       
   858         // Set as unused, flag is set to used if a download registers
       
   859         // to this report
       
   860         att.SetAttributeL( 
       
   861             ENcdReportAttributeIsUsed, EFalse );
       
   862         
       
   863         // Check if the report sending was canceled and
       
   864         // set as sendable if it was
       
   865         if ( att.AttributeInt32( 
       
   866                 ENcdReportAttributeReportBeingSent ) != ENcdReportNone &&
       
   867              att.AttributeInt32( 
       
   868                 ENcdReportAttributeLatestSentReport ) == ENcdReportNone )
       
   869             {
       
   870             DLTRACE(("Set as sendable because previous attempt was canceled"));
       
   871             att.SetAttributeL( ENcdReportAttributeSendable, ETrue );
       
   872             }
       
   873         }
       
   874     else 
       
   875         {
       
   876         DLTRACE(("Set report as failed because engine crashed"));
       
   877         TNcdReportStatusInfo info( ENcdReportFail, KErrUnknown );
       
   878         report->SetStatus( info );
       
   879         att.SetAttributeL( 
       
   880             ENcdReportAttributeIsUsed, EFalse );
       
   881         
       
   882         // Check if the report sending was canceled and
       
   883         // set as sendable if it was
       
   884         att.SetAttributeL( ENcdReportAttributeSendable, ETrue );
       
   885 
       
   886         }
       
   887         
       
   888     iReports.InsertInOrderAllowRepeatsL( 
       
   889         report, 
       
   890         TLinearOrder<CNcdReport>( CNcdReport::Compare ) );
       
   891     
       
   892     CleanupStack::Pop( report ); // report, 
       
   893     
       
   894     // ensure that iNewReportId is higher than any current report id
       
   895     if ( report->ReportId() >= iNewReportId ) 
       
   896         {
       
   897         iNewReportId = report->ReportId() + 1;
       
   898         }
       
   899     
       
   900     DLTRACEOUT(("Report internalized"));
       
   901     }
       
   902 
       
   903 
       
   904 
       
   905 // ---------------------------------------------------------------------------
       
   906 // From CActive
       
   907 // ---------------------------------------------------------------------------
       
   908 
       
   909 
       
   910 // ---------------------------------------------------------------------------
       
   911 //
       
   912 // ---------------------------------------------------------------------------
       
   913 void CNcdReportManager::RunL()
       
   914     {
       
   915     DLTRACEIN((""));
       
   916     if ( iStatus.Int() == KErrNone ) 
       
   917         {
       
   918         switch ( iManagerState ) 
       
   919             {
       
   920             case ENcdReportManagerPreparing:
       
   921                 {
       
   922                 SendReportsL();
       
   923                 break;
       
   924                 };
       
   925             
       
   926             default:
       
   927                 {
       
   928                 DLTRACE(("Default"));
       
   929                 break;
       
   930                 }
       
   931             }
       
   932         }
       
   933     }
       
   934     
       
   935     
       
   936 // ---------------------------------------------------------------------------
       
   937 //
       
   938 // ---------------------------------------------------------------------------
       
   939 void CNcdReportManager::DoCancel()
       
   940     {
       
   941     DLTRACEIN((""));
       
   942     
       
   943     // No requests to cancel
       
   944     }
       
   945     
       
   946         
       
   947 // ---------------------------------------------------------------------------
       
   948 //
       
   949 // ---------------------------------------------------------------------------
       
   950 TInt CNcdReportManager::RunError( TInt aError )
       
   951     {
       
   952     DLTRACEIN(("aError: %d", aError));
       
   953     
       
   954     if ( iObserver != NULL )
       
   955         {
       
   956         iObserver->OperationComplete( NULL, aError );
       
   957         iObserver = NULL;        
       
   958         }
       
   959 
       
   960     // Return KErrNone so that CActiveScheduler doesn't panic 
       
   961     // with E32USER-CBase 47. Would call an observer if there was any.
       
   962     
       
   963     return KErrNone;
       
   964     }
       
   965 
       
   966 
       
   967 // ---------------------------------------------------------------------------
       
   968 //
       
   969 // ---------------------------------------------------------------------------
       
   970 void CNcdReportManager::FinishReportL( MCatalogsHttpOperation& aOperation, TInt aErrorCode )
       
   971     {
       
   972     DLTRACEIN((""));
       
   973 
       
   974     // This function will insert the information into the reports after the
       
   975     // report sending operation has been finished. So, all the reports that have
       
   976     // been handled by the operation are removed from the list.
       
   977        
       
   978     MCatalogsHttpOperation* operationPtr = &aOperation;            
       
   979     
       
   980     // Remove the transaction before any leaving code so that if a leave
       
   981     // occurs, we don't have any hanging transactions in the array
       
   982     TInt index = iTransactions.FindInAddressOrder( &aOperation );
       
   983     DASSERT( index != KErrNotFound );
       
   984     
       
   985     iTransactions.Remove( index );
       
   986     aOperation.Release();
       
   987     
       
   988     TInt i = iReports.Count();
       
   989     while ( i-- )
       
   990         {
       
   991         if ( iReports[i]->ReportTransaction() == operationPtr ) 
       
   992             {
       
   993             iReports[i]->SetReportTransaction( NULL );
       
   994             
       
   995             CNcdAttributes& att( iReports[i]->Attributes() );
       
   996             
       
   997             // Update latest sent report status
       
   998             att.SetAttributeL( 
       
   999                 ENcdReportAttributeLatestSentReport,
       
  1000                 att.AttributeInt32(
       
  1001                     ENcdReportAttributeReportBeingSent ) );
       
  1002                                             
       
  1003             if ( iReports[i]->CanBeRemoved() ) 
       
  1004                 {
       
  1005                 DLTRACE(("Deleting report"));                                
       
  1006                 RemoveReportL( iReports[i]->ReportId() );
       
  1007                 delete iReports[i];
       
  1008                 iReports.Remove( i ); 
       
  1009                 }
       
  1010             else // save info that report was sent
       
  1011                 {                
       
  1012                 SaveReportL( *iReports[i] );
       
  1013                 }
       
  1014             }
       
  1015         }
       
  1016     
       
  1017 
       
  1018     DLTRACE(("Committing report changes"));
       
  1019     iDb->CommitL();
       
  1020 
       
  1021  
       
  1022     // Check if all the transactions have been handled. If they are, then no more
       
  1023     // http operations are going on and the reporting is finished.   
       
  1024     if ( iTransactions.Count() == 0 )
       
  1025         {
       
  1026         DLTRACE(("No more pending reports.")); 
       
  1027         if ( iReportingMethod == MNcdServerReportManager::EReportingBackground )
       
  1028             {
       
  1029             DLINFO(("Start handling next patch"));
       
  1030             // Notice, that by calling this, we continue to the next round in the RunL.
       
  1031             // So, then new reports will be sent if they exist then. If there is already new
       
  1032             // items available, then they will be sent. Otherwise the operation
       
  1033             // will end after RunL is called next time.
       
  1034             SetManagerStateL( ENcdReportManagerPreparing );
       
  1035             }
       
  1036         else
       
  1037             {
       
  1038             DLINFO(("Set to idle because sending is managed by hand."));
       
  1039             // This will set the state and the RunL loop will not be continued.
       
  1040             SetManagerStateL( ENcdReportManagerIdle );
       
  1041             }
       
  1042             
       
  1043         // Notice, that observer is set only for the managed reporting. But, in some cases
       
  1044         // the reporting may have been changed to background before the requested managed send
       
  1045         // was finished. So, instead of waiting for the background action to finish in next
       
  1046         // RunL loop, inform the observer already here about the completion. If only background
       
  1047         // operations have been occurring, then the observer is NULL here.
       
  1048         if ( iObserver != NULL )
       
  1049             {
       
  1050             // Because observer was set for manager to know when managed operation
       
  1051             // was finished, inform the observer.
       
  1052             iObserver->OperationComplete( NULL, aErrorCode );
       
  1053             iObserver = NULL;
       
  1054             }
       
  1055         }
       
  1056     }
       
  1057 
       
  1058 
       
  1059 // ---------------------------------------------------------------------------
       
  1060 // Server capability check
       
  1061 // ---------------------------------------------------------------------------
       
  1062 TBool CNcdReportManager::ServerSupportsReports( 
       
  1063     TNcdReportType aType,
       
  1064     const TDesC& aServerUri,
       
  1065     const TDesC& aServerNamespace ) const
       
  1066     {
       
  1067     DLTRACEIN((""));
       
  1068     const MNcdServerDetails* serverDetails = 
       
  1069         iConfigurationManager.ServerDetails( 
       
  1070             iContext,
       
  1071             aServerUri,
       
  1072             aServerNamespace );
       
  1073     
       
  1074     // No server details so we don't know whether server supports them
       
  1075     // or not    
       
  1076     if ( !serverDetails ) 
       
  1077         {
       
  1078         DLTRACEOUT(("Server details not found"));
       
  1079         return EFalse;
       
  1080         }
       
  1081 
       
  1082     // Notice, that install capability support is already checked here.
       
  1083     TBool supports = 
       
  1084         serverDetails->IsCapabilitySupported( 
       
  1085             NcdCapabilities::KInstallationReport() );
       
  1086 
       
  1087     // Download report requires install capability and also download capability    
       
  1088     if ( aType == ENcdReportDownload ) 
       
  1089         {
       
  1090         DLTRACE(("Checking for downloadReport capability"));
       
  1091     
       
  1092         supports = supports && 
       
  1093             serverDetails->IsCapabilitySupported( 
       
  1094                 NcdCapabilities::KDownloadReport() );
       
  1095         }
       
  1096         
       
  1097     DLTRACEOUT(("Required caps supported: %d", supports ));
       
  1098     return supports;
       
  1099     }
       
  1100 
       
  1101 
       
  1102 // ---------------------------------------------------------------------------
       
  1103 //
       
  1104 // ---------------------------------------------------------------------------
       
  1105 CNcdReportManager::CNcdReportManager( 
       
  1106     const MCatalogsContext& aContext,
       
  1107     CNcdGeneralManager& aGeneralManager,
       
  1108     MCatalogsHttpSession& aHttpSession,
       
  1109     TBool aClientCrashed ) :
       
  1110     CActive( EPriorityStandard ),
       
  1111     iContext( aContext ),
       
  1112     iGeneralManager( aGeneralManager ),
       
  1113     iConfigurationManager( aGeneralManager.ConfigurationManager() ),
       
  1114     iStorageManager( aGeneralManager.StorageManager() ),
       
  1115     iHttpSession( aHttpSession ),
       
  1116     iReportingMethod( MNcdServerReportManager::EReportingBackground ),
       
  1117     iReportingStyle( MNcdServerReportManager::EReportingStyleGeneral ),
       
  1118     iClientCrashed( aClientCrashed )
       
  1119     {
       
  1120     }
       
  1121     
       
  1122     
       
  1123 // ---------------------------------------------------------------------------
       
  1124 //
       
  1125 // ---------------------------------------------------------------------------
       
  1126 void CNcdReportManager::ConstructL()
       
  1127     {
       
  1128     CActiveScheduler::Add( this );   
       
  1129     
       
  1130     iNetworkManager = &CCatalogsHttpSessionManager::NetworkManagerL();
       
  1131     // observe changes in access points
       
  1132     iNetworkManager->AddObserverL( *this );
       
  1133     LoadReportsL(); 
       
  1134     }
       
  1135 
       
  1136 
       
  1137 // ---------------------------------------------------------------------------
       
  1138 //
       
  1139 // ---------------------------------------------------------------------------
       
  1140 CNcdReport* CNcdReportManager::FindReport( 
       
  1141     const TNcdReportId& aReportId,
       
  1142     RNcdReportArray& aArray ) const
       
  1143     {
       
  1144     DLTRACEIN(("aReportId: %d", aReportId));
       
  1145     for ( TInt i = 0; i < aArray.Count(); ++i )
       
  1146         {
       
  1147         if ( aArray[i]->ReportId() == aReportId ) 
       
  1148             {
       
  1149             return aArray[i];
       
  1150             }
       
  1151         }
       
  1152     DLTRACEOUT(("Not found"));
       
  1153     return NULL;
       
  1154     }
       
  1155 
       
  1156 
       
  1157 // ---------------------------------------------------------------------------
       
  1158 //
       
  1159 // ---------------------------------------------------------------------------
       
  1160 CNcdReport* CNcdReportManager::FindReport( 
       
  1161     const TDesC& aId,
       
  1162     const CNcdNodeIdentifier& aNodeId,
       
  1163     const TDesC& aReportUri,
       
  1164     const TNcdReportType& aReportType,
       
  1165     RNcdReportArray& aArray ) const
       
  1166     {
       
  1167     DLTRACEIN(( _L("aId: %S, report URI: %S"), &aId, &aReportUri ));
       
  1168     // Search backwards so that the newest & changeable report is found
       
  1169     TInt count = aArray.Count();
       
  1170     while( count-- )    
       
  1171         {
       
  1172         if ( aArray[ count ]->Match( aNodeId, aId, aReportUri, aReportType ) ) 
       
  1173             {
       
  1174             return aArray[ count ];
       
  1175             }
       
  1176         }
       
  1177     DLTRACEOUT(("Not found"));
       
  1178     return NULL;
       
  1179     }
       
  1180 
       
  1181 
       
  1182 // ---------------------------------------------------------------------------
       
  1183 // State setter
       
  1184 // ---------------------------------------------------------------------------
       
  1185 void CNcdReportManager::SetManagerStateL( TNcdReportManagerState aState )
       
  1186     {
       
  1187     DLTRACEIN(("aState: %d", aState));
       
  1188         
       
  1189     iManagerState = aState;
       
  1190     switch ( iManagerState )
       
  1191         {
       
  1192         case ENcdReportManagerPreparing:
       
  1193             {
       
  1194             ExecuteRunL( KErrNone );
       
  1195             break;
       
  1196             }
       
  1197 
       
  1198         case ENcdReportManagerSending:
       
  1199             {
       
  1200             break;
       
  1201             }
       
  1202         
       
  1203         default:
       
  1204             {
       
  1205             break;
       
  1206             }
       
  1207         }        
       
  1208     }
       
  1209 
       
  1210 
       
  1211 // ---------------------------------------------------------------------------
       
  1212 // Initiate report sending
       
  1213 // ---------------------------------------------------------------------------
       
  1214 void CNcdReportManager::SendReportsL()
       
  1215     {
       
  1216     DLTRACEIN((""));
       
  1217     
       
  1218     DASSERT( !iTransactions.Count() );
       
  1219 
       
  1220     // Update open connections so that IsAccessPointOpen is up-to-date
       
  1221     iNetworkManager->UpdateConnectionsL();    
       
  1222     
       
  1223     TBool defaultApIsOpen = iNetworkManager->IsAccessPointOpen( 
       
  1224         DefaultConnectionMethod() );
       
  1225     
       
  1226     for ( TInt i = 0; i < iReports.Count(); ++i ) 
       
  1227         {
       
  1228         CNcdReport& report = *iReports[i];
       
  1229         
       
  1230         if ( report.IsSendable() && (
       
  1231                 // either report has no AP set -> use default which has to be open
       
  1232                 // or its AP needs to be open
       
  1233                 ( defaultApIsOpen ) ||
       
  1234                 ( iNetworkManager->IsAccessPointOpen( report.ConnectionMethod() ) ) ) )
       
  1235             {
       
  1236             if ( !iNetworkManager->IsAccessPointOpen( report.ConnectionMethod() ) ) 
       
  1237                 {
       
  1238                 DLTRACE(("Using default ap for reporting"));
       
  1239                 report.SetAccessPoint( DefaultConnectionMethod() );
       
  1240                 }
       
  1241 
       
  1242             MCatalogsHttpOperation* transaction = 
       
  1243                 iHttpSession.CreateTransactionL( 
       
  1244                     report.Attributes().AttributeString16(
       
  1245                         ENcdReportAttributeReportUri ), this );
       
  1246             
       
  1247             CleanupReleasePushL( *transaction );
       
  1248 
       
  1249             if ( report.CanBundle() ) 
       
  1250                 {                
       
  1251                 BundleReportsL( i, *transaction );
       
  1252                 }
       
  1253             else
       
  1254                 {
       
  1255                 PrepareReportL( report, *transaction );
       
  1256                 }
       
  1257             
       
  1258             report.UpdateTransactionConfigL( *transaction );
       
  1259             User::LeaveIfError( transaction->Start() );
       
  1260             
       
  1261             iTransactions.InsertInAddressOrderL( transaction );
       
  1262             CleanupStack::Pop( transaction );
       
  1263             }
       
  1264         }
       
  1265 
       
  1266     // The operations that were created above, will call http callback functions 
       
  1267     // of this class and the operation will be finished in FinishReportL function.
       
  1268     
       
  1269     // Check if the manager state should be set to idle or if we should
       
  1270     // let the state to be something else and wait for the HTTP operations
       
  1271     // that were created above to complete..
       
  1272     if ( iTransactions.Count() == 0 )
       
  1273         {
       
  1274         DLTRACE(("Nothing to send anymore."));
       
  1275         // This will set the state and operation will not continue RunL loop
       
  1276         // any more.
       
  1277         SetManagerStateL( ENcdReportManagerIdle );
       
  1278 
       
  1279         if ( iObserver != NULL )
       
  1280             {
       
  1281             // Because observer was set for manager to know when managed operation
       
  1282             // was finished, inform the observer.
       
  1283             iObserver->OperationComplete( NULL, KErrNone );
       
  1284             iObserver = NULL;
       
  1285             }
       
  1286         }
       
  1287     }
       
  1288         
       
  1289     
       
  1290 // ---------------------------------------------------------------------------
       
  1291 // Bundle reports
       
  1292 // ---------------------------------------------------------------------------
       
  1293 void CNcdReportManager::BundleReportsL( 
       
  1294     TInt aIndex, 
       
  1295     MCatalogsHttpOperation& aTransaction )
       
  1296     {
       
  1297     DLTRACEIN(("Bundling reports from index %d onwards", aIndex ));
       
  1298     DASSERT( aIndex < iReports.Count() );
       
  1299     
       
  1300     CNcdRequestInstallation* report = 
       
  1301         NcdRequestGenerator::CreateInstallationReportRequestLC();
       
  1302 
       
  1303     
       
  1304     CNcdReport& currentReport( *iReports[ aIndex ] );
       
  1305     CNcdAttributes& att( currentReport.Attributes() );
       
  1306     
       
  1307     report->SetNamespaceL( 
       
  1308         att.AttributeString16( ENcdReportAttributeReportNamespace ) );
       
  1309     
       
  1310     currentReport.AddReportDataL( *report );
       
  1311     currentReport.SetReportTransaction( &aTransaction );
       
  1312     
       
  1313     // Update report flags: beingSent = current status, 
       
  1314     // latestSentReport = none, so we can identify cases were the same
       
  1315     // status is sent multiple times in a row (pause, pause...)
       
  1316     UpdateReportAttributesForSendingL( currentReport );
       
  1317     
       
  1318     DLTRACE(("Start bundling, report count: %d", iReports.Count() ));
       
  1319     for ( TInt i = aIndex + 1; i < iReports.Count(); ++i )
       
  1320         {
       
  1321         
       
  1322         TNcdReportBundleMatch bundle = CanBundleWithL( 
       
  1323             currentReport,
       
  1324             *iReports[i] );
       
  1325             
       
  1326         if ( bundle == ENcdReportBundleMatch && 
       
  1327              iReports[i]->IsSendable() ) 
       
  1328             {
       
  1329             DLTRACE(("Bundling report %d", i ));
       
  1330             iReports[i]->AddReportDataL( *report );
       
  1331             iReports[i]->SetReportTransaction( &aTransaction );
       
  1332             
       
  1333             // Update report status
       
  1334             UpdateReportAttributesForSendingL( *iReports[i] );            
       
  1335             }
       
  1336         else if ( bundle == ENcdReportBundleNoMatch ) 
       
  1337             {
       
  1338             DLTRACE(("Nothing more to bundle, exit loop"));
       
  1339             break;
       
  1340             }
       
  1341         }
       
  1342     
       
  1343     DLTRACE(("Process report"));
       
  1344     HBufC8* body = 
       
  1345         iGeneralManager.ProtocolManager().ProcessPreminetRequestL(
       
  1346             Context(),
       
  1347             *report,
       
  1348             att.AttributeString16( ENcdReportAttributeReportUri ),
       
  1349             ETrue );
       
  1350     CleanupStack::PopAndDestroy( report );
       
  1351     
       
  1352     CleanupStack::PushL( body );        
       
  1353     aTransaction.SetBodyL( *body );
       
  1354     CleanupStack::PopAndDestroy( body );
       
  1355     }
       
  1356 
       
  1357 
       
  1358 // ---------------------------------------------------------------------------
       
  1359 // Updates common attributes of the report for sending
       
  1360 // ---------------------------------------------------------------------------
       
  1361 void CNcdReportManager::UpdateReportAttributesForSendingL( 
       
  1362     CNcdReport& aReport )
       
  1363     {
       
  1364     DLTRACEIN((""));
       
  1365     CNcdAttributes& att( aReport.Attributes() );
       
  1366     
       
  1367     att.SetAttributeL( 
       
  1368         ENcdReportAttributeReportBeingSent,
       
  1369         aReport.Status().iStatus );
       
  1370 
       
  1371     att.SetAttributeL( 
       
  1372         ENcdReportAttributeLatestSentReport,
       
  1373         ENcdReportNone );
       
  1374     
       
  1375     att.SetAttributeL(
       
  1376         ENcdReportAttributeSendable,
       
  1377         EFalse );
       
  1378     }
       
  1379 
       
  1380 // ---------------------------------------------------------------------------
       
  1381 // Check if reports can be bundled together
       
  1382 // ---------------------------------------------------------------------------
       
  1383 TNcdReportBundleMatch CNcdReportManager::CanBundleWithL(     
       
  1384     const CNcdReport& aReport, 
       
  1385     const CNcdReport& aReport2 ) const
       
  1386     {
       
  1387     DLTRACEIN((""));
       
  1388         // Report URIs must match
       
  1389     if ( ( aReport.Attributes().AttributeString16(
       
  1390                 ENcdReportAttributeReportUri ).Compare( 
       
  1391             aReport2.Attributes().AttributeString16(
       
  1392                 ENcdReportAttributeReportUri ) ) != 0 ) )
       
  1393         {
       
  1394         DLTRACEOUT(("Can stop"));
       
  1395         return ENcdReportBundleNoMatch;
       
  1396         }
       
  1397         
       
  1398     if (
       
  1399         // Report namespaces must match
       
  1400         ( aReport.Attributes().AttributeString16(
       
  1401             ENcdReportAttributeReportNamespace ).Compare( 
       
  1402           aReport2.Attributes().AttributeString16(
       
  1403             ENcdReportAttributeReportNamespace ) ) == 0 ) 
       
  1404 
       
  1405         &&
       
  1406         // Report access points must match
       
  1407         ( CompareConnectionMethods( aReport, aReport2 ) ) )
       
  1408         {
       
  1409         return ENcdReportBundleMatch;
       
  1410         }
       
  1411     
       
  1412     DLTRACEOUT((""));
       
  1413     return ENcdReportBundleUriMatch;
       
  1414     }
       
  1415     
       
  1416     
       
  1417 // ---------------------------------------------------------------------------
       
  1418 // Prepare report for sending
       
  1419 // ---------------------------------------------------------------------------
       
  1420 void CNcdReportManager::PrepareReportL( 
       
  1421     CNcdReport& aReport,
       
  1422     MCatalogsHttpOperation& aTransaction )
       
  1423     {
       
  1424     DLTRACEIN((""));
       
  1425 
       
  1426     aReport.SetReportTransaction( &aTransaction );
       
  1427     
       
  1428     UpdateReportAttributesForSendingL( aReport );    
       
  1429     
       
  1430     HBufC8* body = aReport.CreateReportL();
       
  1431     CleanupStack::PushL( body );
       
  1432     DLINFO(( "body= %S", body ));
       
  1433     
       
  1434     aTransaction.SetBodyL( *body );
       
  1435     CleanupStack::PopAndDestroy( body );        
       
  1436     }
       
  1437 
       
  1438 
       
  1439 // ---------------------------------------------------------------------------
       
  1440 // Complete request
       
  1441 // ---------------------------------------------------------------------------
       
  1442 void CNcdReportManager::ExecuteRunL( TInt aError )    
       
  1443     {
       
  1444     DLTRACEIN(("aError: %d", aError));
       
  1445     
       
  1446     if ( !IsActive() ) 
       
  1447         {        
       
  1448         iStatus = KRequestPending;
       
  1449         SetActive();
       
  1450         TRequestStatus* status = &iStatus;
       
  1451         User::RequestComplete( status, aError );
       
  1452         }
       
  1453     }
       
  1454 
       
  1455 
       
  1456 // ---------------------------------------------------------------------------
       
  1457 // Generate a new report id
       
  1458 // ---------------------------------------------------------------------------
       
  1459 TNcdReportId CNcdReportManager::GenerateReportId()
       
  1460     {
       
  1461     DLTRACEIN((""));    
       
  1462     return iNewReportId++;
       
  1463     }
       
  1464     
       
  1465 
       
  1466 // ---------------------------------------------------------------------------
       
  1467 //
       
  1468 // ---------------------------------------------------------------------------
       
  1469 void CNcdReportManager::SetReportStatusL( 
       
  1470     CNcdReport& aReport,
       
  1471     const TNcdReportStatusInfo& aStatus,
       
  1472     TBool aSendable )
       
  1473     {
       
  1474     DLTRACEIN((""));
       
  1475     aReport.SetStatus( aStatus );
       
  1476     aReport.Attributes().SetAttributeL( 
       
  1477         ENcdReportAttributeSendable, 
       
  1478         aSendable );
       
  1479         
       
  1480     SaveReportL( aReport );
       
  1481     
       
  1482     // Start sending if the report is sendable and the manager isn't already
       
  1483     // sending. Also if the operation is not done in the background then do not
       
  1484     // do sending here. But, later when it is separately asked.
       
  1485     if ( aReport.IsSendable() && 
       
  1486          iManagerState == ENcdReportManagerIdle &&
       
  1487          iReportingMethod == MNcdServerReportManager::EReportingBackground ) 
       
  1488         {
       
  1489         SetManagerStateL( ENcdReportManagerPreparing );
       
  1490         }    
       
  1491     }
       
  1492 
       
  1493 
       
  1494 // ---------------------------------------------------------------------------
       
  1495 //
       
  1496 // ---------------------------------------------------------------------------
       
  1497 TBool CNcdReportManager::CompareConnectionMethods( 
       
  1498     const CNcdReport& aFirstReport,
       
  1499     const CNcdReport& aSecondReport ) const
       
  1500     {
       
  1501     DLTRACEIN((""));
       
  1502     const TCatalogsConnectionMethod& first = aFirstReport.ConnectionMethod();
       
  1503     const TCatalogsConnectionMethod& second = aSecondReport.ConnectionMethod();   
       
  1504     
       
  1505     switch( first.iType )
       
  1506         {                   
       
  1507         case ECatalogsConnectionMethodTypeAlwaysAsk:
       
  1508         case ECatalogsConnectionMethodTypeDeviceDefault: // flow-through
       
  1509             {            
       
  1510             if ( second.iType == first.iType )
       
  1511                 {
       
  1512                 return ETrue;                
       
  1513                 }
       
  1514             break;
       
  1515             }
       
  1516         
       
  1517         case ECatalogsConnectionMethodTypeDestination:
       
  1518             {
       
  1519             if ( second.iType == ECatalogsConnectionMethodTypeDestination )
       
  1520                 {
       
  1521                 return ( first.iId != 0 && first.iId == second.iId ) || 
       
  1522                        ( first.iApnId != 0 && first.iApnId == second.iApnId );                
       
  1523                 }
       
  1524             break;
       
  1525             }
       
  1526         
       
  1527         case ECatalogsConnectionMethodTypeAccessPoint:
       
  1528             {
       
  1529             if ( second.iType == ECatalogsConnectionMethodTypeAccessPoint )
       
  1530                 {
       
  1531                 return ( first.iId != 0 && first.iId == second.iId );
       
  1532                 }
       
  1533             break;
       
  1534             }
       
  1535         
       
  1536         default:
       
  1537             { 
       
  1538             DASSERT( 0 );
       
  1539             }
       
  1540         }
       
  1541         
       
  1542     return ( first.iApnId != 0 && first.iApnId == second.iApnId );     
       
  1543     }