internetradio2.0/dataprovidersrc/irdataprovider.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 19 Apr 2010 14:01:53 +0300
changeset 0 09774dfdd46b
child 12 608f67c22514
permissions -rw-r--r--
Revision: 201011 Kit: 201015

/*
* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "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:  ?Description
*
*/


#include "irdataprovider.h"
#include "irdataproviderobserver.h"
#include "irdebug.h"
#include "irhttpdataprovider.h"
#include "irhttprequestdata.h"
#include "irsettings.h"

// ---------------------------------------------------------------------------
//  CIRDataProvider::NewL(MIRDataProviderObserver& aObserver)
//  Creates instance of CIRDataProvider.
// ---------------------------------------------------------------------------
//
EXPORT_C CIRDataProvider *CIRDataProvider::NewL(
    MIRDataProviderObserver &aObserver )
    {
    IRLOG_DEBUG( "CIRDataProvider::NewL - Entering" );
    CIRDataProvider *self = NewLC( aObserver );
    CleanupStack::Pop(self);
    IRLOG_DEBUG( "CIRDataProvider::NewL - Exiting" );
    return self;
    }

// ---------------------------------------------------------------------------
//  CIRDataProvider::NewL(MIRDataProviderObserver& aObserver)
//  Creates instance of CIRDataProvider.
// ---------------------------------------------------------------------------
//
EXPORT_C CIRDataProvider *CIRDataProvider::NewL(
    MIRDataProviderObserver &aObserver, const TDesC &aFileName )
    {
    IRLOG_DEBUG( "CIRDataProvider::NewL(..., &aFileName) - Entering" );
    CIRDataProvider *self = NewLC( aObserver, aFileName );
    CleanupStack::Pop(self);
    IRLOG_DEBUG( "CIRDataProvider::NewL(..., &aFileName) - Exiting." );
    return self;
    }

// ---------------------------------------------------------------------------
//  CIRDataProvider::~CIRDataProvider()
//  Destructs an instance of CIRDataProvider.
// ---------------------------------------------------------------------------
//
CIRDataProvider::~CIRDataProvider() // destruct - virtual, so no export
    {
    IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Entering" );

    if (iHttpDataProvider)
        {
        // Cancel any active transactions
        iHttpDataProvider->CancelTransaction();
        // Destroy the data provider object
        }

    delete iHttpDataProvider;

    if( iIRSettings )
    	{
    	iIRSettings->Close();
		}

    if (iDataProviderTimer)
        {
     	iDataProviderTimer->Cancel(); // Cancel the timer
        }

    delete iDataProviderTimer; // Destroy the timer object
	if( iResponseHeaders )
		{
        delete iResponseHeaders;
		}
    iFile.Close();
    iFsSession.Close(); // Close the file server session
    IRLOG_DEBUG( "CIRDataProvider::~CIRDataProvider() - Exiting" );
    }

// General functions exported ( These are the API`s exposed )( HTTP )

// ---------------------------------------------------------------------------
//  CIRDataProvider::IRHttpIssueRequest(TDesC8& aUri)
//  Used to issue an Http request
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRDataProvider::IRHttpIssueRequestL(
     CIRHttpRequestData &aRequestObject )
    {
    IRHttpCancelRequest();
    IRLOG_DEBUG( "CIRDataProvider::IRHttpIssueRequestL - Entering" );
	IRRDEBUG2("CIRDATAPROVIDER::IRHTTPISSUEREQUESTL",KNullDesC);
    CIRHttpResponseData* newResponseHeaders = new ( ELeave ) CIRHttpResponseData;
    delete iResponseHeaders;
    iResponseHeaders = newResponseHeaders;


    // Create or replace the file used to store xml response from iSDS
    User::LeaveIfError(iFile.Replace( iFsSession, iXmlFilePath, EFileWrite ));
    iHttpDataProvider->CancelTransaction();

    TInt err = iHttpDataProvider->IssueHttpRequestL( aRequestObject );
    // Cancel the timer if active
    iDataProviderTimer->Cancel();
    // Start the timer for timeout
    iDataProviderTimer->After( iTimeOut );
    if ( err == KErrCouldNotConnect )
        {
        // If error in IssueHttpRequest then close the open file
	    iFile.Close();
	    iDataProviderTimer->Cancel();
	    iDataProviderObserver.IRHttpGeneralError( err );
	    // Cancel any possibly pending transactions
	    iHttpDataProvider->CancelTransaction();
        }

    IRLOG_DEBUG( "CIRDataProvider::IRHttpIssueRequestL - Exiting." );
    }


