/*
* 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 CPushMtmFetchOperation.
*
*/
// INCLUDE FILES
#include "PushMtmFetchOperation.h"
#include "PushContentHandlerPanic.h"
#include "PushMtmLog.h"
#include <CSLPushMsgEntry.h>
#include <Uri8.h>
#include <SysUtil.h>
#include <CookieFilterInterface.h>
#include <uaproffilter_interface.h>
#include <CommDbConnPref.h>
#include <cdbcols.h>
#include <BrowserUiSDKCRKeys.h>
#include "PushMtmPrivateCRKeys.h"
#include <centralrepository.h>
#include <commdb.h>
#include <ApDataHandler.h>
#include <ApAccessPointItem.h>
#include <ApUtils.h>
#include <ApSelect.h>
#include <HttpFilterAcceptHeaderInterface.h>
#include <HttpFilterIopInterface.h>
#include <HttpFilterCommonStringsExt.h>
#include <DeflateFilterInterface.h>
#include <FeatMgr.h>
// ================= MACROS =======================
#ifdef _DEBUG
/// Guard "debug-only" argument name with this (expands to argument).
#define DEBUG_ONLY( argName ) argName
#else /* not defined _DEBUG */
/// Guard "debug-only" argument name with this (expands to nothing).
#define DEBUG_ONLY( argName )
#endif /* def _DEBUG */
// ================= LOCAL CONSTANTS =======================
_LIT8( KHttpProtString, "HTTP/TCP" );
_LIT8( KUserAgent, "Push MTM" );
/// Base HTTP error code. See Extended Error Handling UI Specification!
LOCAL_C const TInt KPushMtmHttpErrorBase = -25000;
// ================= MEMBER FUNCTIONS =======================
// ---------------------------------------------------------
// CPushMtmFetchOperation::NewL
// ---------------------------------------------------------
//
CPushMtmFetchOperation* CPushMtmFetchOperation::NewL
(
const TDesC& aRequestedUrl,
TRequestStatus& aObserverRequestStatus
)
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::NewL")
CPushMtmFetchOperation* op =
new (ELeave) CPushMtmFetchOperation( aObserverRequestStatus );
CleanupStack::PushL( op );
op->ConstructL( aRequestedUrl );
CleanupStack::Pop( op ); // op
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::NewL")
return op;
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::~CPushMtmFetchOperation
// ---------------------------------------------------------
//
CPushMtmFetchOperation::~CPushMtmFetchOperation()
{
Cancel();
delete ( iCacheMgr );
delete iCacheSupply;
iHttpTrans.Close();
iHttpSess.Close();
iConn.Close();
iSockServ.Close();
delete iRequestedUrl;
delete iSourceUri;
delete iBody;
FeatureManager::UnInitializeLib();
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::StartL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::StartL()
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::StartL")
Cancel();
iResult = KErrNone;
iState = EInit;
SetActive();
TRequestStatus* status = &iStatus;
User::RequestComplete( status, KErrNone );
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::StartL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::CPushMtmFetchOperation
// ---------------------------------------------------------
//
CPushMtmFetchOperation::CPushMtmFetchOperation
( TRequestStatus& aObserverRequestStatus )
: CActive( EPriorityStandard ),
iObserver( aObserverRequestStatus ),
iState( EInit ),
iResult( KErrNone )
{
CActiveScheduler::Add( this );
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::ConstructL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::ConstructL( const TDesC& aRequestedUrl )
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::ConstructL")
iRequestedUrl = HBufC8::NewMaxL( aRequestedUrl.Length() );
iRequestedUrl->Des().Copy( aRequestedUrl );
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::ConstructL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::GetDefaultInetAccessPointL
// ---------------------------------------------------------
//
TBool CPushMtmFetchOperation::GetDefaultInetAccessPointL
( TUint32& aIapId ) const
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::GetDefaultInetAccessPointL")
// Try to find the default AP.
// The Browser may stores the default AP in the shared data.
CRepository* repository = CRepository::NewL( KCRUidBrowser );
CleanupStack::PushL( repository );
TInt wapApId;
User::LeaveIfError
( repository->Get( KBrowserDefaultAccessPoint, wapApId ) );
TUint32 wapApId32( wapApId );
TUint32 iapId32( 0 );
CleanupStack::PopAndDestroy( repository );
repository = 0;
CCommsDatabase* commsDb = CCommsDatabase::NewL( EDatabaseTypeIAP );
CleanupStack::PushL( commsDb );
CApDataHandler* apDataHandler = CApDataHandler::NewLC( *commsDb );
CApAccessPointItem* apItem = CApAccessPointItem::NewLC();
TRAPD( err, apDataHandler->AccessPointDataL( wapApId32, *apItem ) );
CApUtils* apUtils = CApUtils::NewLC( *commsDb );
TBool wapApFound( EFalse );
TBool iapFound( EFalse );
PUSHLOG_WRITE_FORMAT(" err: <%d>",err)
if ( err == KErrNone )
{
wapApFound = ETrue;
}
else // err != KErrNone
{
// The first valid access point has to be selected if exists
CApSelect* apSelect = CApSelect::NewLC
(
*commsDb,
KEApIspTypeAll,
EApBearerTypeAll,
KEApSortNameAscending
);
if ( apSelect->MoveToFirst() )
{
wapApFound = ETrue;
wapApId32 = apSelect->Uid();
}
CleanupStack::PopAndDestroy( apSelect ); // apSelect
}
if ( wapApFound )
{
// Get the IAP ID from the WAP AP ID.
#ifndef __SERIES60_WSP
iapId32 = 0;
TRAPD( errTransl, iapId32 = apUtils->IapIdFromWapIdL( wapApId32 ) );
PUSHLOG_WRITE_FORMAT(" IapIdFromWapIdL errTransl: <%d>",errTransl)
if ( errTransl == KErrNone )
{
iapFound = ETrue;
}
#else
iapId32 = wapApId32;
iapFound = ETrue;
#endif // __SERIES60_WSP
}
CleanupStack::PopAndDestroy( 4 ); // apUtils, apItem,
// apDataHandler, commsDb
if ( iapFound )
{
aIapId = iapId32;
}
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::GetDefaultInetAccessPointL")
return iapFound;
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::InitializeL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::InitializeL()
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::InitializeL")
User::LeaveIfError( iSockServ.Connect() );
PUSHLOG_WRITE("CPushMtmFetchOperation iSockServ.Connect() OK")
User::LeaveIfError( iConn.Open( iSockServ ) );
PUSHLOG_WRITE("CPushMtmFetchOperation iConn.Open() OK")
// Open the HTTP session.
iHttpSess.OpenL( KHttpProtString );
PUSHLOG_WRITE("CPushMtmFetchOperation iHttpSess.OpenL OK")
// Set our Socket Server handle and Connection as session properties.
iHttpSess.ConnectionInfo().SetPropertyL
(
StringF( HTTP::EHttpSocketServ ),
THTTPHdrVal( iSockServ.Handle() )
);
PUSHLOG_WRITE("CPushMtmFetchOperation EHttpSocketServ set")
iHttpSess.ConnectionInfo().SetPropertyL
(
StringF( HTTP::EHttpSocketConnection ),
THTTPHdrVal( REINTERPRET_CAST( TInt, &iConn ) )
);
PUSHLOG_WRITE("CPushMtmFetchOperation EHttpSocketConnection set")
// Open different string tables to the session. These are required
// by the Accept Header Filter.
iHttpSess.StringPool().OpenL( HttpFilterCommonStringsExt::GetTable() );
PUSHLOG_WRITE("CPushMtmFetchOperation table 1 opened");
iHttpSess.StringPool().OpenL( HttpFilterCommonStringsExt::GetLanguageTable() );
PUSHLOG_WRITE("CPushMtmFetchOperation table 2 opened");
// Install the very same set of filters that BrowserEngine installs.
// The following filters must not be installed:
// - Authentication Filter, because the fetch operation and the push mtm
// subsystem does not support credentials.
// - Conn Handler Filter, because the fetch operation let it to the HTTP
// core framework to create connection - it just sets the acces point.
// Install UAProf filter.
CHttpUAProfFilterInterface::InstallFilterL( iHttpSess );
PUSHLOG_WRITE(" UAProf installed")
// Install cookie filter.
CHttpCookieFilter::InstallFilterL( iHttpSess );
PUSHLOG_WRITE(" Cookie filter installed")
// Create cache manager
FeatureManager::InitializeLibL();
iCacheMgr = CHttpCacheManager::NewL();
PUSHLOG_WRITE(" Cache Manager installed")
// Install Accept Header Filter.
CHttpFilterAcceptHeaderInterface::InstallFilterL( iHttpSess );
PUSHLOG_WRITE(" Accept Header Filter installed")
// Install IOP Filter.
CHttpFilterIopInterface::InstallFilterL( iHttpSess, iopOptionHostHeader );
PUSHLOG_WRITE(" IOP Filter installed")
// Install Deflate Filter.
CHttpDeflateFilter::InstallFilterL( iHttpSess );
PUSHLOG_WRITE(" Deflate Filter installed");
TUint32 defIapId( 0 );
TBool defIapIdFound = EFalse;
TCommDbConnPref commPrefs;
#ifndef __WINS__
// Use Browser default AP & comms db:
defIapIdFound = GetDefaultInetAccessPointL( defIapId );
PUSHLOG_WRITE_FORMAT(" defIapIdFound: <%d>",(TInt)defIapIdFound)
PUSHLOG_WRITE_FORMAT(" defIapId: <%d>",defIapId)
commPrefs.SetDialogPreference( ECommDbDialogPrefDoNotPrompt );
if ( defIapIdFound )
{
commPrefs.SetIapId( defIapId );
}
#else // __WINS__
// Prompt the user to select access point
commPrefs.SetDialogPreference( ECommDbDialogPrefPrompt );
#endif // __WINS__
iState = EStartRequest;
iStatus = KRequestPending;
SetActive();
iConn.Start( commPrefs, iStatus );
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::InitializeL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::StartRequestL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::StartRequestL()
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::StartRequestL")
// Create the transaction.
CreateTransactionL();
CheckCacheL();
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::StartRequestL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::CheckCacheL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::CheckCacheL()
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::CheckCacheL")
iCacheSupply = CPushMtmCacheSupply::NewL(iCacheMgr, this);
TInt ret = iCacheSupply->StartRequestL();
iStatus = KRequestPending;
SetActive();
if (ret != KErrNone) // Not in cache
{
iState = ERequest;
iCachedResponse = ETrue;
TRequestStatus* status = &iStatus;
User::RequestComplete( status, KErrNone);
}
else
{
iState = EDone;
iCachedResponse = EFalse;
}
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::CheckCacheL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::RequestL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::RequestL()
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::RequestL")
iState = EDone;
iStatus = KRequestPending;
SetActive();
SubmitTransactionL();
// Do not call InvokeRun(). Let MHFRunL to handle the request.
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::RequestL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::Done
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::Done()
{
PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::Done iResult: <%d>",iResult);
delete iRequestedUrl;
iRequestedUrl = NULL;
// Notify parent.
TRequestStatus* status = &iObserver;
User::RequestComplete( status, iResult );
// iState = EInit;
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::CreateTransactionL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::CreateTransactionL()
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::CreateTransactionL")
__ASSERT_DEBUG( iRequestedUrl,
ContHandPanic( EPushContHandPanNotInitUrl ) );
// Create the transaction.
TUriParser8 uri;
User::LeaveIfError( uri.Parse( *iRequestedUrl ) );
iHttpTrans =
iHttpSess.OpenTransactionL( uri, *this, StringF( HTTP::EGET ) );
PUSHLOG_WRITE("CPushMtmFetchOperation OpenTransactionL OK")
// Set request headers.
RHTTPHeaders hdr = iHttpTrans.Request().GetHeaderCollection();
SetHeaderL( hdr, HTTP::EUserAgent, KUserAgent );
SetHeaderL( hdr, HTTP::EAccept, HTTP::EAnyAny );
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::CreateTransactionL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::SubmitTransactionL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::SubmitTransactionL()
{
iHttpTrans.SubmitL();
PUSHLOG_WRITE("CPushMtmFetchOperation iHttpTrans.SubmitL OK")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::HandleResponseHeadersL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::HandleResponseHeadersL( RHTTPResponse aResponse )
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::HandleResponseHeadersL")
TInt httpCode = aResponse.StatusCode();
PUSHLOG_WRITE_FORMAT(" HttpStatus: %d",httpCode)
#ifdef __TEST_LOG__
LogHeadersL( aResponse.GetHeaderCollection() );
#endif // __TEST_LOG__
if ( HTTPStatus::IsSuccessful( httpCode ) &&
( httpCode != HTTPStatus::ENoContent ) )
{
// Successful GET.
PUSHLOG_WRITE(" Successful GET")
// Get content type.
iDataType = TDataType
( GetContentTypeL( aResponse.GetHeaderCollection() ) );
// Get source URI.
HBufC8* buf = GetSourceUriL( iHttpTrans ).AllocL();
PUSHLOG_WRITE(" Source URI got")
delete iSourceUri;
iSourceUri = buf;
// No error:
iResult = KErrNone;
}
else
{
// See Extended Error Handling UI Specification!
iResult = KPushMtmHttpErrorBase - httpCode;
PUSHLOG_WRITE_FORMAT(" iResult: <%d>",iResult)
}
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::HandleResponseHeadersL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::VersionRetryL
// ---------------------------------------------------------
//
TBool CPushMtmFetchOperation::VersionRetryL()
{
TBool retryDone( EFalse );
// Check what http version we are using.
THTTPHdrVal val;
TBool exists = iHttpSess.ConnectionInfo().Property
(
StringF( HTTP::EHTTPVersion ),
val
);
if ( exists && TInt( val ) == HTTP::EHttp11 )
{
// Currently using HTTP/1.1. Cancel transaction and resubmit it using
// HTTP/1.0.
iHttpTrans.Cancel();
iHttpSess.ConnectionInfo().SetPropertyL
(
StringF( HTTP::EHTTPVersion ),
THTTPHdrVal( StringF( HTTP::EHttp10 ) )
);
SubmitTransactionL();
retryDone = ETrue;
}
return retryDone;
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::AppendResponse
// ---------------------------------------------------------
//
TInt CPushMtmFetchOperation::AppendResponse( const TDesC8& aDataChunk )
{
TInt err( KErrNone );
HBufC8* newBodyBuf = NULL;
if ( !iBody )
{
// iBody does not exist yet; allocate buffer for the first data chunk.
newBodyBuf = HBufC8::New( aDataChunk.Length() );
}
else
{
const TInt needed( iBody->Des().Length() + aDataChunk.Length() );
if ( iBody->Des().MaxLength() < needed )
{
// iBody exists, but small.
newBodyBuf = iBody->ReAlloc( needed );
iBody = NULL; // ReAlloc deleted it!
}
else
{
// iBody exists and the new chunk fits into it.
}
}
if ( newBodyBuf )
{
__ASSERT_DEBUG( iBody == NULL,
ContHandPanic( EPushContHandPanAlreadyInitialized ) );
delete iBody; // Not necessary, JIC.
iBody = newBodyBuf;
}
else
{
if (aDataChunk.Length() > 0)
{
err = KErrNoMemory;
}
}
if ( !err )
{
iBody->Des().Append( aDataChunk );
}
return err;
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::SetHeaderL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders,
HTTP::TStrings aHdrField,
const TDesC8& aHdrValue )
{
RStringF valStr = iHttpSess.StringPool().OpenFStringL( aHdrValue );
CleanupClosePushL<RStringF>( valStr );
SetHeaderL( aHeaders, aHdrField, valStr );
CleanupStack::PopAndDestroy(); // close valStr
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::SetHeaderL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders,
HTTP::TStrings aHdrField,
HTTP::TStrings aHdrValue )
{
SetHeaderL( aHeaders, aHdrField, StringF( aHdrValue ) );
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::SetHeaderL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::SetHeaderL( RHTTPHeaders aHeaders,
HTTP::TStrings aHdrField,
const RStringF aHdrValue )
{
THTTPHdrVal val( aHdrValue );
aHeaders.SetFieldL( StringF( aHdrField ), val );
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::GetContentTypeL
// ---------------------------------------------------------
//
const TDesC8& CPushMtmFetchOperation::GetContentTypeL( RHTTPHeaders aHeaders )
{
THTTPHdrVal hdrVal;
User::LeaveIfError
( aHeaders.GetField( StringF( HTTP::EContentType ), 0, hdrVal ) );
if ( hdrVal.Type() != THTTPHdrVal::KStrFVal )
{
User::Leave( KErrArgument );
}
return hdrVal.StrF().DesC();
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::GetSourceUriL
// ---------------------------------------------------------
//
const TDesC8& CPushMtmFetchOperation::GetSourceUriL
( RHTTPTransaction aTransaction )
{
// TODO if redirected URI exists, how do we get it?
// For the moment request URI is used.
return aTransaction.Request().URI().UriDes();
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::LogHeadersL
// ---------------------------------------------------------
//
#ifndef __TEST_LOG__
void CPushMtmFetchOperation::LogHeadersL( RHTTPHeaders /*aHeaders*/ )
{
}
#else // #ifdef __TEST_LOG__
void CPushMtmFetchOperation::LogHeadersL( RHTTPHeaders aHeaders )
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::LogHeadersL")
_LIT( KDateFormat, "%D%M%Y%/0%1%/1%2%/2%3%/3 %:0%H%:1%T%:2%S.%C%:3" );
PUSHLOG_WRITE("Headers:");
RStringPool strP = iHttpTrans.Session().StringPool();
THTTPHdrFieldIter it = aHeaders.Fields();
while ( !it.AtEnd() )
{
RStringTokenF fieldName = it();
RStringF fieldNameStr = strP.StringF( fieldName );
THTTPHdrVal fieldVal;
if ( aHeaders.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
{
const TInt KMaxLogStrLen = 64;
TPtrC8 fieldName8 = fieldNameStr.DesC();
TInt fieldNameLen = fieldName8.Length();
fieldNameLen = ( KMaxLogStrLen < fieldNameLen ) ?
KMaxLogStrLen : fieldNameLen;
fieldName8.Set( fieldName8.Mid( 0, fieldNameLen ) );
HBufC* fieldNameHBufC = HBufC::NewMaxLC( fieldName8.Length() );
TPtr fieldName = fieldNameHBufC->Des();
fieldName.Copy( fieldName8 );
switch ( fieldVal.Type() )
{
case THTTPHdrVal::KTIntVal:
{
PUSHLOG_WRITE_FORMAT2
(" <%S> (%d)",&fieldName,fieldVal.Int())
break;
}
case THTTPHdrVal::KStrFVal:
{
RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
TPtrC8 fieldVal8 = fieldValStr.DesC();
// Truncate if too long.
TInt fieldValLen = fieldVal8.Length();
fieldNameLen = ( KMaxLogStrLen < fieldValLen ) ?
KMaxLogStrLen : fieldValLen;
fieldVal8.Set( fieldVal8.Mid( 0, fieldValLen ) );
// Truncate end.
HBufC* fieldValHBufC = HBufC::NewMaxLC( fieldVal8.Length() );
TPtr fieldVal = fieldValHBufC->Des();
fieldVal.Copy( fieldVal8 );
PUSHLOG_WRITE_FORMAT2
(" <%S> (%S)",&fieldName,&fieldVal)
CleanupStack::PopAndDestroy( fieldValHBufC );
// fieldValHBufC
break;
}
case THTTPHdrVal::KStrVal:
{
RString fieldValStr = strP.String( fieldVal.Str() );
TPtrC8 fieldVal8 = fieldValStr.DesC();
// Truncate if too long.
TInt fieldValLen = fieldVal8.Length();
fieldNameLen = ( KMaxLogStrLen < fieldValLen ) ?
KMaxLogStrLen : fieldValLen;
fieldVal8.Set( fieldVal8.Mid( 0, fieldValLen ) );
// Truncate end.
HBufC* fieldValHBufC = HBufC::NewMaxLC( fieldVal8.Length() );
TPtr fieldVal = fieldValHBufC->Des();
fieldVal.Copy( fieldVal8 );
PUSHLOG_WRITE_FORMAT2
(" <%S> (%S)",&fieldName,&fieldVal)
CleanupStack::PopAndDestroy( fieldValHBufC );
// fieldValHBufC
break;
}
case THTTPHdrVal::KDateVal:
{
TDateTime date = fieldVal.DateTime();
TBuf<40> dateTimeString;
TTime t( date );
TRAP_IGNORE( t.FormatL( dateTimeString, KDateFormat ) );
PUSHLOG_WRITE_FORMAT2
(" <%S> (%S)",&fieldName,&dateTimeString)
break;
}
default:
{
PUSHLOG_WRITE_FORMAT2
(" <%S> unrecognised value type (%d)",
&fieldName,fieldVal.Type())
break;
}
}
// Display realm for WWW-Authenticate header.
RStringF wwwAuth = strP.StringF
( HTTP::EWWWAuthenticate, RHTTPSession::GetTable() );
if ( fieldNameStr == wwwAuth )
{
PUSHLOG_WRITE(" fieldNameStr == wwwAuth")
// check the auth scheme is 'basic'
RStringF basic = strP.StringF
( HTTP::EBasic, RHTTPSession::GetTable() );
RStringF realm = strP.StringF
( HTTP::ERealm, RHTTPSession::GetTable() );
THTTPHdrVal realmVal;
if ( ( fieldVal.StrF() == basic ) &&
( !aHeaders.GetParam( wwwAuth, realm, realmVal ) ) )
{
RStringF realmValStr = strP.StringF( realmVal.StrF() );
PUSHLOG_WRITE_FORMAT(" Realm <%S>",&realmValStr);
}
}
CleanupStack::PopAndDestroy( fieldNameHBufC ); // fieldNameHBufC
}
++it;
}
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::LogHeadersL")
}
#endif // __TEST_LOG__
// ---------------------------------------------------------
// CPushMtmFetchOperation::DoCancel
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::DoCancel()
{
switch ( iState )
{
/*case EStartConnect:
{
// Complete ourselves - nothing is outstanding.
TRequestStatus* ownStatus = &iStatus;
User::RequestComplete( ownStatus, KErrCancel );
break;
}*/
/*case EConnect:
{
//__ASSERT_DEBUG( iConn, ContHandPanic( ECodInternal ) );
//iConn->Cancel(); // This will complete our status.
break;
}*/
case EStartRequest:
case ECheckCache:
case ERequest:
{
delete iCacheSupply;
iCacheSupply = NULL;
iHttpTrans.Close();
// Now the transaction has been closed. Closing it does not
// complete our status, so we do it manually.
TRequestStatus* status = &iStatus;
SetActive();
User::RequestComplete( status, iResult );
break;
}
case EInit:
default:
{
// No requests should be outstanding in these states.
//ContHandPanic( ECodInternal );
break;
}
}
iResult = KErrCancel;
Done();
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::RunL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::RunL()
{
PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunL status = %d", iState);
// Handle errors in RunError().
User::LeaveIfError( iStatus.Int() );
switch ( iState )
{
case EInit:
{
InitializeL();
break;
}
case EStartRequest:
{
StartRequestL();
break;
}
case ERequest:
{
RequestL();
break;
}
case EDone:
{
Done();
break;
}
default:
{
// JIC.
Done();
break;
}
}
PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunL moving to status = %d", iState);
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::RunError
// ---------------------------------------------------------
//
TInt CPushMtmFetchOperation::RunError( TInt aError )
{
PUSHLOG_WRITE_FORMAT("CPushMtmFetchOperation::RunError <%d>",aError)
iResult = aError;
delete iCacheSupply;
iCacheSupply = NULL;
iHttpTrans.Close();
Done();
return KErrNone;
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::MHFRunL
// ---------------------------------------------------------
//
void CPushMtmFetchOperation::MHFRunL
(
RHTTPTransaction DEBUG_ONLY( aTransaction ),
const THTTPEvent& aEvent
)
{
PUSHLOG_ENTERFN("CPushMtmFetchOperation::MHFRunL")
__ASSERT_DEBUG( aTransaction == iHttpTrans,
ContHandPanic( EPushContHandPanBadTransaction ) );
switch ( aEvent.iStatus )
{
case THTTPEvent::EGotResponseHeaders:
{
PUSHLOG_WRITE(" EGotResponseHeaders")
// pass headers to the cache first
TRAP_IGNORE( iCacheSupply->HeadersReceivedL() );
// Now we know that the request was processed by the server.
HandleResponseHeadersL( iHttpTrans.Response() );
break;
}
case THTTPEvent::EGotResponseBodyData:
{
PUSHLOG_WRITE(" EGotResponseBodyData")
// pass chunk to the cache first
TRAP_IGNORE( iCacheSupply->BodyReceivedL() );
// Get body data and save it.
TInt err( KErrNone );
MHTTPDataSupplier* body = iHttpTrans.Response().Body();
if ( !body )
{
PUSHLOG_WRITE(" NULL body")
}
else
{
TPtrC8 bodyPtr;
// Caution: no leaving between body->GetNextDataPart and
// body->ReleaseData calls! Data must always be released.
#ifdef __TEST_LOG__
TBool isLast = body->GetNextDataPart( bodyPtr ); // No leave...
PUSHLOG_WRITE_FORMAT(" last? (%d)",(isLast?1:0))
#else // ifndef __TEST_LOG__
(void)body->GetNextDataPart( bodyPtr ); // No leave...
#endif // __TEST_LOG__
//if ( iHttpTrans.Request().Method() == StringF( HTTP::EGET ) )
err = AppendResponse( bodyPtr );
body->ReleaseData(); // ...until here.
PUSHLOG_WRITE_FORMAT(" err: (%d)",err)
User::LeaveIfError( err );
}
break;
}
case THTTPEvent::EResponseComplete:
{
// do not mix it up with the ESucceeded
// The transaction's response is complete. An incoming event.
TRAP_IGNORE( iCacheSupply->ResponseCompleteL() );
break;
}
case THTTPEvent::ERequestComplete:
{
// request is all set
iCacheSupply->CloseRequest();
break;
}
case THTTPEvent::EFailed:
{
PUSHLOG_WRITE(" EFailed")
// Safety code: we should already have an error code.
if ( iResult == KErrNone )
{
iResult = KErrGeneral;
}
// TODO. Fall through.
}
case THTTPEvent::ESucceeded:
{
PUSHLOG_WRITE(" ESucceeded")
delete iCacheSupply;
iCacheSupply = NULL;
iHttpTrans.Close();
// Transaction is finished, invoke RunL now.
TRequestStatus* status = &iStatus;
if (!IsActive())
{
SetActive();
}
User::RequestComplete( status, iResult );
break;
}
case THTTPEvent::ERedirectedPermanently:
{
PUSHLOG_WRITE(" ERedirectedPermanently")
// Do nothing just continue.
break;
}
default:
{
PUSHLOG_WRITE(" default case")
// Handle errors in MHFRunError.
User::LeaveIfError( aEvent.iStatus );
break;
}
}
PUSHLOG_LEAVEFN("CPushMtmFetchOperation::MHFRunL")
}
// ---------------------------------------------------------
// CPushMtmFetchOperation::MHFRunError
// ---------------------------------------------------------
//
TInt CPushMtmFetchOperation::MHFRunError
(
TInt aError,
RHTTPTransaction DEBUG_ONLY( aTransaction ),
const THTTPEvent& /*aEvent*/
)
{
__ASSERT_DEBUG( aTransaction == iHttpTrans,
ContHandPanic( EPushContHandPanBadTransaction ) );
iResult = aError;
iCacheSupply->CloseRequest();
iHttpTrans.Close();
// Transaction is finished, invoke RunL now.
// iResult contains the (error) code.
if ( !IsActive() )
{
SetActive();
}
TRequestStatus* status = &iStatus;
User::RequestComplete( status, KErrNone );
return KErrNone;
}
// End of file.