--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/codhandler/codeng/src/CodEngBase.cpp Mon Mar 30 12:54:55 2009 +0300
@@ -0,0 +1,2856 @@
+/*
+* Copyright (c) 2002 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:
+* Implementation of class CCodEngBase.
+*
+*
+*/
+
+
+// INCLUDE FILES
+
+#include "CodEngBase.h"
+#include "Connection.h"
+#include "HttpLoader.h"
+#include "CodSaver.h"
+#include "FileSaver.h"
+#include "RoapSaver.h"
+#include "CodData.h"
+#include "CodLoadObserver.h"
+#include "CodError.h"
+#include "CodStatus.h"
+#include "CodPanic.h"
+#include "CodUtil.h"
+#include "CodLogger.h"
+#include "RoapData.h"
+#include "CodProgress.h"
+#include "MediaObject.h"
+#include "DownloadDataClient.h"
+
+#include <AiwGenericParam.h>
+#include <DocumentHandler.h>
+#include <ApmStd.h>
+#include <Oma2Agent.h>
+#include <RoapDef.h>
+#include <f32file.h>
+#include <BodyPart.h>
+#include <SysUtil.h>
+#include <pathinfo.h>
+#include "CodDefs.h"
+#include <CodUi.rsg>
+#include <AknQueryDialog.h>
+#include <stringloader.h>
+#include <bautils.h>
+#include "FileExt.h"
+
+#ifdef __SYNCML_DM_FOTA
+#include <fotaengine.h>
+#include "FotaSaver.h"
+/// FOTA Update Package type.
+_LIT8( KFotaPackageDataType, "application/vnd.nokia.swupd.dp2" );
+/// Default FOTA package id.
+LOCAL_D const TInt KCodDefaultFotaPkgId = -1;
+#endif /*def __SYNCML_DM_FOTA */
+
+#ifdef RD_MULTIPLE_DRIVE
+#include <centralrepository.h>
+#include <driveinfo.h>
+#include <BrowserUiSDKCRKeys.h>
+#endif //RD_MULTIPLE_DRIVE
+
+#include <bldvariant.hrh>
+
+// ================= CONSTANTS =======================
+const TInt KDownloadInfoIncrSize = 2*4096; // used for DownloadInfo
+
+/// Name of UTF-8 character set.
+_LIT8( KCodUtf8, "utf-8" );
+
+#ifdef RD_MULTIPLE_DRIVE
+_LIT( KDefaultDriveListSep, ";" );
+_LIT( KDefaultDriveList, "C;E" );
+#endif
+// ================= MEMBER FUNCTIONS =======================
+
+// ---------------------------------------------------------
+// CCodEngBase::~CCodEngBase()
+// ---------------------------------------------------------
+//
+EXPORT_C CCodEngBase::~CCodEngBase()
+ {
+ Cancel();
+ delete iRoapData;
+
+ if(iSaver)
+ {
+ iSaver->Cleanup( !Pausable() );
+ }
+
+ delete iSaver;
+ delete iDocHandler;
+ delete iLoader;
+ delete iConn;
+ delete iCodBuf;
+ delete iData;
+ iFs.Close();
+ CLOG(( ECodEng, 2, _L("CCodEngBase::~CCodEngBase") ));
+ CLOG(( ECodEng, 2, _L("*****************") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetL()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::SetL
+ (
+ const TDesC8& aBuf,
+ TRequestStatus* aStatus,
+ const CAiwGenericParamList* aParams,
+ const RPointerArray<CBodyPart>* aParts
+ )
+ {
+ CLOG(( ECodEng, 0, _L("-> CCodEngBase::SetL aParams=0x%x, aParts=0x%x"), \
+ &aParams, aParts ));
+
+ // Misuse asserts.
+ __ASSERT_ALWAYS( aStatus, CodPanic( ECodInvalidArguments ) );
+ __ASSERT_ALWAYS( iState == EInit || iState == EReady, \
+ CodPanic( ECodOffState ) );
+ // Internal asserts.
+ __ASSERT_DEBUG( !iConn, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iLoader, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iCodBuf, CodPanic( ECodInternal ) );
+
+ ResetPaths();
+ delete iSaver;
+ iSaver = NULL;
+ iData->Reset();
+ iParts = aParts;
+ iParams = aParams;
+ iType = TDataType();
+ iHandler = TUid::Null();
+ delete iRoapData;
+ iRoapData = NULL;
+
+ // Default parameters.
+ TPtrC8 sourceUri;
+ TPtrC8 charset( KCodUtf8 );
+ iPreferredIap = 0;
+
+ // Get params from GenericParams.
+ if ( iParams )
+ {
+ CodUtil::GetDesParamLC( sourceUri, EGenericParamURL, *iParams );
+ CodUtil::GetDesParamLC( charset, EGenericParamCharSet, *iParams );
+ CodUtil::GetUint32Param( iPreferredIap, EGenericParamAccessPoint, *iParams );
+
+ CodUtil::GetUint32Param( iDownloadId, EGenericParamDownloadId, *iParams );
+
+ TUint32 AppUId(0);
+ CodUtil::GetUint32Param( AppUId, EGenericParamApplication, *iParams );
+ iAppUId.iUid = AppUId;
+
+ // Generate COD DL Info folder name - C:\system\dmgr\<appuid>\codinfo\
+
+ TBuf<KMaxPath> folderName;
+ CODDownloadInfoFolder(folderName);
+
+ // TO DO - Create the folder if it does not exist
+
+ iCodDlInfoPath.Format( _L("%S%d"), &folderName,iDownloadId );
+
+ }
+
+ iData->SetSourceUriL( sourceUri );
+ iCodBuf = CodUtil::ConvertToUcs2L( aBuf, charset, iFs );
+
+ if ( iParams )
+ {
+ CleanupStack::PopAndDestroy( 2 ); // Two pushed temp buffer.
+ }
+
+ iParentStatus = aStatus;
+ *iParentStatus = KRequestPending;
+
+ Continue( ESet );
+
+ CLOG(( ECodEng, 0, _L("<- CCodEngBase::SetL (user 8-bit)") ));
+ }
+
+
+
+
+// ---------------------------------------------------------
+// CCodEngBase::SetL()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::SetL
+ (
+ const TInt aDownloadId,
+ const TUid aDlUid,
+ //TRequestStatus* aStatus,
+ const RPointerArray<CBodyPart>* aParts
+ )
+
+ {
+ ResetPaths();
+ delete iSaver;
+ iSaver = NULL;
+ iData->Reset();
+ iParts = aParts;
+ //iParams = aParams;
+ iType = TDataType();
+ iHandler = TUid::Null();
+ delete iRoapData;
+ iRoapData = NULL;
+
+
+ // Default parameters.
+ TPtrC8 sourceUri;
+ TPtrC8 charset( KCodUtf8 );
+ iPreferredIap = 0;
+ //iLoader->LoadDownloadInfoL()
+ //Read from info file
+ iAppUId = aDlUid;
+ iDownloadId = aDownloadId;
+ TBuf<KMaxPath> folderName;
+ CODDownloadInfoFolder(folderName);
+ iCodDlInfoPath.Format( _L("%S%d"), &folderName,iDownloadId );
+
+ // Download resumed after Pause
+ iResumedDownload = ETrue;
+
+ LoadInfoFilesL();
+
+ }
+// ---------------------------------------------------------
+// CCodEngBase::CODDownloadInfoFolder()
+// ---------------------------------------------------------
+//
+void CCodEngBase::CODDownloadInfoFolder( TDes& aFolder ) const
+ {
+ aFolder.Format( KDownloadFolderFormat,
+ &KDmDefaultDir,
+ iAppUId,
+ &KInfoFilesCodDirName );
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::Data()
+// ---------------------------------------------------------
+//
+EXPORT_C const CCodData& CCodEngBase::Data() const
+ {
+ return *iData;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetObserver()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::SetObserver( MCodLoadObserver* aObserver )
+ {
+ CLOG(( ECodEng, 2, _L("CCodEngBase::SetObserver(0x%x)"), aObserver ));
+ __ASSERT_ALWAYS( !(aObserver && iObserver), \
+ CodPanic( ECodObserverAlreadySet ) );
+ iObserver = aObserver;
+ if ( iSaver )
+ {
+ iSaver->SetObserver( iObserver );
+ }
+ if ( iProgress )
+ {
+ iProgress->SetObserver( iObserver );
+ }
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::Accept()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::Accept( TRequestStatus* aStatus )
+ {
+ CLOG(( ECodEng, 0, _L("-> CCodEngBase::Accept") ));
+ // Misuse asserts.
+ __ASSERT_ALWAYS( iData->IsValid(), CodPanic( ECodInvalidData ) );
+ __ASSERT_ALWAYS( aStatus, CodPanic( ECodInvalidArguments ) );
+ __ASSERT_ALWAYS( iState == EReady, CodPanic( ECodOffState ) );
+ // Internal asserts.
+ __ASSERT_DEBUG( !iConn, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iLoader, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodInternal ) );
+
+ iParentStatus = aStatus;
+ *iParentStatus = KRequestPending;
+ /*
+ OMA 2: If the license element includes the order attribute and the order attribute
+ is equal to the post. The contents of the license element MUST NOT be passed
+ to the License Agent unless the Media Object or Product is successfully downloaded
+ */
+ if (iIsLicense && !iData->IsPostOrder())
+ {
+ // dd2 case with license tag and order tag equals to "any",
+ // so we should install the ROAP trigger as soon as it became available
+ Continue( EStartInstallRoap );
+ }
+ else
+ {
+ // we should install MO first
+ // 1) dd1 case
+ // 2) dd2 without license tag
+ // 3) dd2 with license tag and order tag = "POST"
+ __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
+ Continue( EStartConnect );
+ }
+ CLOG(( ECodEng, 0, _L("<- CCodEngBase::Accept") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::Reject()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::Reject( TRequestStatus* aStatus )
+ {
+ CLOG(( ECodEng, 0, _L("-> CCodEngBase::Reject") ));
+ // Misuse asserts.
+ __ASSERT_ALWAYS( iData->IsValid(), CodPanic( ECodInvalidData ) );
+ __ASSERT_ALWAYS( aStatus, CodPanic( ECodInvalidArguments ) );
+ __ASSERT_ALWAYS( iState == EReady, CodPanic( ECodOffState ) );
+ // Internal asserts.
+ __ASSERT_DEBUG( !iConn, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iLoader, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iParentStatus, CodPanic( ECodInternal ) );
+//TODO
+ if (!iIsLicense )
+ {
+ __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
+ }
+
+ iParentStatus = aStatus;
+ *iParentStatus = KRequestPending;
+
+ iResult = KErrAbort;
+ iStatusCode = StatusCode( iResult, iState );
+ Continue( EStartNotify );
+ CLOG(( ECodEng, 0, _L("<- CCodEngBase::Reject") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::Stop()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::Stop()
+ {
+ CLOG(( ECodEng, 0, _L("-> CCodEngBase::Stop iState(%d)"), iState ));
+
+ // This method is almost the same as DoCancel, yet works differently:
+ //
+ // When Cancel()->DoCancel() is called, this Active Object is not longer
+ // active (set inactive by the framework). That is, RunL will not be called
+ // after Cancel(). Anything that is going on stopped abruptly, without
+ // any further processing, we are Done() (parent is completed).
+ //
+ // When Stop is called, we still stay active, so after cancelling the
+ // outstanding request (if any), we will complete (RunL will be called)
+ // with KErrCancel. That triggers further processing, so we are not Done()
+ // yet (parent is not completed).
+ //
+ // Having this method comes from the logic of how a downloading is
+ // cancelled: after cancel, we may still have to continue with notify. In
+ // effect, a download must be cancelled twice to stop it; this method
+ // supports the double-cancel.
+
+ if ( iStopInProgress )
+ {
+ // Prevent reentrant calls.
+ // Reentrancy normally should not be possible: we call some Cancel()
+ // here, and that should not return and should not allow other object
+ // to run until done. But it does: disconnecting the WAP stack
+ // unfortunately includes waiting on the disconnect_cnf event.
+ // This means that there IS a Cancel which allows other objects run.
+ CLOG(( ECodEng, 0, _L("<- CCodEngBase::Stop already stopping") ));
+ return;
+ }
+ iStopInProgress = ETrue;
+
+ switch ( iState )
+ {
+ case ESet:
+ {
+ // Cancelled before we could start.
+ delete iCodBuf;
+ iCodBuf = NULL;
+ // Own status already completed (by self-completion).
+ __ASSERT_DEBUG( iStatus != KRequestPending, \
+ CodPanic( ECodInternal ) );
+ SelfComplete( KErrCancel );
+ // Complete parent.
+ iResult = KErrCancel;
+ Done();
+ break;
+ }
+
+ case EStartConnect:
+ case EStartFetch:
+ case EStartNotify:
+ {
+ // Already completed (by self-completion).
+ __ASSERT_DEBUG( iStatus != KRequestPending, \
+ CodPanic( ECodInternal ) );
+ SelfComplete( KErrCancel );
+ break;
+ }
+
+ case EConnect:
+ {
+ __ASSERT_DEBUG( iConn, CodPanic( ECodInternal ) );
+ iConn->Cancel();
+ // We are not Done() - parent request is still outstanding, we
+ // are still active. RunL will be called with KErrCancel.
+ break;
+ }
+
+ case EFetch:
+ {
+ if ( iObserver && iNotificationStatus == ELoad )
+ {
+ CLOG(( ECodEng, 3, \
+ _L("-> CCodEngBase::Stop notify StartCancelL") ));
+ TRAP_IGNORE( iObserver->StartCancelL() );
+ iNotificationStatus = ECancel;
+ }
+ __ASSERT_DEBUG( iLoader, CodPanic( ECodInternal ) );
+ iLoader->Cancel();
+ // We are not Done() - parent request is still outstanding, we
+ // are still active. RunL will be called with KErrCancel.
+ break;
+ }
+
+ case EInstall:
+ case EInstallRoap:
+ {
+ __ASSERT_DEBUG( iSaver, CodPanic( ECodInternal ) );
+ iSaver->CancelInstall();
+ // We are not Done() - parent request is still outstanding, we
+ // are still active. RunL will be called with KErrCancel.
+ break;
+ }
+
+ case ENotify:
+ {
+ __ASSERT_DEBUG( iLoader, CodPanic( ECodInternal ) );
+ iLoader->Cancel();
+ // We are not Done() - parent request is still outstanding, we
+ // are still active. RunL will be called with KErrCancel.
+ break;
+ }
+
+ case EInit:
+ case EReady:
+ case EStartInstall:
+ default:
+ {
+ if ( iObserver && iNotificationStatus == EPaused )
+ {
+ TRAP_IGNORE( iObserver->StartCancelL() );
+ iNotificationStatus = ECancel;
+ }
+ // No request is outstanding, but as this is an user-callable
+ // method, tolerate misuse (and do nothing).
+ break;
+ }
+ }
+ iStopInProgress = EFalse;
+ CLOG(( ECodEng, 0, _L("<- CCodEngBase::Stop") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::RemovableMedia()
+// ---------------------------------------------------------
+//
+EXPORT_C TBool CCodEngBase::RemovableMedia() const
+ {
+ return iRemovableMedia;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::GetPath()
+// ---------------------------------------------------------
+//
+EXPORT_C TPtrC CCodEngBase::GetPath() const
+ {
+ if(!iData || !iData->Count() || !(*iData)[iData->ActiveDownload()]->iFullName )
+ return KNullDesC();
+ return *((*iData)[iData->ActiveDownload()]->iFullName);
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::GetDestFilePath()
+// ---------------------------------------------------------
+//
+EXPORT_C TPtrC CCodEngBase::GetDestFilePath (TInt aMOIndex ) const
+ {
+ if(iData && aMOIndex >=1 && aMOIndex <= iData->Count())
+ {
+ if((*iData)[aMOIndex]->iFullName)
+ return *((*iData)[aMOIndex]->iFullName);
+ }
+ return TPtrC( KNullDesC );
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::GetType()
+// ---------------------------------------------------------
+//
+EXPORT_C const TDataType& CCodEngBase::GetType() const
+ {
+ return iType;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::GetHandler()
+// ---------------------------------------------------------
+//
+EXPORT_C TUid CCodEngBase::GetHandler() const
+ {
+ return iHandler;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::GetStatusCode()
+// ---------------------------------------------------------
+//
+EXPORT_C TInt CCodEngBase::GetStatusCode() const
+ {
+ return iStatusCode;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::GetRoapData()
+// ---------------------------------------------------------
+//
+EXPORT_C const CRoapData* CCodEngBase::GetRoapData() const
+ {
+ return iRoapData;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetCodDlAttached()
+// ---------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::SetCodDlAttached(const TBool aValue)
+ {
+ iAttached = aValue;
+ if(iSaver)
+ {
+ iSaver->SetProgressiveMode(aValue);
+ }
+
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::CCodEngBase()
+// ---------------------------------------------------------
+//
+CCodEngBase::CCodEngBase( MCodLoadObserver* aObserver )
+: CActive( CActive::EPriorityStandard ),
+ iState( EInit ),
+ iObserver( aObserver ),
+ iStopInProgress( EFalse ),
+ iPreferredIap( 0 ),
+ iNotificationStatus( ENull ),
+ iFsUsed( EFalse ),
+ iDownloadId( 0 ),
+#ifdef RD_MULTIPLE_DRIVE
+ iSpaceAvailOk( EFalse ),
+ iAvailDriveSpace( -1 ),
+#else
+ iPhoneMemoryOk( EFalse ),
+ iMmcOk( EFalse ),
+#endif
+ iRemovableMedia( EFalse ),
+ iStatusCode( KHttp902UserCancelled ),
+ iResult( KErrGeneral ),
+ iContentTypeCheck ( EFalse ),
+ iResumedDownload ( EFalse )
+ {
+ CLOG(( ECodEng, 2, _L("") ));
+ CLOG(( ECodEng, 2, _L("*****************") ));
+ CLOG(( ECodEng, 2, _L("CCodEngBase::CCodEngBase") ));
+ CLOG(( ECodEng, 2, _L8("Build time " __DATE__ " " __TIME__) ));
+ CActiveScheduler::Add( this );
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::ConstructL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::ConstructL( CEikProcess* aProcess )
+ {
+ iData = CCodData::NewL();
+ iDocHandler = CDocumentHandler::NewL( aProcess );
+ User::LeaveIfError( iFs.Connect() );
+#ifdef RD_MULTIPLE_DRIVE
+ QueryDriveListL();
+#endif
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::DoCancel()
+// ---------------------------------------------------------
+//
+void CCodEngBase::DoCancel()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::DoCancel iState(%d)"), iState ));
+
+ switch ( iState )
+ {
+ case ESet:
+ case EStartConnect:
+ case EStartFetch:
+ case EStartNotify:
+ {
+ // Already completed (by self-completion).
+ __ASSERT_DEBUG( iStatus != KRequestPending, \
+ CodPanic( ECodInternal ) );
+ SelfComplete( KErrCancel );
+ break;
+ }
+
+ case EConnect:
+ {
+ // Instant abort, without any further processing
+ // (no install, no notify).
+ __ASSERT_DEBUG( iConn, CodPanic( ECodInternal ) );
+ iConn->Cancel();
+ break;
+ }
+
+ case EFetch:
+ case ENotify:
+ {
+ // Instant abort, without any further processing
+ // (no install, no notify).
+ __ASSERT_DEBUG( iLoader, CodPanic( ECodInternal ) );
+ iLoader->Cancel();
+ break;
+ }
+
+ case EInstall:
+ {
+ // Instant abort, without any further processing (no notify).
+ __ASSERT_DEBUG( iSaver, CodPanic( ECodInternal ) );
+ iSaver->CancelInstall();
+ break;
+ }
+
+ case EInit:
+ case EReady:
+ case EStartInstall:
+ default:
+ {
+ // No requests should be outstanding in these states.
+ CodPanic( ECodInternal );
+ break;
+ }
+ }
+
+ iStatusCode = KHttp902UserCancelled; // "Clarity only" code.
+ iResult = KErrCancel; // "Clarity only" code.
+ Done(); // Complete parent.
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::DoCancel") ));
+ }
+
+
+EXPORT_C void CCodEngBase::Pause()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::Pause iState(%d)"), iState ));
+
+ switch ( iState )
+ {
+ case EFetch:
+ {
+ // Instant abort, without any further processing
+ // (no install, no notify).
+ __ASSERT_DEBUG( iLoader, CodPanic( ECodInternal ) );
+ iLoader->Pause();
+ //iLoader->CompleteTransaction();
+ break;
+ }
+ }
+
+ //Done(); // Complete parent.
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::Pause") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::RunL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::RunL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::RunL iStatus(%d) iState(%d)"), \
+ iStatus.Int(), iState ));
+
+ switch( iState )
+ {
+ case ESet:
+ {
+ SetL();
+ break;
+ }
+
+ case EStartInstallRoap:
+ {
+ StartInstallRoapL();
+ break;
+ }
+
+ case EInstallRoap:
+ {
+ EndInstallRoapL();
+ break;
+ }
+
+ case EStartConnect:
+ {
+ StartConnectL();
+ break;
+ }
+
+ case EConnect:
+ {
+ EndConnectL();
+ break;
+ }
+
+ case EStartFetch:
+ {
+ StartFetchL();
+ break;
+ }
+
+ case EFetch:
+ {
+ EndFetchL();
+ break;
+ }
+
+ case EStartInstall:
+ {
+ StartInstallL();
+ break;
+ }
+
+ case EInstall:
+ {
+ EndInstallL();
+ break;
+ }
+
+ case EStartNotify:
+ {
+ StartNotifyL();
+ break;
+ }
+
+ case ENotify:
+ {
+ EndNotifyL();
+ break;
+ }
+ case EMediaChange:
+ {
+ ChangeMediaObjectL();
+ break;
+ }
+ case EStartProductNotify:
+ {
+ StartProductNotifyL();
+ break;
+ }
+ case EProductNotify:
+ {
+ EndProductNotifyL();
+ break;
+ }
+ case EInit:
+ case EReady:
+ default:
+ {
+ // No requests should be outstanding in these states.
+ CLOG(( ECodEng, 0, _L("CCodEngBase::RunL: unexpected state") ));
+ CodPanic( ECodInternal );
+ break;
+ }
+ }
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::RunL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::RunError()
+// ---------------------------------------------------------
+//
+TInt CCodEngBase::RunError( TInt aError )
+ {
+ CLOG(( ECodEng, 2, \
+ _L("-> CCodEngBase::RunError iStatus(%d) iState(%d) aError(%d)"), \
+ iStatus.Int(), iState, aError ));
+ switch( iState )
+ {
+ case ESet:
+ {
+ delete iCodBuf;
+ iCodBuf = NULL;
+ // Failed - classify reason and notify about failure.
+ iStatusCode = StatusCode( aError, iState );
+ iResult = aError;
+ Continue( EStartNotify );
+ break;
+ }
+
+ case EStartInstallRoap:
+ case EInstallRoap:
+ {
+ iStatusCode = StatusCode( aError, iState );
+ iResult = aError;
+ Continue( EStartNotify );
+ break;
+ }
+ case EStartConnect:
+ case EConnect:
+ case EStartFetch:
+ case EFetch:
+ case EStartInstall:
+ case EInstall:
+ {
+
+ if(aError != KErrCodHttpServerError)
+ {
+ //if PreconditionFailed check if the updated DD URI is present
+ //cancel the download if not set
+ if( aError == KErrCodHttpPreconditionFailed )
+ {
+ if( iData && iData->UpdatedDDUriL().Length() )
+ {
+ iState = EInit;//in case of 412 we should restart from first state
+ iStatusCode = StatusCode( aError, iState );
+ TBuf<KMaxPath> folderName;
+ CODDownloadInfoFolder(folderName);
+
+ HBufC* fileNameBuf = HBufC::NewLC( KMaxPath );
+ TPtr fileName = fileNameBuf->Des();
+
+ fileName.Format( _L("%S%d"), &folderName,iDownloadId );
+ RFs fs;
+ User::LeaveIfError( fs.Connect() );
+ fs.Delete( fileName );//delete the info path as download has to begin from fresh state
+ CleanupStack::PopAndDestroy( fileNameBuf );
+ fs.Close();
+ }
+ else
+ {
+ // Failed - classify reason and notify about failure.
+ iStatusCode = StatusCode( aError, iState );
+ iResult = aError;
+
+ //If ther is no Updated DD Uri. Cancel the download.
+ DoCancel();
+ break;
+ }
+ }
+ else
+ {
+ //If user cancel the download, delete the media object also.
+ //If paused due to other errors, delete the file if non-pausable.
+ if(iSaver)
+ {
+ TBool delContent = (aError == KErrCancel) ? ETrue : !( iData && (*iData)[iData->ActiveDownload()]->iPausable );
+ iSaver->Cleanup( delContent );
+ }
+ }
+ if( iObserver && KErrCodHttpPreconditionFailed != aError)
+ {
+ //TODO : Pass the error code if required
+ iObserver->DownloadPaused();
+ iNotificationStatus = EPaused;
+ }
+
+ }
+ delete iSaver; // Cleans up.
+ iSaver = NULL;
+
+ // Failed - classify reason and notify about failure.
+ iStatusCode = StatusCode( aError, iState );
+ iResult = aError;
+ Continue( EStartNotify );
+ break;
+ }
+
+ case EStartNotify:
+ case ENotify:
+ {
+ //If Notify Fails do not delete download.
+ //Ignore the error code.
+ //End State Machine.Download is Successful.
+ Done();
+ break;
+ }
+ case EStartProductNotify:
+ case EProductNotify:
+ {
+ Done();
+ break;
+ }
+
+ case EInit:
+ case EReady:
+ default:
+ {
+ // No requests should be outstanding in these states.
+ CLOG(( ECodEng, 0, _L("CCodEngBase::RunError: unexpected state") ));
+ CodPanic( ECodInternal );
+ break;
+ }
+ }
+
+ if (iData && iData->Count())
+ {
+ (*iData)[iData->ActiveDownload()]->iStatusCode = iStatusCode;
+ (*iData)[iData->ActiveDownload()]->iResult = iResult;
+ }
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::RunError") ));
+ return KErrNone;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::SetL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::SetL (internal)") ));
+ __ASSERT_DEBUG( iState == ESet, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( iCodBuf, CodPanic( ECodInternal ) );
+
+ ParseDataL();
+
+ iData->SetActiveDownload ( 1 );
+ if( !(*(*iData)[iData->ActiveDownload()]).Name().Length() )
+ {
+ //No name To display
+ //add "unnamed"
+ (*(*iData)[iData->ActiveDownload()]).SetNameL( _L("Unnamed") );
+ }
+ CLOG(( ECodEng, 4, _L("CCodEngBase::SetL: parsed OK") ));
+ delete iCodBuf;
+ iCodBuf = NULL;
+ CheckDataL(); // TODO move that out from derived classes.
+
+ TInt err = KErrNone;
+ for( TInt i = 1; i <= iData->Count() ; ++i )
+ {
+ iData->SetActiveDownload ( i );
+ //So that this download is considered when resume happens
+ //only in progress download can resume
+ (*iData)[ iData->ActiveDownload()]->iState = EInProgress;
+ TRAP( err , CapabilityCheckL());
+ if( !err )
+ {
+ break;
+ }
+ else if( err != KErrCodInsufficientSpace )
+ {
+ User::Leave( err );
+ }
+ }
+
+ if( err )
+ {
+ User::Leave( err );
+ }
+ iState = EReady;
+ iResult = KErrNone;
+ iStatusCode = StatusCode( iResult, iState );
+
+ //Create info files
+ //This would create info file for album and each media track
+
+ StoreInfoFilesL();
+
+ // Update album and track info in server
+ UpdateMediaInfoL();
+
+ if (iIsLicense && !iData->IsPostOrder())
+ {
+ // install Roap trigger first
+ DoneDD2();
+ }
+ else
+ {
+ Done();
+ }
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::SetL (internal)") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetFileNameL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::SetFileNameL()
+ {
+
+ // Full name that we need to construct
+ HBufC* fullName = HBufC::NewLC(KMaxFileName);
+ TPtr fullNamePtr( fullName->Des() );
+ fullNamePtr.Append( (*iData)[iData->ActiveDownload()]->iTempPath ); // "c:\\system\\temp\\"
+ fullNamePtr.Append( (*iData)[iData->ActiveDownload()]->Name() ); // "c:\\system\\temp\\myfile"
+
+
+
+ const TDataType& type( (*iData)[iData->ActiveDownload()]->Types().MdcaPoint( 0) );
+
+ //Following code is added to fix the bug DRAI-7KA8TT( File is not available in Gallery even when download list shows "Saved to Gallery".)
+ //Fix applied: Changing the content type that is passed to document handler to "application/vnd.oma.drm.content" when the received content type is
+ //"application/vnd.oma.drm.message"
+ //This is because document handler is not changing the extension when content type is passed as "application/vnd.oma.drm.message"
+ if(0==type.Des8().Compare(KOma1DrmMessageContentType))
+ {
+ // Add extention to full name of file
+ iDocHandler->CheckFileNameExtension(fullNamePtr, TDataType(KOma1DcfContentType)); // "c:\\system\\temp\\myfile.mp3"
+ }
+ else
+ {
+ // Add extention to full name of file
+ iDocHandler->CheckFileNameExtension(fullNamePtr, type ); // "c:\\system\\temp\\myfile.mp3"
+ }
+
+ CleanupStack::Pop(fullName);
+
+ // This is the Full name that we want
+ delete (*iData)[iData->ActiveDownload()]->iFullName;
+ (*iData)[iData->ActiveDownload()]->iFullName = fullName;
+
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetUniqueFileNameL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::SetUniqueFileNameL()
+ {
+ HBufC* fullName = HBufC::NewLC(KMaxFileName);
+ TPtr fullNamePtr( fullName->Des() );
+ fullNamePtr.Append( (*iData)[iData->ActiveDownload()]->iFullName->Des() );
+
+ // Get the file path
+ HBufC* filePath = HBufC::NewLC(KMaxFileName);
+ filePath->Des().Append( (*iData)[iData->ActiveDownload()]->iTempPath ); // "c:\\system\\temp\\"
+
+ // Retrieve extention as a string
+ HBufC* extention = HBufC::NewLC(KMaxFileName);
+ TInt dotInd = fullNamePtr.LocateReverse( '.' );
+ if( dotInd != KErrNotFound )
+ // filename extension found.
+ {
+ extention->Des().Copy( fullNamePtr.Right( fullNamePtr.Length() - dotInd ) );
+ }
+
+ // File name without extention
+ HBufC* fileName = HBufC::NewLC(KMaxFileName);
+ fileName->Des().Append( (*iData)[iData->ActiveDownload()]->Name() ); // "myfile"
+ TInt dot = fileName->LocateReverse( '.' );//check if Dot is part of name in DD file
+ // Find a unique file name. If fileName already exists, then this function will
+ // change fileName to some other unique name (like "myfile(1)")
+ if( dot != KErrNotFound )
+ {
+ //Remove Extension
+ //File Name is with an extension.
+ fileName->Des().Copy( fileName->Des().Left(dot));
+ }
+ iSaver->ConvertDownloadNameUniqueL( filePath, fileName, extention );
+ HBufC* dispName = HBufC::NewLC(KMaxFileName);
+ TPtr displayName(dispName->Des());
+ displayName.Append(*fileName);
+ if( dot != KErrNotFound )
+ {
+ //Since Name is with extension Append to Display Name
+ displayName.Append(*extention);
+ }
+ (*iData)[iData->ActiveDownload()]->SetNameL( displayName );
+ CleanupStack::PopAndDestroy(dispName);
+
+
+ // Now when we have a unique file name, create the full name (with path and extention)
+ fullNamePtr.Copy( *filePath );
+ fullNamePtr.Append( *fileName );
+ fullNamePtr.Append( *extention ); // Example - "c:\\system\\temp\\myfile(1).mp3"
+ CleanupStack::PopAndDestroy(fileName);
+ CleanupStack::PopAndDestroy(extention);
+ CleanupStack::PopAndDestroy(filePath);
+ CleanupStack::Pop(fullName);
+
+ // This is the Full name that we want
+ delete (*iData)[iData->ActiveDownload()]->iFullName;
+ (*iData)[iData->ActiveDownload()]->iFullName = fullName;
+
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StartConnectL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StartConnectL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::StartConnectL") ));
+ __ASSERT_DEBUG( iState == EStartConnect, CodPanic( ECodInternal ) );
+ if (!iIsLicense )
+ {
+ __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
+ }
+ __ASSERT_DEBUG( !iConn, CodPanic( ECodInternal ) );
+
+
+ //For the first track it is done already
+ CapabilityCheckL();
+
+ //Inform server about the Active download
+ iObserver->SetActiveDownload( );
+ iObserver->ContentTypeChanged();
+ iObserver->MediaObjectNameChanged();
+
+ //Content type check should be done for subsequent tracks
+ iContentTypeCheck = EFalse;
+
+ //Download is resumed for the current track in the album. For the subsequent tracks(downloads),iResumedDownload should be false
+ iResumedDownload = EFalse;
+
+
+ //Let all download that begin be in this state and then go to subsequent Succeeded state
+ (*iData)[iData->ActiveDownload()]->iState = EInProgress;
+
+ if ( iFsUsed && (*iData)[iData->ActiveDownload()]->iTempPath == KNullDesC )
+ {
+ // Select drive before IAP selection.
+ SetPathsL();
+ SetFileNameL();
+ //Store in Info File
+ StoreSubInfoFileL( NULL, iData->ActiveDownload() );
+ }
+ else
+ {
+ //Paused Download change display name if not already done
+ iObserver->MediaObjectNameChanged();
+ }
+
+ if ( CodUtil::IsCidSchemeL( (*iData)[iData->ActiveDownload()]->Url() ) &&
+ ( !(*iData)[iData->ActiveDownload()]->InstallNotify().Length() ||
+ CodUtil::IsCidSchemeL( (*iData)[iData->ActiveDownload()]->InstallNotify() )
+ )
+ )
+ {
+ CLOG(( ECodEng, 3, _L(" all URI-s are cid -> no connect") ));
+ // All URI-s are cid, no need to connect.
+ // Synchronous state change - we are already under RunL().
+ iState = EConnect;
+ EndConnectL();
+ }
+ else
+ {
+ // We have at least one non-cid scheme URI, need to connect.
+ CLOG(( ECodEng, 3, _L(" connecting") ));
+ iConn = CConnection::NewL();
+ iConn->ConnectL( iPreferredIap, &iStatus );
+ iState = EConnect;
+ SetActive();
+ if ( iObserver )
+ {
+ CLOG(( ECodEng, 3, \
+ _L("-> CCodEngBase::StartConnectL notify StartLoadL(%d)"), \
+ KHttp900Success ));
+ iObserver->StartLoadL( KHttp900Success );
+ iNotificationStatus = ELoad;
+ }
+ }
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::StartConnectL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::EndConnectL
+// ---------------------------------------------------------
+//
+void CCodEngBase::EndConnectL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::EndConnectL iStatus(%d)"), \
+ iStatus.Int() ));
+ __ASSERT_DEBUG( iState == EConnect, CodPanic( ECodInternal ) );
+
+ User::LeaveIfError( iStatus.Int() ); // Handle errors in RunError().
+
+ // Synchronous state change - we are already under RunL().
+ iState = EStartFetch;
+ StartFetchL();
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::EndConnectL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StartFetchL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StartFetchL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::StartFetchL") ));
+ __ASSERT_DEBUG( iState == EStartFetch, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( !iLoader, CodPanic( ECodInternal ) );
+ if (!iIsLicense )
+ {
+ __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
+ }
+
+ // Setup progress.
+ // Fetch size is known. ROAP & notify traffic is estimated.
+ if(!iProgress)
+ {
+ iProgress = new (ELeave) TCodProgress( iObserver );
+
+ TInt roapBytes = (*iData)[iData->ActiveDownload()]->Type().Compare( KOma2TriggerContentType ) ?
+ 0 :
+ KRoapProgressMax;
+/*
+ iProgress->Setup
+ (
+ iData->Size() + roapBytes ,
+ iData->InstallNotify().Length() ? KCodNotifyTraffic : 0
+ );
+*/
+ iProgress->Setup
+ (
+ (*iData)[iData->ActiveDownload()]->Size() + roapBytes ,
+ iData->InstallNotify().Length() ? KCodNotifyTraffic : 0
+ );
+ }
+
+ if ( CodUtil::IsCidSchemeL( (*iData)[iData->ActiveDownload()]->Url() ) )
+ {
+ if ( !iParts )
+ {
+ // Cannot resolve cid: scheme URI-s without the multipart parts!
+ CLOG(( ECodEng, 4, _L(" no multipart, fail") ));
+ User::Leave( KErrNotFound );
+ }
+ CBodyPart* part = CodUtil::PartByCidL( *iParts, (*iData)[iData->ActiveDownload()]->Url() );
+ if ( !part )
+ {
+ CLOG(( ECodEng, 4, _L(" part not found, fail") ));
+ User::Leave( KErrNotFound );
+ }
+ CreateSaverL( part->ContentType() );
+ User::LeaveIfError( iSaver->AppendData( part->Body() ) );
+ iSaver->CloseStore();
+ iProgress->IncrementL( part->Body().Size() );
+ // Synchronous state change - we are already under RunL().
+ iState = EFetch;
+ EndFetchL();
+ }
+ else
+ {
+ __ASSERT_DEBUG( iConn, CodPanic( ECodInternal ) );
+ iLoader = CHttpLoader::NewL( *iConn, NULL, iProgress ,this);
+ HBufC8* url = CodUtil::AbsoluteUrlLC
+ ( iData->SourceUri(), (*iData)[iData->ActiveDownload()]->Url() );
+ iLoader->LoadL( *url, *this, &iStatus );
+ CleanupStack::PopAndDestroy( url );
+
+ iState = EFetch;
+ SetActive();
+ }
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::StartFetchL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::EndFetchL
+// ---------------------------------------------------------
+//
+void CCodEngBase::EndFetchL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::EndFetchL iStatus(%d)"), \
+ iStatus.Int() ));
+ __ASSERT_DEBUG( iState == EFetch, CodPanic( ECodInternal ) );
+
+ User::LeaveIfError( iStatus.Int() ); // Handle errors in RunError().
+
+ __ASSERT_DEBUG( iSaver, CodPanic( ECodInternal ) );
+//TODO: ?? iState == EStoreOpen (for dd2) EStoreClose - for dd1
+ iSaver->CheckResponseAttributesL( *iData ); // Leaves if response not OK.
+
+ if (iIsLicense)
+ {
+ iStatusCode = KHttp956LicenseSuccess;
+ }
+ else
+ {
+ iStatusCode = KHttp900Success;
+ }
+ iResult = KErrNone;
+ // Synchronous state change - we are already under RunL().
+ iState = EStartInstall;
+ StartInstallL();
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::EndFetchL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StartInstallL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StartInstallL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::StartInstallL iStatusCode(%d)"), \
+ iStatusCode ));
+ __ASSERT_DEBUG( iState == EStartInstall, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( iSaver, CodPanic( ECodInternal ) );
+
+ //__ASSERT_DEBUG( iStatusCode == KHttp900Success, CodPanic( ECodInternal ) );
+
+ (*iData)[iData->ActiveDownload()]->iState = ETobeInstalled;
+
+ if( iData->Count() > 1)
+ {
+ // Check to see if all tracks are downloaded. Install will be done only at the end
+ for( TInt i = 1; i <= iData->Count() ; ++i )
+ {
+ TInt state ((*iData)[i]->iState);
+ if( state != ETobeInstalled && state != ESucceeded )
+ {
+ Continue(EInstall);
+ return;
+ }
+ }
+ }
+
+ TInt installErr( KErrNone );
+
+ if (iObserver && (iObserver->ConnError() == KErrTimedOut))
+ {
+ User::LeaveIfError( KErrTimedOut );
+ }
+ else
+ {
+ if( iData->Count() > 1)
+ {
+ TRAP( installErr, iSaver->BulkInstallL( &iStatus, *iData, iAttached ));
+ }
+ else
+ {
+ if (!iIsDd2)
+ {
+ TRAP( installErr, iSaver->InstallL( &iStatus, (*iData)[iData->ActiveDownload()]->Name(), iAttached ));
+ }
+ else
+ {
+ TRAP( installErr, iSaver->InstallL( &iStatus, (*iData)[iData->ActiveDownload()]->iFullName->Des(), iAttached ));
+ }
+ //Move has happened update destination file name
+ (*iData)[ iData->ActiveDownload()]->iFullName = iSaver->NameL();
+ }
+ }
+
+ // if download is DRM-protected content with Preview-only rights
+ // then we cannot move content, but will launch it from the temp file
+ // that it is currently in. For all other errors we leave.
+ if( installErr == KDRMErrPreviewRights )
+ {
+ iDrmPreviewOnly = ETrue;
+ }
+ else
+ {
+ User::LeaveIfError( installErr );
+ }
+ SetActive();
+ iState = EInstall;
+ CLOG(( ECodEng, 4, _L("<- CCodEngBase::StartInstallL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StartInstallRoapL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StartInstallRoapL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::StartInstallRoapL iStatusCode(%d)"), \
+ iStatusCode ));
+ __ASSERT_DEBUG( iState == EStartInstallRoap, CodPanic( ECodInternal ) );
+//TODO check if we have a retry the iSaver could be NULL ?
+ if (iSaver)
+ {
+ iSaver->InstallL( &iStatus, (*iData)[iData->ActiveDownload()]->Name(), ETrue );
+ }
+ // Synchronous state change - we are already under RunL().
+ iState = EInstallRoap;
+ SetActive();
+
+ CLOG(( ECodEng, 4, _L("<- CCodEngBase::StartInstallRoapL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::EndInstallRoapL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::EndInstallRoapL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::InstallRoapL iStatusCode(%d)"), \
+ iStatusCode ));
+
+ User::LeaveIfError( iStatus.Int() ); // Handle errors in RunError().
+//TODO: make sure that 956 and 900 sent
+ iStatusCode = KHttp956LicenseSuccess;
+ iResult = KErrNone;
+// iSaver->CloseStore();
+ iState = EStartConnect;
+ StartConnectL();
+ CLOG(( ECodEng, 4, _L("<- CCodEngBase::EndInstallRoapL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::EndInstallL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::EndInstallL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::EndInstallL iStatus(%d)"), \
+ iStatus.Int() ));
+ __ASSERT_DEBUG( iState == EInstall, CodPanic( ECodInternal ) );
+
+ User::LeaveIfError( iStatus.Int() ); // Handle errors in RunError().
+ // Synchronous state change - we are already under RunL().
+ iState = EStartNotify;
+ StartNotifyL();
+ CLOG(( ECodEng, 4, _L("<- CCodEngBase::EndInstallL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StartNotifyL
+// ---------------------------------------------------------
+//
+void CCodEngBase::StartNotifyL()
+ {
+ __ASSERT_DEBUG( iState == EStartNotify, CodPanic( ECodInternal ) );
+
+ if ( iData && iData->Count() > 0 && iData->ActiveDownload() && (*iData)[iData->ActiveDownload()]->InstallNotify().Length() )
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::StartNotifyL iStatusCode(%d)"), \
+ iStatusCode ));
+
+ CLOG(( ECodEng, 4, _L("CCodEngBase::StartNotifyL: init request") ));
+ if ( !iProgress )
+ {
+ // Setup notify-only progress.
+ iProgress = new (ELeave) TCodProgress( iObserver );
+ iProgress->Setup( 0, KCodNotifyTraffic );
+ }
+ iProgress->StartPhaseL( TCodProgress::ENotify );
+ TBool notifyObserver = EFalse;
+ // When notifying after fetch, we already have a loader (and the
+ // observer has already been notified about load).
+ // When notifying without fetch, we don't have a loader yet (and the
+ // observer has not been notified about load yet).
+ if ( !iConn )
+ {
+ iConn = CConnection::NewL();
+ }
+ // For notify, attach only (do no create new connection).
+ iConn->AttachL( iPreferredIap );
+ if( !iLoader )
+ {
+ iLoader = CHttpLoader::NewL( *iConn, NULL, iProgress ,this );
+ notifyObserver = ETrue;
+ }
+ HBufC8* url = CodUtil::AbsoluteUrlLC
+ ( (*iData)[iData->ActiveDownload()]->SourceUri(), (*iData)[iData->ActiveDownload()]->InstallNotify() );
+ iLoader->NotifyL( *url, StatusText( iStatusCode ), &iStatus );
+ CleanupStack::PopAndDestroy( url );
+ iState = ENotify;
+ SetActive();
+ if ( iObserver && notifyObserver )
+ {
+ if ( iStatusCode == KHttp902UserCancelled ||
+ iStatusCode == KHttp921UserAborted )
+ {
+ CLOG(( ECodEng, 3, \
+ _L("-> CCodEngBase::StartNotifyL notify StartCancelL") ));
+ iObserver->StartCancelL();
+ iNotificationStatus = ECancel;
+ }
+ else
+ {
+ CLOG(( ECodEng, 3, \
+ _L("-> CCodEngBase::StartNotifyL notify StartLoadL(%d)"), \
+ iStatusCode ));
+ iObserver->StartLoadL( iStatusCode );
+ iNotificationStatus = ELoad;
+ }
+ }
+ }
+ else
+ {
+ // No install notify attribute, regarded as successful notification.
+ CLOG(( ECodEng, 4, _L("CCodEngBase::StartNotifyL: nothing to do") ));
+ Continue( ENotify );
+ }
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::StartNotifyL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::EndNotifyL
+// ---------------------------------------------------------
+//
+void CCodEngBase::EndNotifyL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::EndNotifyL iStatus(%d)"), \
+ iStatus.Int() ));
+ __ASSERT_DEBUG( iState == ENotify, CodPanic( ECodInternal ) );
+
+ delete iLoader;
+ iLoader = NULL;
+ delete iConn;
+ iConn = NULL;
+
+ User::LeaveIfError( iStatus.Int() ); // Handle errors in RunError().
+
+ // Do not leave after this point! Notify was successful, we must keep
+ // downloaded content now.
+
+ if ( iProgress )
+ {
+ TRAP_IGNORE( iProgress->DoneL() );
+ delete iProgress;
+ iProgress = NULL;
+ }
+
+ if( iSaver && iResult == KErrNone )
+ {
+//TODO: check if in case of PD we should release. It is already done.
+ iSaver->ReleaseContent( (*iData)[iData->ActiveDownload()]->iFileName, iHandler );
+
+ if ((!(*iData)[iData->ActiveDownload()]->iFullName) || (!((*iData)[iData->ActiveDownload()]->iFullName->Compare(KNullDesC))))
+ {
+ delete (*iData)[iData->ActiveDownload()]->iFullName;
+ (*iData)[iData->ActiveDownload()]->iFullName = (*iData)[iData->ActiveDownload()]->iFileName.AllocL();
+ }
+
+ iType = iSaver->DataType();
+ }
+
+ //Done();
+ Continue ( EMediaChange );
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::EndNotifyL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::Done
+// ---------------------------------------------------------
+//
+void CCodEngBase::Done()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::Done iResult(%d)"), iResult ));
+
+ if( iSaver )
+ {
+ iSaver->Cleanup( !(*iData)[iData->ActiveDownload()]->iPausable );
+ }
+
+ delete iSaver; // Cleans up unless Release()-d.
+ iSaver = NULL;
+ delete iLoader;
+ iLoader = NULL;
+ delete iConn;
+ iConn = NULL;
+ delete iCodBuf;
+ iCodBuf = NULL;
+ delete iProgress;
+ iProgress = NULL;
+
+ if( iObserver )
+ {
+ CLOG(( ECodEng, 3, \
+ _L("CCodEngBase::Done notify Done code(%d) err(%d)"), \
+ iStatusCode, iResult ));
+ iObserver->Done( iStatusCode, iResult );
+ iNotificationStatus = ENull;
+ }
+
+ // Reinit state.
+ iState = iData->IsValid() ? EReady : EInit;
+ // Notify parent.
+ __ASSERT_DEBUG( iParentStatus, CodPanic( ECodInternal ) );
+ User::RequestComplete( iParentStatus, iResult );
+ iParentStatus = NULL;
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::Done") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::DoneDD2
+// ---------------------------------------------------------
+//
+void CCodEngBase::DoneDD2()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::Done iResult(%d)"), iResult ));
+ delete iLoader;
+ iLoader = NULL;
+ delete iConn;
+ iConn = NULL;
+ delete iCodBuf;
+ iCodBuf = NULL;
+ delete iProgress;
+ iProgress = NULL;
+
+ if( iObserver )
+ {
+ CLOG(( ECodEng, 3, \
+ _L("CCodEngBase::Done notify Done code(%d) err(%d)"), \
+ iStatusCode, iResult ));
+ iObserver->Done( iStatusCode, iResult );
+ iNotificationStatus = ENull;
+ }
+
+ // Reinit state.
+ iState = iData->IsValid() ? EReady : EInit;
+ // Notify parent.
+ __ASSERT_DEBUG( iParentStatus, CodPanic( ECodInternal ) );
+ User::RequestComplete( iParentStatus, iResult );
+ iParentStatus = NULL;
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::Done") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::Continue
+// ---------------------------------------------------------
+//
+void CCodEngBase::Continue( TState aNextState )
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::Continue nextState(%d)"), \
+ aNextState ));
+ __ASSERT_DEBUG( !IsActive(), CodPanic( ECodInternal ) );
+
+ iState = aNextState;
+ TRequestStatus* ownStatus = &iStatus;
+ *ownStatus = KRequestPending;
+ SetActive();
+ User::RequestComplete( ownStatus, KErrNone );
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::Continue") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SelfComplete
+// ---------------------------------------------------------
+//
+void CCodEngBase::SelfComplete( TInt aError )
+ {
+ // This method safely handles the case when a request may be completed
+ // multiple times.
+ // The main use is for content viewing (EContentView state), where
+ // there is no real external request made and the request can complete
+ // the following ways:
+ // - Embedded viewer exits and calls NotifyExit()
+ // - CodEng is Cancelled (e.g. deleted, if Exit is issued inside the
+ // embedded viewer.
+ CLOG(( ECodEng, 2, _L("CCodEngBase::SelfComplete(%d)"), aError ));
+ if ( iStatus == KRequestPending )
+ {
+ // Request is pending, complete now.
+ CLOG(( ECodEng, 4, _L(" completing now") ));
+ TRequestStatus* ownStatus = &iStatus;
+ User::RequestComplete( ownStatus, aError );
+ }
+ else
+ {
+ // Request already completed.
+ // - If this second completion is error, override status.
+ // - If this second completion is success, don't override - existing
+ // result may be error and we can't undo that.
+ CLOG(( ECodEng, 4, _L(" already completed") ));
+ if ( aError != KErrNone )
+ {
+ iStatus = aError;
+ }
+ }
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::CapabilityCheckL
+// ---------------------------------------------------------
+//
+void CCodEngBase::CapabilityCheckL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::CapabilityCheckL") ));
+ __ASSERT_DEBUG( iData->ActiveDownload(),CodPanic( ECodInternal ));
+ // 1. Data type checking.
+ TInt typeErr( KErrNone );
+#ifdef __SYNCML_DM_FOTA
+ TBool fota( EFalse );
+#endif /*def __SYNCML_DM_FOTA */
+ for ( TInt i = 0; i < (*iData)[iData->ActiveDownload()]->Types().MdcaCount() && !iContentTypeCheck; i++ )
+ {
+ const TDataType& type( (*iData)[iData->ActiveDownload()]->Types().MdcaPoint( i ) );
+#ifdef __TEST_COD_LOG
+ TPtrC8 mime( type.Des8() );
+#endif /* def __TEST_COD_LOG */
+
+ if (
+ type == TDataType( KOma1XmlRoContentType ) ||
+ type == TDataType( KOma1WbxmlRoContentType )
+ )
+ {
+ // DRM related types which are not proper files (not saved to FS).
+ CLOG(( ECodEng, 4, _L8(" <%S> DRM1 rights OK"), &mime ));
+ iIsDd2 = EFalse;
+ }
+ else if ( type == TDataType( KOma1DrmMessageContentType ) )
+ {
+ // Accept DRM message. The system supports it but
+ // DocHandler does not report this.
+ CLOG(( ECodEng, 4, _L8(" <%S> DRM1 msg OK"), &mime ));
+ iFsUsed = ETrue;
+ }
+#ifdef __DRM_OMA2
+ else if (
+ type == TDataType( KOma2RoContentType ) ||
+ type == TDataType( KOma2ProtectedRoType ) ||
+ type == TDataType( KOma2TriggerContentType )
+ )
+ {
+ // DRM related types which are not proper files (not saved to FS).
+ CLOG(( ECodEng, 4, _L8(" <%S> DRM2 rights OK"), &mime ));
+ iIsDd2 = EFalse;
+ }
+#endif /*def __DRM_OMA2*/
+#ifdef __SYNCML_DM_FOTA
+ else if ( type == TDataType( KFotaPackageDataType ) )
+ {
+ // Accept FOTA download. Special storage (not saved to FS).
+ CLOG(( ECodEng, 4, _L8(" <%S> FOTA OK"), &mime ));
+ fota = ETrue;
+ }
+#endif /*def __SYNCML_DM_FOTA */
+ else
+ {
+ CLOG(( ECodEng, 4, _L8(" <%S> DocHandler check"), &mime ));
+ iFsUsed = ETrue;
+
+ if ( !iResumedDownload )
+ {
+ TRAP( typeErr, iDocHandler->CanOpenL( type ));
+ if (typeErr == KMimeNotSupported)
+ {
+ CAknQueryDialog* dialog = CAknQueryDialog::NewL();
+ dialog->PrepareLC(R_COD_UI_CONFIRM_NOTE);
+ HBufC* prompt;
+ prompt = StringLoader::LoadLC(R_QTN_BROWSER_DOWNLOADS_UNSUPPORTED_CONTENT_QUERY);
+ dialog->SetPromptL(*prompt);
+ CleanupStack::PopAndDestroy( prompt );
+ if(!dialog->RunLD())
+ {
+ User::Leave( KHttp902UserCancelled );
+ }
+ }
+ }
+ }
+ }
+
+ // 2. Storage space checking. (Depends on data types.)
+
+ TInt size = (*iData)[iData->ActiveDownload()]->Size() - (*iData)[iData->ActiveDownload()]->DownloadedSize();
+ TInt bytesToWrite = size;
+ if (bytesToWrite < 0)
+ bytesToWrite = 0;
+
+ if ( iFsUsed )
+ {
+ CLOG(( ECodEng, 2, _L(" FS check (%d)"), size ));
+#ifdef RD_MULTIPLE_DRIVE
+ TInt err( KErrNone );
+ iSpaceAvailOk = EFalse;
+ User::LeaveIfError(
+ DriveInfo::GetDefaultDrive( DriveInfo::EDefaultPhoneMemory, iAvailDriveSpace ) );
+
+ HBufC8* drivesDynList = QueryDynDriveListLC();
+ TPtrC8 drives( *drivesDynList );
+
+ // drive letters are separated by semicolons
+ for( TInt i = 0; i < drives.Length() && (err || !iSpaceAvailOk); i = i + 2 )
+ {
+ if( (err = iFs.CharToDrive( drives[i], iAvailDriveSpace )) == KErrNone )
+ {
+ // Check if there's enough memory in the phone
+ TRAP( err, iSpaceAvailOk = !SysUtil::DiskSpaceBelowCriticalLevelL(
+ &iFs,
+ bytesToWrite,
+ iAvailDriveSpace ));
+ }
+ else
+ {
+ CLOG(( ECodEng, 4, _L("Bad drive letter [%c]"), drives[i] ));
+ }
+ }
+ CleanupStack::PopAndDestroy( drivesDynList );
+
+ if( err || !iSpaceAvailOk )
+ {
+ User::Leave( KErrCodInsufficientSpace );
+ }
+#else
+ iPhoneMemoryOk = EFalse;
+ iMmcOk = EFalse;
+ // Check C:
+ iPhoneMemoryOk = !SysUtil::FFSSpaceBelowCriticalLevelL( &iFs, bytesToWrite );
+ CLOG(( ECodEng, 4, _L(" iPhoneMemoryOk(%d)"), iPhoneMemoryOk ));
+ RFeatMgr featMgr;
+ featMgr.OpenL();
+ CleanupClosePushL<RFeatMgr>( featMgr );
+ if ( featMgr.FeatureSupported( KFeatureIdMmc ) )
+ {
+ // If no MMC is inserted, this will leave (and not set iMmcOk).
+ TRAP_IGNORE( iMmcOk = !SysUtil::MMCSpaceBelowCriticalLevelL
+ ( &iFs, bytesToWrite ); )
+ }
+ CleanupStack::PopAndDestroy(); // featMgr
+ CLOG(( ECodEng, 4, _L(" iMmcOk(%d)"), iMmcOk ));
+ if( !(iPhoneMemoryOk || iMmcOk) )
+ {
+ User::Leave( KErrCodInsufficientSpace );
+ }
+#endif
+ }
+
+#ifdef __SYNCML_DM_FOTA
+ if ( fota )
+ {
+ // Transient FOTA session is used to check store space -> waste.
+ // Pre-allocate FOTA saver to avoid this (??) makes the saver's
+ // lifespan hard to follow, error-prone. TODO (??)
+ CLOG(( ECodEng, 2, _L(" FOTA check (%d)"), size ));
+ RFotaEngineSession fotaEng;
+ CleanupClosePushL<RFotaEngineSession>( fotaEng );
+ fotaEng.OpenL();
+ if ( !fotaEng.IsPackageStoreSizeAvailable( size ) )
+ {
+ User::Leave( KErrCodInsufficientSpace );
+ }
+ CleanupStack::PopAndDestroy( &fotaEng );
+ }
+#endif /*def __SYNCML_DM_FOTA */
+
+ //When reached here, it is assured that capability check is done successfully
+ //for the active download.
+ //Content type check is done for this track
+ iContentTypeCheck = ETrue;
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::CapabilityCheckL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::CreateSaverL
+// ---------------------------------------------------------
+//
+CCodSaver* CCodEngBase::CreateSaverL( const TDesC8& aType )
+ {
+ CLOG(( ECodEng, 2, _L8("-> CCodEngBase::CreateSaverL <%S>"), &aType ));
+//TODO: __ASSERT_DEBUG( !iSaver, CodPanic( ECodInternal ) );
+ // TODO check attribute match (early reject mismatched or unsupported types)!
+
+ if( aType == KNullDesC8 )
+ {
+ return NULL;
+ }
+
+// DD1 and DD2 cases
+ if (( aType.Find( KOma2TriggerContentType ) != KErrNotFound) || ( aType.Find( KDd2DataType ) != KErrNotFound )|| ( aType.Find( KOma1WbxmlRoContentType ) != KErrNotFound ))
+ {
+ iSaver = CRoapSaver::NewL( aType, iRoapData, iProgress, KRoapProgressMax, (*iData)[iData->ActiveDownload()]->iTempPath, (*iData)[iData->ActiveDownload()]->iRootPath, KNullDesC());
+ iSaver->SetObserver( iObserver );
+ iSaver->SetParams( iParams );
+ iSaver->SetMaxSize( iData->Size() );
+ iSaver->OpenStoreL(); // TODO unneeded method, put to construction.
+ }
+#ifdef __SYNCML_DM_FOTA
+ else if ( aType.Find( KFotaPackageDataType ) != KErrNotFound )
+ {
+ TInt pkgId( KCodDefaultFotaPkgId );
+ if ( iParams )
+ {
+ CodUtil::GetIntParam( pkgId, EGenericParamFotaPkgId, *iParams );
+ }
+ iSaver = CFotaSaver::NewL( aType, pkgId );
+ iSaver->SetObserver( iObserver );
+ iSaver->SetParams( iParams );
+ iSaver->SetMaxSize( iData->Size() );
+ iSaver->OpenStoreL(); // TODO unneeded method, put to construction.
+ }
+#endif /*def __SYNCML_DM_FOTA */
+ else
+ {
+ // TODO the assert below crashes without early reject!
+ //__ASSERT_DEBUG( iFsUsed, CodPanic( ECodInternal ) );
+
+ TBool contentTypeMisMatch ( ETrue );
+ for ( TInt i = 0; i < (*iData)[iData->ActiveDownload()]->Types().MdcaCount(); i++ )
+ {
+ const TDataType& type( (*iData)[iData->ActiveDownload()]->Types().MdcaPoint( i ) );
+ if( ( aType.Find (type.Des8()) != KErrNotFound ) ||
+ ( (type.Des8().Find(KOma1DrmMessageContentType)!= KErrNotFound) && (aType.Find(KOma1DcfContentType)!= KErrNotFound ) ))
+ {
+ contentTypeMisMatch = EFalse;
+ break;
+ }
+ }
+ if(contentTypeMisMatch)
+ {
+ User::Leave(KErrCodAttributeMismatch);
+ }
+
+ // Do this only if Unique filename check has never been performed earlier for this file.
+ if (( !(*iData)[iData->ActiveDownload()]->IsUniqueFilenameSet() ))
+ {
+ // Append an index to filename in case file with same name already exists
+ SetUniqueFileNameL();
+ (*iData)[iData->ActiveDownload()]->UniqueFilenameSet( ETrue );
+
+ CArrayPtrFlat<CHeaderField>* headers = NULL;
+ if (iLoader)
+ headers = iLoader->ResponseHeaders();
+
+ // Store in Sub-Info File
+ StoreSubInfoFileL( headers, iData->ActiveDownload() );
+ // Name changed. Inform server.
+ iObserver->MediaObjectNameChanged();
+ }
+
+ if (iIsDd2)
+ {
+ iSaver = CFileSaver::NewL( ((*iData)[iData->ActiveDownload()]->Types().MdcaPoint( 0)), iFs, *iDocHandler, (*iData)[iData->ActiveDownload()]->iTempPath, (*iData)[iData->ActiveDownload()]->iRootPath, (*iData)[iData->ActiveDownload()]->iFullName->Des());
+ }
+ else
+ {
+ iSaver = CFileSaver::NewL( aType, iFs, *iDocHandler, (*iData)[iData->ActiveDownload()]->iTempPath, (*iData)[iData->ActiveDownload()]->iRootPath, (*iData)[iData->ActiveDownload()]->iFullName->Des());
+ }
+ iSaver->SetObserver( iObserver );
+ iSaver->SetParams( iParams );
+ iSaver->SetMaxSize( iData->Size() );
+ iSaver->OpenStoreL(); // TODO unneeded method, put to construction.
+ iSaver->ReleaseFileName( (*iData)[iData->ActiveDownload()]->iFileName);
+ //send message that PDL is available. The DlMgrUiLib will have a "Play" option available
+ /*
+ OMA 2:
+ If the Media Object of the Product containing the Media Object has a license element,
+ the Download Agent MUST NOT make the Media Object(s) available for rendering before
+ the License has been successfully installed..
+ Only the order tag equals to any allows to install the License element first.
+ */
+ if ((iIsDd2 && iObserver && iData && (*iData)[iData->ActiveDownload()]->ProgressiveDownload() && !iIsLicense) ||
+ (iIsDd2 && iObserver && iData && (*iData)[iData->ActiveDownload()]->ProgressiveDownload() && iIsLicense && !iData->IsPostOrder()))
+ {
+ iSaver->ReleaseFileName( (*iData)[iData->ActiveDownload()]->iFileName);
+ iObserver->PdPlayAvailable();
+ }
+ }
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::CreateSaverL") ));
+ return iSaver;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::SetPathsL
+// ---------------------------------------------------------
+//
+void CCodEngBase::SetPathsL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::SetPathsL") ));
+#ifdef RD_MULTIPLE_DRIVE
+ __ASSERT_DEBUG( iSpaceAvailOk, CodPanic( ECodInternal ) );
+#else
+ __ASSERT_DEBUG( iPhoneMemoryOk || iMmcOk, CodPanic( ECodInternal ) );
+ __ASSERT_DEBUG( iFsUsed, CodPanic( ECodInternal ) );
+#endif
+ (*iData)[iData->ActiveDownload()]->iTempPath = KNullDesC;
+ (*iData)[iData->ActiveDownload()]->iRootPath = KNullDesC;
+#ifdef RD_MULTIPLE_DRIVE
+ if ( iSpaceAvailOk )
+ {
+ User::LeaveIfError( PathInfo::GetRootPath( (*iData)[iData->ActiveDownload()]->iRootPath, iAvailDriveSpace ) );
+ }
+#else
+ if ( iPhoneMemoryOk && iMmcOk && iObserver )
+ {
+ iObserver->GetRootPathL( (*iData)[iData->ActiveDownload()]->iRootPath );
+ if(!(*iData)[iData->ActiveDownload()]->iRootPath.Compare(_L("C:\\")))
+ {
+ (*iData)[iData->ActiveDownload()]->iRootPath = PathInfo::PhoneMemoryRootPath();
+
+ }
+ }
+ else if ( iPhoneMemoryOk )
+ {
+ (*iData)[iData->ActiveDownload()]->iRootPath = PathInfo::PhoneMemoryRootPath();
+ }
+ else
+ {
+ __ASSERT_DEBUG( iMmcOk, CodPanic( ECodInternal ) );
+ (*iData)[iData->ActiveDownload()]->iRootPath = PathInfo::MemoryCardRootPath();
+ }
+#endif
+
+ TParsePtrC rootPath( (*iData)[iData->ActiveDownload()]->iRootPath );
+ TBuf<KMaxPath> tempBuf;
+ // Set temp path to the same drive.
+ tempBuf.Format( KDownloadFolderFormat,
+ &KCodDefaultTempDir,
+ iAppUId,
+ &KTempFilesCodDirName );
+
+ (*iData)[iData->ActiveDownload()]->iTempPath.Append(rootPath.Drive());
+ (*iData)[iData->ActiveDownload()]->iTempPath.Append(tempBuf);
+
+ TDriveInfo info;
+ TDriveUnit unit( rootPath.Drive() );
+ User::LeaveIfError( iFs.Drive( info, unit ) );
+ // Create the temp directory earlier in case it's not created yet
+ iFs.MkDirAll( (*iData)[iData->ActiveDownload()]->iTempPath );
+ if ( info.iDriveAtt & KDriveAttRemovable )
+ {
+ iRemovableMedia = ETrue;
+ }
+
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::SetPathsL root<%S> temp<%S>"), \
+ &(*iData)[iData->ActiveDownload()]->iRootPath, &(*iData)[iData->ActiveDownload()]->iTempPath ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::ResetPaths
+// ---------------------------------------------------------
+//
+void CCodEngBase::ResetPaths()
+ {
+ iFsUsed = EFalse;
+#ifdef RD_MULTIPLE_DRIVE
+ iSpaceAvailOk = EFalse;
+ DriveInfo::GetDefaultDrive( DriveInfo::EDefaultPhoneMemory, iAvailDriveSpace );
+#else
+ iPhoneMemoryOk = EFalse;
+ iMmcOk = EFalse;
+#endif
+ //(*iData)[iData->ActiveDownload()]->iTempPath = KNullDesC;
+ //(*iData)[iData->ActiveDownload()]->iRootPath = KNullDesC;
+ iRemovableMedia = EFalse;
+ }
+
+#ifdef RD_MULTIPLE_DRIVE
+//------------------------------------------------------------------------
+//CCodEngBase::QueryDynDriveListLC
+//------------------------------------------------------------------------
+HBufC8* CCodEngBase::QueryDynDriveListLC()
+ {
+ TDriveList driveList;
+ TInt driveCount( 0 );
+ TChar driveLetter;
+ TBuf8<KMaxDriveListStrLen> driveLettersDyn;
+
+ // Checking validity of drives in Cenrep List
+ // drive letters are separated by semicolons
+ // Destination is FFS in default
+ TInt drive;
+ User::LeaveIfError(
+ DriveInfo::GetDefaultDrive( DriveInfo::EDefaultPhoneMemory, drive ) );
+
+ for( TInt i = 0; i < iDriveLettersCenRep.Length(); i = i + 2 )
+ {
+ if( iFs.CharToDrive( iDriveLettersCenRep[i], drive ) == KErrNone )
+ {
+ TUint status;
+ if ( DriveInfo::GetDriveStatus( iFs, drive, status ) == KErrNone )
+ {
+ if ( ( status & ( DriveInfo::EDriveUserVisible | DriveInfo::EDrivePresent ) ) )
+ {
+ CLOG(( ECodEng, 0, _L("-> CCodEngBase::QueryDynDriveListLC Drive is present and visible")));
+ }
+ }
+ }
+ }
+
+ // get the list of drives available in real time
+ if ( DriveInfo::GetUserVisibleDrives( iFs, driveList, driveCount ) == KErrNone )
+ {
+ if ( iDriveLettersCenRep.Length() > 0 )
+ {
+ driveLettersDyn.Append( iDriveLettersCenRep );
+ if ( driveLettersDyn[driveLettersDyn.Length() - 1] != ';' )
+ {
+ driveLettersDyn.Append( KDefaultDriveListSep );
+ }
+ }
+ TInt count( driveList.Length() );
+ for ( TInt i( 0 ); i < count; ++i )
+ {
+ if ( driveList[ i ] )
+ {
+ User::LeaveIfError( iFs.DriveToChar( i, driveLetter) );
+ TInt drivePos = driveLettersDyn.LocateF( driveLetter );
+ if ( drivePos == KErrNotFound )
+ {
+ driveLettersDyn.Append( driveLetter );
+ driveLettersDyn.Append( KDefaultDriveListSep );
+ }
+ }
+ }
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::QueryDynDriveListLC Pref. drive list dynamic: [%S]"), \
+ &driveLettersDyn));
+ }
+
+ HBufC8* driveLetters = HBufC8::NewLC( KMaxDriveListStrLen );
+ driveLetters->Des().Copy( driveLettersDyn );
+ return driveLetters;
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::QueryDriveList
+//------------------------------------------------------------------------
+void CCodEngBase::QueryDriveListL()
+ {
+ CRepository* repository = CRepository::NewLC( KCRUidBrowser );
+
+ if( repository->Get(KBrowserDrivePrefListForDownloadedContent, iDriveLettersCenRep) != KErrNone )
+ {
+ CLOG(( ECodEng, 0, _L("-> CCodEngBase::QueryDriveListL Drive list not found")));
+ iDriveLettersCenRep.Copy( KDefaultDriveList );
+ }
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::QueryDriveListL Pref. drive list: [%S]"), \
+ &iDriveLettersCenRep));
+
+ CleanupStack::PopAndDestroy( repository );
+ }
+
+#endif
+
+//------------------------------------------------------------------------
+//CCodEngBase::DownloadID
+//------------------------------------------------------------------------
+TUint32 CCodEngBase::DownloadID()
+ {
+ return iDownloadId;
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::SetPausable
+//------------------------------------------------------------------------
+
+void CCodEngBase::SetPausable(TBool aPausable)
+ {
+ (*iData)[iData->ActiveDownload()]->iPausable = aPausable;
+ if( iData->Count() > 1 && aPausable )
+ {
+ iObserver->UpdatePausable(aPausable);
+ }
+ else if(iData->Count() == 1)
+ {
+ iObserver->UpdatePausable(aPausable);
+ }
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::SetResumePDAvailable
+//------------------------------------------------------------------------
+
+void CCodEngBase::SetResumePDAvailable()
+ {
+ if(iData && iData->ActiveDownload()
+ && iData->Count()
+ && (*iData)[iData->ActiveDownload()]->ProgressiveDownload())
+ {
+ iObserver->DownloadResumedPdAvailable();
+ }
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::StoreFilePathsL
+//------------------------------------------------------------------------
+void CCodEngBase::StoreFilePathsL(TPtr8& aBuf)
+ {
+ HBufC* buf1 = (*iData)[iData->ActiveDownload()]->iTempPath.AllocLC();
+ AppendBufL(aBuf,buf1);
+
+ HBufC* buf2 = (*iData)[iData->ActiveDownload()]->iRootPath.AllocLC();
+ AppendBufL(aBuf,buf2);
+
+ CleanupStack::PopAndDestroy(2,buf1);
+ AppendBufL(aBuf,(*iData)[iData->ActiveDownload()]->iFullName);
+
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::LoadFilePathsL
+//------------------------------------------------------------------------
+void CCodEngBase::LoadFilePathsL(RFile& aInFile)
+ {
+ HBufC* buf1 = NULL;
+ HBufC* buf2 = NULL;
+ ReadHBufCL(aInFile,buf1);
+ (*iData)[iData->ActiveDownload()]->iTempPath = *buf1;
+
+ ReadHBufCL(aInFile,buf2);
+
+ (*iData)[iData->ActiveDownload()]->iRootPath = *buf2;
+
+ ReadHBufCL(aInFile,(*iData)[iData->ActiveDownload()]->iFullName);
+ delete buf1;
+ delete buf2;
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::Start()
+//------------------------------------------------------------------------
+//
+EXPORT_C void CCodEngBase::Start( const CAiwGenericParamList* aParams, TRequestStatus* aStatus )
+ {
+ iParentStatus = aStatus;
+ *iParentStatus = KRequestPending;
+ iParams = aParams;
+ // Get params from GenericParams.
+ if ( iParams )
+ {
+ CodUtil::GetUint32Param( iPreferredIap, EGenericParamAccessPoint, *iParams );
+ }
+
+ Continue( EStartConnect );
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::ChangeMediaObjectL()
+//------------------------------------------------------------------------
+//
+void CCodEngBase::ChangeMediaObjectL()
+ {
+ __ASSERT_DEBUG( iState == EMediaChange, CodPanic( ECodInternal ) );
+
+ TInt mediaObjectCount = iData->Count();
+ if( mediaObjectCount && iData->ActiveDownload() )
+ {
+ (*iData)[iData->ActiveDownload()]->iStatusCode = iStatusCode;
+ (*iData)[iData->ActiveDownload()]->iResult = iResult;
+ iObserver->Done( iStatusCode, iResult );
+
+ if( iStatusCode == KHttp900Success )
+ {
+ (*iData)[iData->ActiveDownload()]->iState = ESucceeded;
+ StoreSubInfoFileL(NULL, iData->ActiveDownload() );
+ }
+
+ UpdateTrackInfoL();
+
+ if( iData->ActiveDownload() != mediaObjectCount &&( (*iData)[iData->ActiveDownload()]->iResult != KErrCancel
+ && (*iData)[iData->ActiveDownload()]->iResult != KErrAbort
+ && (*iData)[iData->ActiveDownload()]->iResult != KErrCodWapConnectionDropped
+ && (*iData)[iData->ActiveDownload()]->iResult != KErrCodHttpDownloadPaused
+ && (*iData)[iData->ActiveDownload()]->iResult != KErrCodInvalidDescriptor))
+ {
+ if( iSaver )
+ {
+ iSaver->Cleanup( !(*iData)[iData->ActiveDownload()]->iPausable );
+ }
+ delete iSaver; // Cleans up unless Release()-d.
+ iSaver = NULL;
+ delete iLoader;
+ iLoader = NULL;
+ delete iConn;
+ iConn = NULL;
+ delete iCodBuf;
+ iCodBuf = NULL;
+
+ TInt count = iData->ActiveDownload();
+ do
+ {
+ count++;
+ }
+ while( count <= iData->Count() && !( (*iData)[count]->State() == EQueued
+ || (*iData)[count]->State() == EInProgress )
+ );
+
+ if( count <= iData->Count())
+ {
+ iData->SetActiveDownload(count);
+ Continue( EStartConnect );
+ return;
+ }
+ }
+ }
+ Continue ( EStartProductNotify );
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::Pausable
+//------------------------------------------------------------------------
+EXPORT_C TBool CCodEngBase::Pausable()
+ {
+ return (*iData)[iData->ActiveDownload()]->iPausable;
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StoreMainInfoFileL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StoreMainInfoFileL()
+ {
+ if ( iCodDlInfoPath == KNullDesC )
+ {
+ return;
+ }
+ TInt bufSz = KDownloadInfoIncrSize;
+ HBufC8* newInfo = HBufC8::NewLC( bufSz );
+ TPtr8 newInfoPtr = newInfo->Des();
+
+ // Append the DD attributes
+ iData->AppendStorageInfoL(newInfoPtr);
+
+ RFile outFile;
+ CleanupClosePushL<RFile>( outFile );
+
+ User::LeaveIfError( outFile.Replace( iFs,
+ iCodDlInfoPath,
+ EFileShareExclusive |
+ EFileStream |
+ EFileWrite ) );
+
+ outFile.Write( newInfoPtr );
+ User::LeaveIfError( outFile.Flush() );
+
+ CleanupStack::PopAndDestroy(2);
+
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StoreSubInfoFileL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StoreSubInfoFileL( const CArrayPtrFlat<CHeaderField>* aHeaders, TInt aMediaIndex )
+ {
+ if ( iCodDlInfoPath == KNullDesC )
+ {
+ return;
+ }
+ RFile outFile;
+ CleanupClosePushL<RFile>( outFile );
+
+
+ TInt bufSz = KDownloadInfoIncrSize;
+ HBufC8* newInfo = HBufC8::NewLC( bufSz );
+ TPtr8 newInfoPtr = newInfo->Des();
+
+ TFileName infoPath;
+ infoPath.Format( _L("%S_%d"), &iCodDlInfoPath, aMediaIndex );
+
+ newInfoPtr.Zero();
+
+ // Load the DD attributes and other required information to the buffer
+ (*iData)[aMediaIndex]->StoreMediaInfoL( newInfoPtr, aHeaders );
+
+ User::LeaveIfError( outFile.Replace( iFs,
+ infoPath,
+ EFileShareExclusive |
+ EFileStream |
+ EFileWrite ) );
+
+ outFile.Write( newInfoPtr );
+ User::LeaveIfError( outFile.Flush() );
+
+ CleanupStack::PopAndDestroy(2);
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StoreInfoFilesL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::StoreInfoFilesL()
+ {
+ StoreMainInfoFileL();
+
+ for(TInt i = 1; i <= iData->Count(); ++i)
+ {
+ StoreSubInfoFileL( NULL, i );
+ }
+ }
+// ---------------------------------------------------------
+// CCodEngBase::LoadMainInfoFileL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::LoadMainInfoFileL()
+ {
+
+ RFile inFile;
+ CleanupClosePushL<RFile>( inFile );
+ TInt err = inFile.Open(iFs,
+ CodDlInfoFile(),
+ EFileShareReadersOnly |
+ EFileRead ) ;
+
+ // Possible erros KErrNotFound , KErrPathNotFound , KErrBadName
+ if( err )
+ {
+ CleanupStack::PopAndDestroy();
+ return;
+ }
+
+ iData->LoadStorageInfoL( inFile );
+ CleanupStack::PopAndDestroy(); // inFile
+
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::LoadSubInfoFileL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::LoadSubInfoFileL( TInt aMediaIndex, CArrayPtrFlat<CHeaderField>* aHeaders )
+ {
+
+ RFile inFile;
+ CleanupClosePushL<RFile>( inFile );
+
+ TFileName infoPath;
+ infoPath.Format( _L("%S_%d"), &iCodDlInfoPath, aMediaIndex );
+
+
+ TInt err = inFile.Open(iFs,
+ infoPath,
+ EFileShareReadersOnly |
+ EFileRead ) ;
+
+ // Possible erros KErrNotFound , KErrPathNotFound , KErrBadName
+ if( err )
+ {
+ CleanupStack::PopAndDestroy();
+ return;
+ }
+
+ (*iData)[aMediaIndex]->LoadMediaInfoL( inFile, iFs, aHeaders );
+ CleanupStack::PopAndDestroy(); // inFile
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::LoadInfoFilesL()
+// ---------------------------------------------------------
+//
+void CCodEngBase::LoadInfoFilesL()
+ {
+ LoadMainInfoFileL();
+
+ TBool activeDownloadSet = EFalse;
+
+ for(TInt i = 1; i <= iData->Count(); ++i)
+ {
+ LoadSubInfoFileL( i, NULL );
+ if( ((*iData)[i]->State() == EInProgress || (*iData)[i]->State() == EQueued ) && !activeDownloadSet )
+ {
+ iData->SetActiveDownload ( i );
+ activeDownloadSet = ETrue;
+ }
+ }
+ if( iData->ActiveDownload() == 0 )
+ {
+ iData->SetActiveDownload(iData->Count());
+ }
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::StartProductNotifyL
+// ---------------------------------------------------------
+//
+void CCodEngBase::StartProductNotifyL()
+ {
+
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::StartProductNotifyL iStatus(%d)"), \
+ iStatus.Int() ));
+ __ASSERT_DEBUG( iState == EStartProductNotify, CodPanic( ECodInternal ) );
+ if ( iData->InstallNotify().Length() )
+ {
+ CLOG(( ECodEng, 4, _L("CCodEngBase::StartProductNotifyL: init request") ));
+ if ( !iProgress )
+ {
+ // Setup notify-only progress.
+ iProgress = new (ELeave) TCodProgress( iObserver );
+ iProgress->Setup( 0, KCodNotifyTraffic );
+ }
+ iProgress->StartPhaseL( TCodProgress::ENotify );
+ TBool notifyObserver = EFalse;
+ // When notifying after fetch, we already have a loader (and the
+ // observer has already been notified about load).
+ // When notifying without fetch, we don't have a loader yet (and the
+ // observer has not been notified about load yet).
+ if ( !iConn )
+ {
+ iConn = CConnection::NewL();
+ }
+ // For notify, attach only (do no create new connection).
+ iConn->AttachL( iPreferredIap );
+ if( !iLoader )
+ {
+ iLoader = CHttpLoader::NewL( *iConn, NULL, iProgress ,this );
+ notifyObserver = ETrue;
+ }
+ TInt statusCode;
+
+ if(!iData->Count())
+ {
+ statusCode = KHttp906InvalidDescriptor;
+ }
+ else
+ {
+ statusCode = KHttp981DownloadCompletion;
+ }
+
+ for( TInt i = 1;i <= iData->Count(); ++i )
+ {
+ if( (*iData)[i]->iStatusCode != KHttp900Success )
+ {
+ statusCode = KHttp970MixedStatus;
+ break;
+ }
+ }
+ HBufC8* url = CodUtil::AbsoluteUrlLC
+ ( iData->SourceUri(), iData->InstallNotify() );
+ iLoader->NotifyL( *url, StatusText( statusCode ), &iStatus );
+ CleanupStack::PopAndDestroy( url );
+ iState = EProductNotify;
+ SetActive();
+ if ( iObserver && notifyObserver )
+ {
+ if ( iStatusCode == KHttp902UserCancelled ||
+ iStatusCode == KHttp921UserAborted )
+ {
+ CLOG(( ECodEng, 3, \
+ _L("-> CCodEngBase::StartNotifyL notify StartCancelL") ));
+ iObserver->StartCancelL();
+ iNotificationStatus = ECancel;
+ }
+ else
+ {
+ CLOG(( ECodEng, 3, \
+ _L("-> CCodEngBase::StartNotifyL notify StartLoadL(%d)"), \
+ iStatusCode ));
+ iObserver->StartLoadL( iStatusCode );
+ iNotificationStatus = ELoad;
+ }
+ }
+ }
+ else
+ {
+ // No install notify attribute, regarded as successful notification.
+ CLOG(( ECodEng, 4, _L("CCodEngBase::StartNotifyL: nothing to do") ));
+ Continue( EProductNotify );
+ }
+ CLOG(( ECodEng, 2, _L("<- CCodEngBase::StartNotifyL") ));
+ }
+
+// ---------------------------------------------------------
+// CCodEngBase::EndProductNotifyL
+// ---------------------------------------------------------
+void CCodEngBase::EndProductNotifyL()
+ {
+ CLOG(( ECodEng, 2, _L("-> CCodEngBase::EndNotifyL iStatus(%d)"), \
+ iStatus.Int() ));
+ __ASSERT_DEBUG( iState == EProductNotify, CodPanic( ECodInternal ) );
+
+ delete iLoader;
+ iLoader = NULL;
+ delete iConn;
+ iConn = NULL;
+
+ User::LeaveIfError( iStatus.Int() ); // Handle errors in RunError().
+
+ // Do not leave after this point! Notify was successful, we must keep
+ // downloaded content now.
+
+ if ( iProgress )
+ {
+ TRAP_IGNORE( iProgress->DoneL() );
+ delete iProgress;
+ iProgress = NULL;
+ }
+ /*
+ if( iSaver && (*iData)[iData->ActiveDownload()]->iResult == KErrNone )
+ {
+//TODO: check if in case of PD we should release. It is already done.
+ iSaver->ReleaseContent( (*iData)[iData->ActiveDownload()]->iFileName, iHandler );
+ iType = iSaver->DataType();
+ }
+ */
+ Done();
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::UpdatedDownloadDataL
+//------------------------------------------------------------------------
+EXPORT_C HBufC8* CCodEngBase::UpdatedDownloadDataL()
+ {
+ if (!iData)
+ return NULL;
+
+ CDownloadDataClient* dlData = CDownloadDataClient::NewLC();
+ ConvertCodDataToDownloadDataL( dlData );
+ HBufC8* des8 = dlData->MarshalDataL();
+ CleanupStack::PopAndDestroy(dlData);
+
+ return des8;
+ }
+// ---------------------------------------------------------
+// CCodEngBase::UpdateDownloadedSize
+// ---------------------------------------------------------
+void CCodEngBase::UpdateDownloadedSize( TInt aSize )
+ {
+ (*iData)[iData->ActiveDownload()]->SetDownloadedSize( (*iData)[iData->ActiveDownload()]->DownloadedSize() + aSize );
+ }
+// ---------------------------------------------------------
+// CCodEngBase::ActiveDownload
+// ---------------------------------------------------------
+EXPORT_C TInt CCodEngBase::ActiveDownload()
+ {
+ return iData->ActiveDownload();
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::UpdatedTrackDataL
+//------------------------------------------------------------------------
+EXPORT_C HBufC8* CCodEngBase::UpdatedTrackDataL(TInt& aValue)
+ {
+ if (!iData)
+ return NULL;
+
+ aValue = iData->ActiveDownload();
+
+ CMediaDataClient* mediaData = CMediaDataClient::NewL();
+ CleanupStack::PushL(mediaData);
+ ConvertMOToMediaDataL(mediaData, aValue);
+ HBufC8* des8 = mediaData->MarshalDataL();
+ CleanupStack::PopAndDestroy(); //mediaData
+
+ return des8;
+ }
+//------------------------------------------------------------------------
+//CCodEngBase::ConvertCODDataToDownloadDataL
+//------------------------------------------------------------------------
+void CCodEngBase::ConvertCodDataToDownloadDataL( CDownloadDataClient*& aDlData )
+ {
+ if (aDlData)
+ {
+ aDlData->SetNameL( iData->Name() );
+ aDlData->SetSize( iData->Size() );
+ aDlData->SetIconL( iData->Icon() );
+ aDlData->SetUpdatedDDURI( iData->UpdatedDDUriL() );
+
+ for (TInt mObj = 1; mObj <= iData->Count(); ++mObj)
+ {
+ CMediaDataClient* mediaData = CMediaDataClient::NewL();
+ CleanupStack::PushL(mediaData);
+
+ ConvertMOToMediaDataL(mediaData, mObj);
+ aDlData->AppendMediaData(mediaData);
+
+ CleanupStack::Pop(); //mediaData
+ }
+ }
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::ConvertMOToMediaDataL
+//------------------------------------------------------------------------
+void CCodEngBase::ConvertMOToMediaDataL( CMediaDataClient*& aMOData, TInt aMOIndex )
+ {
+ CMediaObjectData* objMedia = (*iData)[aMOIndex];
+
+ aMOData->SetNameL( objMedia->Name() );
+ aMOData->SetUrlL( objMedia->Url() );
+ aMOData->SetSize( objMedia->Size() );
+ aMOData->SetIconL( objMedia->Icon() );
+ aMOData->SetSourceUriL( objMedia->SourceUri() );
+ aMOData->SetProgressiveDownload( objMedia->ProgressiveDownload() );
+ aMOData->SetState( objMedia->State() );
+ aMOData->SetResult( objMedia->iResult );
+ aMOData->SetDownloadedSize( objMedia->DownloadedSize() );
+ aMOData->SetPausable( objMedia->Pausable() );
+ if(objMedia->iFullName)
+ {
+ aMOData->SetDestFilenameL( objMedia->FullName() );
+ aMOData->SetTempFilenameL( objMedia->FullName() );
+ }
+
+ for (TInt type = 0; type < objMedia->TypesCount(); ++type)
+ aMOData->AddTypeL( objMedia->Types().MdcaPoint(type) );
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::UpdateMediaInfoL
+//------------------------------------------------------------------------
+void CCodEngBase::UpdateMediaInfoL()
+ {
+ if (iObserver)
+ {
+ iObserver->UpdateMediaInfoL();
+ }
+ }
+// ---------------------------------------------------------
+// CCodEngBase::GetProductStatusCode
+// ---------------------------------------------------------
+EXPORT_C TCodDownloadProgress::TState CCodEngBase::GetProductStatusCode() const
+ {
+ TCodDownloadProgress::TState statusCode = TCodDownloadProgress::EFailedPermanent;
+ TInt allSucceeded = 0;
+ TInt currentActiveDownload = iData->ActiveDownload();
+
+ for( TInt i = 1 ; i <= iData->Count() ; ++i )
+ {
+ TInt mediaObjectStatusCode = (*iData)[i]->iStatusCode;
+
+ // If the current track failed for some reason, set this as the
+ // active download. Do this only for the first failed track.
+ if ((mediaObjectStatusCode != KHttp900Success) &&
+ (mediaObjectStatusCode != KHttp956LicenseSuccess))
+ {
+ if( currentActiveDownload > i )
+ {
+ //This is done so that next time when resume happens
+ //it happens from first failed download
+ iData->SetActiveDownload ( i );
+ currentActiveDownload = i;
+
+ //Inform server about the Active download
+ iObserver->SetActiveDownload();
+ iObserver->MediaObjectNameChanged();
+ }
+ }
+
+ // Check for error and status code
+ switch( mediaObjectStatusCode )
+ {
+ case KHttp900Success:
+ case KHttp956LicenseSuccess:
+ {
+ allSucceeded++;
+ statusCode = TCodDownloadProgress::ESucceeded;
+ break;
+ }
+
+ case KHttp901InsufficientMemory:
+ {
+ statusCode = TCodDownloadProgress::EFailedTemporary;
+ break;
+ }
+ case KHttp902UserCancelled:
+ case KHttp921UserAborted:
+ case KHttp957LicenseFailed:
+ {
+ break;
+ }
+
+ case KHttp905AttributeMismatch:
+ case KHttp906InvalidDescriptor:
+ case KHttp907InvalidType:
+ case KHttp922DeviceAborted:
+ case KHttp923NonAcceptableContent:
+ case KHttp924LoaderError:
+ case KHttp951InvalidDdVersion:
+ case KHttp952DeviceAborted:
+ case KHttp953NonAcceptableContent:
+ case KHttp909RequestedRangeNotSatisfiable:
+ {
+ // Permanent errors: retry is useless.
+ if( (*iData)[i]->iPausable )
+ {
+ //for pausable permanent errors
+ //Are actually Temporary errors
+ return TCodDownloadProgress::EFailedTemporary;
+ }
+ break;
+ }
+ case KHttp954LoaderError:
+ case KHttp903LossOfService:
+ case KHttp910NoMemory:
+ {
+ if( (*iData)[i]->iPausable )
+ {
+ return TCodDownloadProgress::EPaused;
+ }
+ break;
+ }
+
+
+ case KHttp955PreconditionFailed:
+ {
+ return TCodDownloadProgress::EInit;
+ }
+
+ default:
+ {
+ // Unexpected status.
+ //__ASSERT_DEBUG( EFalse, CodUiPanic( ECodUiInternal ) );
+ statusCode = TCodDownloadProgress::EFailedPermanent;
+ break;
+ }
+
+ }
+ }
+
+ if( iData->Count() && allSucceeded == iData->Count())
+ {
+ return TCodDownloadProgress::ESucceeded;
+ }
+ if( statusCode == TCodDownloadProgress::EFailedPermanent && !allSucceeded)
+ {
+ return statusCode;
+ }
+
+ return TCodDownloadProgress::EFailedTemporary;
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::UpdateTrackInfoL
+//------------------------------------------------------------------------
+void CCodEngBase::UpdateTrackInfoL()
+ {
+ if (iObserver)
+ {
+ iObserver->UpdateTrackInfoL();
+ }
+ }
+
+//------------------------------------------------------------------------
+//CCodEngBase::SetUrlL
+//------------------------------------------------------------------------
+void CCodEngBase::SetUrlL(const TDesC& aUrl)
+ {
+ TInt currentActiveDownload = iData->ActiveDownload();
+ (*iData)[currentActiveDownload]->SetUrlL( aUrl );
+ }
+
+
+//------------------------------------------------------------------------
+//CCodEngBase::ContentTypeChanged
+//------------------------------------------------------------------------
+void CCodEngBase::ContentTypeChanged()
+ {
+ if (iObserver)
+ {
+ iObserver->ContentTypeChanged();
+ }
+ }