// ---------------------------------------------------------------------------
//  CIRDataProvider::IRHttpCancelRequest()
//  Used to cancel a request
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRDataProvider::IRHttpCancelRequest()
    {
    IRLOG_DEBUG( "CIRDataProvider::IRHttpCancelRequest - Entering" );
    // Cancel the timer if active
    iDataProviderTimer->Cancel();
    // Cancel any possibly pending transactions
    iHttpDataProvider->CancelTransaction();
    // Close the file handle used to store the xml response
    iFile.Close();
    IRLOG_DEBUG( "CIRDataProvider::IRHttpCancelRequest - Exiting." );
    }


// ---------------------------------------------------------------------------
//  CIRDataProvider::ReleaseResources()
//  Used to release the resources held by the IRHttpDataProvider
// ---------------------------------------------------------------------------
//
EXPORT_C void CIRDataProvider::ReleaseResources()
	{
	IRLOG_DEBUG( "CIRDataProvider::ReleaseResources - Entering" );
	// Release the resources held by the IRHttpDataProvider
	iHttpDataProvider->ReleaseResources();
	IRLOG_DEBUG( "CIRDataProvider::ReleaseResources - Exiting" );
	}


//These are the callback functions used by CIRHttpDataProvider to
//provide the CIRDataProvider with the data after processing the
//HTTP request.

// ---------------------------------------------------------------------------
//  CIRDataProvider::HttpEventComplete()
//  Used to Indicate to the observer that the request event has completed
// ---------------------------------------------------------------------------
//
void CIRDataProvider::HttpEventComplete()
    {
    IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Entering" );
    iFile.Close();
    iDataProviderTimer->Cancel();

    // Need to take a member to a local variable, as the IRHttpDataReceived may initiate
    // an IRHttpIssueRequestL() call, causing the headers to be replaced with empty ones, and
    // causing crashes.
    CIRHttpResponseData* currentHeaders = iResponseHeaders;
    iResponseHeaders = NULL; // prevents the destructor to delete in case something streange happens.
    iDataProviderObserver.IRHttpDataReceived( iXmlFilePath,*currentHeaders );

    delete currentHeaders;
    IRLOG_DEBUG( "CIRDataProvider::HttpEventComplete - Exiting." );
    }


void CIRDataProvider::ExtractHeaderValue(const TDesC8& aHeaderData,const
	TDesC8& aHeaderName,const TDesC8& aDelimeter,TDes8& aHolder) const
	{
	IRLOG_DEBUG( "CIRDataProvider::ExtractHeaderValue - Entering" );
	TInt position = aHeaderData.Find(aHeaderName);
	if( position >= 0)
		{
		TPtrC8 headerValue = aHeaderData.Mid(position);
		TInt delimeterPosition = headerValue.Find(aDelimeter);
		if( delimeterPosition != KErrNotFound )
			{
			delimeterPosition++;
			TPtrC8 value = headerValue.Mid(delimeterPosition);
			aHolder.Copy(value);
			aHolder.TrimAll();
			}
		}
	IRLOG_DEBUG( "CIRDataProvider::ExtractHeaderValue - Exiting." );
	}


// ---------------------------------------------------------------------------
//  CIRDataProvider::HttpHeaderReceived( const TDesC8& aHeaderData )
//  Used by CIRHttpDataProvider to indicate that an HTTP header is received.
// ---------------------------------------------------------------------------
//
void CIRDataProvider::HttpHeaderReceived( const TDesC8& aHeaderData )
    {
    IRLOG_DEBUG( "CIRDataProvider::HttpHeaderReceived - Entering." );
	_LIT8(KDelim,":");
	_LIT8(KContentType,"Content-Type");
	ExtractHeaderValue(aHeaderData,KContentType,KDelim,iResponseHeaders->
		iContentType);
	_LIT8(KMaxAge,"max-age");
	_LIT8(KDelimEqual,"=");
	ExtractHeaderValue(aHeaderData,KMaxAge,KDelimEqual,iResponseHeaders->
		iMaxAge);
	_LIT8(KContentLength,"Content-Length");
	ExtractHeaderValue(aHeaderData,KContentLength,KDelim,iResponseHeaders->
		iContentLength);
	_LIT8(KExpires,"Expires");
	ExtractHeaderValue(aHeaderData,KExpires,KDelim,iResponseHeaders->iExpires);
	IRLOG_DEBUG( "CIRDataProvider::HttpHeaderReceived - Exiting." );
    }


