--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/browserutilities/downloadmgr/DownloadMgrServEng/Src/HttpClientApp.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,709 @@
+/*
+* Copyright (c) 2002-2004 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+*/
+
+
+
+// INCLUDE FILES
+#include "HttpClientAppInstance.h"
+#include "HttpConnHandler.h"
+#include "HttpDownloadManagerServerEngine.h"
+#include "FileExt.h"
+#include "HttpClientApp.h"
+#include "HttpDownloadMgrLogger.h"
+
+// EXTERNAL DATA STRUCTURES
+//extern ?external_data;
+
+// EXTERNAL FUNCTION PROTOTYPES
+//extern ?external_function( ?arg_type,?arg_type );
+
+// CONSTANTS
+_LIT( KDownloadFilenameFormat, "%S%S");
+
+// MACROS
+//#define ?macro ?macro_def
+
+// LOCAL CONSTANTS AND MACROS
+//const ?type ?constant_var = ?constant;
+//#define ?macro_name ?macro_def
+
+// MODULE DATA STRUCTURES
+//enum ?declaration
+//typedef ?declaration
+
+// LOCAL FUNCTION PROTOTYPES
+//?type ?function_name( ?arg_type, ?arg_type );
+
+// FORWARD DECLARATIONS
+//class ?FORWARD_CLASSNAME;
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::CHttpClientApp
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CHttpClientApp::CHttpClientApp( TUint32 aAppUid,
+ CHttpDownloadManagerServerEngine* aEngine )
+ : iAppUid( aAppUid )
+ , iEngine( aEngine )
+ {
+ CLOG_CREATE;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::ConstructL()
+ {
+ CLOG_NAME_1( _L("CHttpClientApp_%x"), iAppUid );
+
+ iInstances = new (ELeave) CArrayPtrFlat<CHttpClientAppInstance>(2);
+ iDownloads = new (ELeave) CArrayPtrFlat<CHttpDownload>(2);
+ iConnections = new (ELeave) CArrayPtrFlat<CHttpConnHandler>(2);
+
+ TBuf<KMaxPath> folder;
+ iEngine->ClientAppFolder( this, folder );
+
+ // Create client app's folder
+ TInt error = iEngine->Fs().MkDirAll( folder );
+ if( error != KErrNone && error != KErrAlreadyExists )
+ // leave if makedir failed in some way
+ // don't leave if already exists
+ {
+ CLOG_WRITE8_1( "MkDirAll: %d", error );
+ User::Leave( error );
+ }
+
+ // create folder for info files
+ iEngine->DownloadInfoFolder( this, folder );
+
+ error = iEngine->Fs().MkDirAll( folder );
+ if( error != KErrNone && error != KErrAlreadyExists )
+ // leave if makedir failed in some way
+ // don't leave if already exists
+ {
+ CLOG_WRITE8_1( "info dir: %d", error );
+ User::Leave( error );
+ }
+
+ // create folder for COD info files
+ iEngine->CODDownloadInfoFolder( this, folder );
+
+ error = iEngine->Fs().MkDirAll( folder );
+ if( error != KErrNone && error != KErrAlreadyExists )
+ // leave if makedir failed in some way
+ // don't leave if already exists
+ {
+ CLOG_WRITE8_1( "info dir: %d", error );
+ User::Leave( error );
+ }
+
+ // create folder for content files
+ iEngine->DownloadContentFolder( this, folder );
+ error = iEngine->Fs().MkDirAll( folder );
+ if( error != KErrNone && error != KErrAlreadyExists )
+ // leave if makedir failed in some way
+ // don't leave if already exists
+ {
+ CLOG_WRITE8_1( "content dir: %d", error );
+ User::Leave( error );
+ }
+
+ iEngine->ClientAppFolder( this, folder );
+ LoadClientInfoL( folder );
+
+ iEngine->CodFolder( this, folder );
+
+ CFileMan* fileman = CFileMan::NewL( iEngine->Fs() );
+ fileman->RmDir( folder );
+ delete fileman;
+
+ iEngine->Fs().MkDir( folder );
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CHttpClientApp* CHttpClientApp::NewL( TUint32 aAppUid,
+ CHttpDownloadManagerServerEngine* aEngine )
+ {
+ CHttpClientApp* self = new( ELeave ) CHttpClientApp( aAppUid, aEngine );
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop();
+
+ return self;
+ }
+
+
+// Destructor
+CHttpClientApp::~CHttpClientApp()
+ {
+ CloseClientApp( EFalse );
+
+ CLOG_CLOSE;
+ }
+
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::CreateNewInstanceL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CHttpClientAppInstance*
+ CHttpClientApp::CreateNewInstanceL( MDownloadStateObserver* aObserver,
+ TBool aMaster )
+ {
+ LOGGER_ENTERFN( "CreateNewInstanceL" );
+
+ TInt instanceId( 1 );
+ TInt index;
+
+ if( aMaster )
+ {
+ // Check that there can be only 1 master instance
+ for( index = 0; index < iInstances->Count(); ++index )
+ {
+ if( (*iInstances)[index]->Master() )
+ {
+ User::Leave( KErrAlreadyExists );
+ }
+ }
+ }
+
+ // generate new instance id
+ for( index = 0; index < iInstances->Count(); ++index )
+ {
+ if( instanceId <= (*iInstances)[index]->InstanceId() )
+ {
+ instanceId = (*iInstances)[index]->InstanceId() + 1;
+ }
+ }
+
+ CLOG_WRITE8_1( "New instance id: [%d]", instanceId );
+
+ // Create new connhandler used by the instance
+ // Every instance has its own connhandler
+ CHttpConnHandler* conn = CHttpConnHandler::NewL( this );
+
+ // connhandlers are owned by CHttpClientApp.
+ CleanupStack::PushL( conn );
+ iConnections->AppendL( conn );
+ CleanupStack::Pop( conn );
+
+ // Create new client instance
+ CHttpClientAppInstance* instance =
+ CHttpClientAppInstance::NewL( this, conn, aMaster, instanceId, aObserver );
+
+ CleanupStack::PushL( instance );
+ iInstances->AppendL( instance );
+ CleanupStack::Pop( instance );
+
+ // Associate connhandler with client instance
+ conn->SetClientAppInst( instance );
+
+ for( index = 0; index < iDownloads->Count(); ++index )
+ {
+ if( !(*iDownloads)[index]->ClientAppInstance() )
+ // this download is not occupied by any client instance
+ {
+ CLOG_WRITE8_1( "Controlling download: [%d]", (*iDownloads)[index]->Id() );
+ // From it's owned by this new instance
+ (*iDownloads)[index]->SetClientInstance( instance, ETrue );
+ if( (*iDownloads)[index]->ConnHandler() && aMaster )//In case of embedded browser(aMaster =0) the connection should be set by parent application
+ {
+ // conn handler in this download is not associated with
+ // any client instance. do it now.
+ (*iDownloads)[index]->ConnHandler()->SetClientAppInst( instance );
+ }
+ }
+ }
+
+ return instance;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::CloseInstance
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::CloseInstance( CHttpClientAppInstance* aInstance )
+ {
+ LOGGER_ENTERFN( "CloseInstance" );
+
+ CLOG_WRITE_1( "Instance: %d", aInstance->InstanceId() );
+ CLOG_WRITE_1( "ExitAction: %d", aInstance->ExitAction() );
+
+ TInt index;
+
+ // find this instance
+ for( index = 0; index < iInstances->Count(); ++index )
+ {
+ if( aInstance == (*iInstances)[index] )
+ {
+ break;
+ }
+ }
+
+ __ASSERT_DEBUG( index != iInstances->Count(), DMPanic( KErrCorrupt ) );
+ if( index == iInstances->Count() )
+ {
+ return;
+ }
+
+ // delete instance from the array
+ iInstances->Delete( index );
+
+ CHttpClientAppInstance* masterInstance = NULL;
+
+ // find which client instance will inherit
+ // the downloads of the closed instance
+ for( index = 0; index < iInstances->Count(); ++index )
+ {
+ if( (*iInstances)[index]->Master() )
+ {
+ masterInstance = (*iInstances)[index];
+ break;
+ }
+ }
+
+ // Detach instance from conn handler(s) associated with it.
+ for( index = 0; index < iConnections->Count(); ++index )
+ {
+ if( (*iConnections)[index]->ClientAppInst() == aInstance )
+ {
+ (*iConnections)[index]->SetClientAppInst( masterInstance );
+
+ if(!masterInstance && iInstances->Count() == 0)
+ {
+ DestroyConnHandler((*iConnections)[index]);
+ }
+
+
+ }
+ }
+
+ // detach download(s) from this instance
+ for( index = 0; index < iDownloads->Count(); ++index )
+ {
+ if( aInstance == (*iDownloads)[index]->ClientAppInstance() ||
+ aInstance == (*iDownloads)[index]->PDClientAppInstance() )
+ {
+ //Unregister the download in case of PDClientAppInstance. This was registered during attach
+ if( (*iDownloads)[index]->DetachClientInstance( aInstance ) )
+ {
+ continue;
+ }
+ if( !(*iDownloads)[index]->Pausable() )
+ // non-pausable download always deleted
+ {
+ CLOG_WRITE_1( "Download is not pausable: [%d]", (*iDownloads)[index]->Id() );
+ (*iDownloads)[index]->Delete( aInstance );
+ // index(th) element was delete
+ --index;
+ }
+ else
+ {
+ switch( aInstance->ExitAction() )
+ {
+ case EExitPause:
+ {
+ TRAP_IGNORE( (*iDownloads)[index]->PauseL() );
+ }
+ // flow through
+
+ case EExitNothing:
+ {
+ (*iDownloads)[index]->SetClientInstance( masterInstance );
+ }
+ break;
+
+
+ case EExitDelete:
+ {
+ CLOG_WRITE_1( "Deleting: [%d]", (*iDownloads)[index]->Id() );
+ (*iDownloads)[index]->Delete( aInstance );
+ // index(th) element was delete
+ --index;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ }
+
+ // delete the instance
+ delete aInstance;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::CloseClientApp
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::CloseClientApp( TBool /*bStore*/ )
+ {
+ LOGGER_ENTERFN( "CloseClientApp" );
+
+ if( iConnections )
+ {
+ iConnections->ResetAndDestroy();
+ delete iConnections;
+ iConnections = NULL;
+ }
+
+ if( iDownloads )
+ {
+ for (TInt i=0; i<iDownloads->Count(); i++)
+ {
+ iDownloads->At(i)->Deref();
+ }
+ delete iDownloads;
+ iDownloads = NULL;
+ }
+
+ if( iInstances )
+ {
+ iInstances->ResetAndDestroy();
+ delete iInstances;
+ iInstances = NULL;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::Instances
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CHttpClientAppInstance>* CHttpClientApp::Instances() const
+ {
+ return iInstances;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::CreateNewDownloadL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CHttpDownload*
+ CHttpClientApp::CreateNewDownloadL( CHttpClientAppInstance* aClAppInstance,
+ const TDesC8& aUrl )
+ {
+ if( !aUrl.Length() )
+ // w/o url a download is meaningless
+ {
+ User::Leave( KErrArgument );
+ }
+
+ TInt downloadId = iEngine->NextDownloadId();
+
+ CHttpDownload* newDl = CHttpDownload::NewL( aUrl,
+ this,
+ downloadId,
+ aClAppInstance );
+
+ CleanupStack::PushL( newDl );
+ RegisterDownloadL( newDl );
+ CleanupStack::Pop( newDl );
+
+ return newDl;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::AppUid
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TUint32 CHttpClientApp::AppUid() const
+ {
+ return iAppUid;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::Downloads
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CArrayPtrFlat<CHttpDownload>* CHttpClientApp::Downloads() const
+ {
+ return iDownloads;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::Engine
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+CHttpDownloadManagerServerEngine* CHttpClientApp::Engine() const
+ {
+ return iEngine;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::RegisterDownloadL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::RegisterDownloadL( CHttpDownload* aDownload )
+ {
+ iDownloads->AppendL( aDownload );
+ aDownload->Ref();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::UnregisterDownload
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CHttpClientApp::UnregisterDownload( CHttpDownload* aDownload )
+ {
+ CLOG_WRITE_1("Unregister download: %d", aDownload->Id() );
+
+ TInt index;
+ for( index = 0; index < iDownloads->Count(); ++index )
+ {
+ if( (*iDownloads)[index] == aDownload )
+ {
+ iDownloads->Delete( index );
+ aDownload->Deref();
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::DownloadsInMaster
+//
+// Counts how many (no media) downloads the Master instance has.
+//
+// -----------------------------------------------------------------------------
+//
+TInt32 CHttpClientApp::DownloadsInMaster( TBool aNoMediasOnly )
+ {
+ TInt32 counter( 0 );
+
+ for( TInt i = 0; i < iDownloads->Count(); ++i )
+ {
+ if( (*iDownloads)[i]->ClientAppInstance()&&
+ (*iDownloads)[i]->ClientAppInstance()->Master() )
+ {
+ if( aNoMediasOnly && (*iDownloads)[i]->NoMedia() )
+ // count only the aNoMediasOnly
+ {
+ ++counter;
+ }
+ else if( !aNoMediasOnly )
+ // count every download
+ {
+ ++counter;
+ }
+ }
+ }
+
+ return counter;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::DestroyConnHandler
+//
+// Deletes given connhandler from the array and destroys the object itself.
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::DestroyConnHandler( CHttpConnHandler* aConnHandler )
+ {
+ CLOG_WRITE( "DestroyConnHandler" );
+
+ __ASSERT_DEBUG( aConnHandler, DMPanic( KErrCorrupt ));
+
+ for( TInt index = 0; index < iConnections->Count(); ++index )
+ {
+ if( (*iConnections)[index] == aConnHandler )
+ {
+ __ASSERT_DEBUG( !aConnHandler->ClientAppInst(), DMPanic( KErrCorrupt ));
+ iConnections->Delete( index );
+ delete aConnHandler;
+
+ break;
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::LoadClientInfoL
+//
+// Download info and all the downloads are loaded here
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::LoadClientInfoL( const TDesC& /*aFolder*/ )
+ {
+ LoadDownloadsL();
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::StoreClientInfoL
+//
+// For further improvement if any download info has to be persisted
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::StoreClientInfoL()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::LoadDownloadsL
+// ?implementation_description
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CHttpClientApp::LoadDownloadsL()
+ {
+ TPath folder;
+
+ Engine()->DownloadInfoFolder( this, folder );
+
+ CDir* dirs = NULL;
+
+ TUint mask = KEntryAttMatchMask | KEntryAttMatchExclude;
+
+ User::LeaveIfError( Engine()->Fs().GetDir( folder,
+ mask,
+ EAscending | EDirsLast,
+ dirs ) );
+ if( dirs && dirs->Count() )
+ // there are downloads for this client
+ {
+ TInt err;
+
+ CleanupStack::PushL( dirs );
+ for( TInt i = 0; i < dirs->Count(); ++i )
+ {
+ if( (*dirs)[i].IsDir() )
+ // directories are sorted to the end of the array
+ // if this entry is dir we finished
+ {
+ break;
+ }
+
+ TInt32 id = DownloadIdL( (*dirs)[i].iName );
+
+ if ( IsDownloadAlreadyLoaded( id ) )
+ continue;
+
+ // Download is not assigned to any instance
+ // Id comes from the filename
+ CHttpDownload* newDl = NULL;
+ TRAP( err, newDl = CHttpDownload::NewL( KNullDesC8(), this, id ) );
+ if( err != KErrEof &&
+ err != KErrCorrupt &&
+ err != KErrNotFound &&
+ err != KErrNotSupported )
+ // no problem load info file and the download is valid
+ // and it was pausable, or non-pausable but completed
+ {
+ RegisterDownloadL( newDl );
+ }
+ else
+ {
+ TBuf<KMaxPath> fileName;
+
+ fileName.Format( KDownloadFilenameFormat,
+ &folder,
+ &(*dirs)[i].iName );
+
+ if( newDl )
+ {
+ newDl->Delete(NULL);
+ delete newDl;
+ }
+
+ if( !err )
+ // delete unusable info file
+ {
+ iEngine->Fs().Delete( fileName );
+ }
+ }
+ }
+
+ CleanupStack::Pop( dirs );
+ }
+
+ delete dirs;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::OutputFilenameL
+//
+// Gets the download id from the give folder name
+// -----------------------------------------------------------------------------
+//
+TInt32 CHttpClientApp::DownloadIdL( const TDesC& aFilename ) const
+ {
+ TLex temp( aFilename );
+ TUint32 id;
+ User::LeaveIfError( temp.Val( id, EDecimal ) );
+
+ return id;
+ }
+
+// -----------------------------------------------------------------------------
+// CHttpClientApp::IsDownloadAlreadyLoaded
+//
+// Check whether the download is already loaded or not for the client
+// -----------------------------------------------------------------------------
+//
+TBool CHttpClientApp::IsDownloadAlreadyLoaded( TInt32 aId ) const
+ {
+
+ for( TInt index = 0; index < iDownloads->Count(); ++index )
+ {
+ if( (*iDownloads)[index]->Id() == aId)
+ {
+ return ETrue;
+ }
+ }
+ return EFalse;
+ }
+
+
+
+// ========================== OTHER EXPORTED FUNCTIONS =========================
+
+// End of File