void CIRDataProvider::HttpDateHeaderReceived(const TDesC8 &aHeader,
	const TTime& aTime )
	{
	IRLOG_DEBUG( "CIRDataProvider::HttpDateHeaderReceived - Entering." );
	_LIT8(KDate,"Date");
	_LIT8(KLastModified,"Last-Modified");
	TInt position = aHeader.Find(KDate);
	if( position != KErrNotFound )
		{
		iResponseHeaders->iDate = aTime;
		//find the difference between device time and response time
		//and storing the offset
		SetOffsetSeconds( aTime );
		return ;
		}
	position = aHeader.Find(KLastModified);
	if( position != KErrNotFound )
		{
		iResponseHeaders->iLastModified = aTime;
		}
	IRLOG_DEBUG( "CIRDataProvider::HttpDateHeaderReceived - Exiting." );
	}



// ---------------------------------------------------------------------------
//  CIRDataProvider::HttpBodyReceived( const TDesC8& aBodyData )
//  Used by CIRHttpDataProvider to indicate that an HTTP response body
//  is received.
// ---------------------------------------------------------------------------
//
void CIRDataProvider::HttpBodyReceived( const TDesC8 &aBodyData )
    {
    IRLOG_DEBUG( "CIRDataProvider::HttpBodyReceived - Entering" );
    TInt FileWritePos = 0;
    iFile.Seek( ESeekEnd, FileWritePos );
    iFile.Write( FileWritePos, aBodyData );
    IRLOG_DEBUG( "CIRDataProvider::HttpBodyReceived - Exiting." );
    }

// ---------------------------------------------------------------------------
//  CIRDataProvider::HttpTransactionError(TInt aErrCode)
//  Used by CIRHttpDataProvider to indicate that a HTTP Transaction error
//  has occured.
// ---------------------------------------------------------------------------
//
void CIRDataProvider::HttpTransactionError( TInt aErrCode )
    {
    IRLOG_DEBUG( "CIRDataProvider::HttpTransactionError - Entering" );
    iFile.Close();
    iDataProviderTimer->Cancel();
    iDataProviderObserver.IRHttpGeneralError( aErrCode );
    // Cancel any possibly pending transactions
    iHttpDataProvider->CancelTransaction();
    IRLOG_DEBUG( "CIRDataProvider::HttpTransactionError - Exiting." );
    }

// ---------------------------------------------------------------------------
//  CIRDataProvider::HttpResponseCodeRecieved(TInt aResponseCode)
//  Used by CIRHttpDataProvider to indicate to the iSDS Client that a
//  304 Not Changed response received
//  Note: Implemented in version 0.2
// ---------------------------------------------------------------------------
//
void CIRDataProvider::HttpResponseCodeRecieved( TInt aResponseCode )
    {
    IRLOG_DEBUG( "CIRDataProvider::HttpResponseCodeRecieved - Entering" );
    iDataProviderObserver.IRHttpResponseCodeReceived( aResponseCode, *iResponseHeaders );
    IRLOG_DEBUG( "CIRDataProvider::HttpResponseCodeRecieved- Exiting" );
    }

// constructor support
// don't export these, because used only by functions in this DLL
// ---------------------------------------------------------------------------
//  CIRDataProvider::CIRDataProvider(MIRDataProviderObserver& aObserver):
//  iDataProviderObserver(aObserver)
//  Default Constructor
// ---------------------------------------------------------------------------
//
void CIRDataProvider::TimerExpired()
    {
    IRLOG_INFO( "CIRDataProvider::TimerExpired - Entering" );
    IRHttpCancelRequest();
    HttpTransactionError( KDataProviderTimeout );
    IRLOG_INFO( "CIRDataProvider::TimerExpired - Exiting" );
    }



CIRDataProvider::CIRDataProvider( MIRDataProviderObserver &aObserver ):
    iDataProviderObserver( aObserver ) // first-phase C++ constructor
    {
    IRLOG_INFO( "CIRDataProvider::CIRDataProvider" );
    // Definition not required
    }

// ---------------------------------------------------------------------------
//  void CIRDataProvider::ConstructL()
//  2nd Phase construction
// ---------------------------------------------------------------------------
//
void CIRDataProvider::ConstructL() // second-phase constructor
    {
    IRLOG_DEBUG( "CIRDataProvider::ConstructL - Entering" );
    _LIT( KXmlFile, "iSdsResponse.xml" );
    ConstructL(KXmlFile);
    iHttpDataProvider->iSetNonUAProfUserAgent = EFalse;
    IRLOG_DEBUG( "CIRDataProvider::ConstructL - Exiting" );
    }

// ---------------------------------------------------------------------------
//  void CIRDataProvider::ConstructL(TDesC& aFilePath)
//  2nd Phase construction
// ---------------------------------------------------------------------------
//
void CIRDataProvider::ConstructL( const TDesC &aFileName )
    {
    IRLOG_DEBUG( "CIRDataProvider::ConstructL(const TDesC &aFileName) - Entering" );
    iHttpDataProvider = CIRHttpDataProvider::NewL( *this );
    iDataProviderTimer = CIRDataProviderTimer::NewL( EPriorityHigh,  *this );
    User::LeaveIfError(iFsSession.Connect());
    iIRSettings = CIRSettings::OpenL();
    iXmlFilePath = iIRSettings->PrivatePath();
    iXmlFilePath.Append( aFileName );
    iTimeOut = iIRSettings->GetTimeOut();
    iHttpDataProvider->iSetNonUAProfUserAgent = ETrue;
    IRLOG_DEBUG( "CIRDataProvider::ConstructL(const TDesC &aFileName) - Exiting." );
    }



// ---------------------------------------------------------------------------
//  CIRDataProvider::NewLC(MIRDataProviderObserver& aObserver)
//  Creates instance of CIRDataProvider.
// ---------------------------------------------------------------------------
//
CIRDataProvider *CIRDataProvider::NewLC( MIRDataProviderObserver &aObserver )
    {
    IRLOG_DEBUG( "CIRDataProvider::NewLC - Entering." );
    CIRDataProvider *self = new( ELeave )CIRDataProvider( aObserver );
    CleanupStack::PushL( self );
    self->ConstructL();
    IRLOG_DEBUG( "CIRDataProvider::NewLC - Exiting." );
    return self;
    }

// ---------------------------------------------------------------------------
//  CIRDataProvider::NewLC(MIRDataProviderObserver& aObserver)
//  Creates instance of CIRDataProvider.
// ---------------------------------------------------------------------------
//
CIRDataProvider *CIRDataProvider::NewLC( MIRDataProviderObserver &aObserver,
    const TDesC &aFileName )
    {
    IRLOG_DEBUG( "CIRDataProvider::NewLC - Entering." );
    CIRDataProvider *self = new( ELeave )CIRDataProvider( aObserver );
    CleanupStack::PushL( self );
    self->ConstructL( aFileName );
    IRLOG_DEBUG( "CIRDataProvider::NewLC - Exiting." );
    return self;
    }

EXPORT_C CIRHttpDataProvider* CIRDataProvider::GetHttpDataProvider()
{
IRLOG_DEBUG( "CIRDataProvider::GetHttpDataProvider" );
	return iHttpDataProvider;
}

// ---------------------------------------------------------------------------
//  CIRDataProvider::SetOffsetSeconds( const TTime& aTime )
//  Stores the offset between device time and response header in settings
// ---------------------------------------------------------------------------
//
void CIRDataProvider::SetOffsetSeconds( const TTime& aTime )
	{
	IRLOG_DEBUG( "CIRDataProvider::SetOffsetSeconds - Entering" );
	TTime currenttime;
	//calculates the current time
	currenttime.UniversalTime();
	//finds offset from isds response
	TTimeIntervalSeconds offsetseconds;
	//Find offset from isds response
	TInt err = currenttime.SecondsFrom(aTime,offsetseconds);
	if( err )
		{
		//if error offsetseconds is set to zero
		offsetseconds = 0;
		}
	//storing the offset value in setting
	TRAP_IGNORE( iIRSettings->SetTimeCorrectionL(offsetseconds.Int()) )
	IRLOG_DEBUG( "CIRDataProvider::SetOffsetSeconds - Exiting." );
	}