uidesigner/com.nokia.sdt.series60.componentlibrary/components/non-layout/webclient/WebClientEngine.cpp
don't rely on all services reporting in-use together for UI to show connection in use
/*
* Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description:
*
*/
// INCLUDE FILES
#include <avkon.hrh>
#include <aknnotewrappers.h>
#include <stringloader.h>
#include <http.h>
//#include <WebClient.rsg>
#include "WebClientEngine.pan"
//#include "WebClient.hrh"
#include "WebClientEngine.h"
// ----------------------------------------------------------------------------
// CWebClientEngine::NewL()
// Creates instance of CWebClientEngine.
// ----------------------------------------------------------------------------
//
CWebClientEngine* CWebClientEngine::NewL( MWebClientObserver& aObserver )
{
CWebClientEngine* self = CWebClientEngine::NewLC( aObserver );
CleanupStack::Pop( self );
return self;
}
// ----------------------------------------------------------------------------
// CWebClientEngine::NewLC()
// Creates instance of CWebClientEngine.
// ----------------------------------------------------------------------------
//
CWebClientEngine* CWebClientEngine::NewLC( MWebClientObserver& aObserver )
{
CWebClientEngine* self = new (ELeave) CWebClientEngine( aObserver );
CleanupStack::PushL( self );
self->ConstructL();
return self;
}
// ----------------------------------------------------------------------------
// CWebClientEngine::CWebClientEngine()
// First phase constructor.
// ----------------------------------------------------------------------------
//
CWebClientEngine::CWebClientEngine( MWebClientObserver& aObserver )
: iObserver( aObserver ),
iSessionOpened( EFalse ),
iRunning( EFalse )
{
// no implementation required
}
// ----------------------------------------------------------------------------
// CWebClientEngine::~CWebClientEngine()
// Destructor.
// ----------------------------------------------------------------------------
//
CWebClientEngine::~CWebClientEngine()
{
iSession.Close();
iConnection.Close();
iSocketServ.Close();
}
// ----------------------------------------------------------------------------
// CWebClientEngine::ConstructL()
// Second phase construction.
// ----------------------------------------------------------------------------
//
void CWebClientEngine::ConstructL()
{
}
void CWebClientEngine::OpenSessionL()
{
if (iSessionOpened) return;
// Open RHTTPSession with default protocol ("HTTP/TCP")
TRAPD( err, iSession.OpenL() );
if( err != KErrNone ) {
// Most common error; no access point configured, and session creation
// leaves with KErrNotFound.
iObserver.ClientOpenSessionFailedL( *this, err );
User::Leave( err );
}
User::LeaveIfError(iSocketServ.Connect());
User::LeaveIfError(iConnection.Open(iSocketServ));
User::LeaveIfError(iConnection.Start());
RStringPool strP = iSession.StringPool();
RHTTPConnectionInfo connInfo = iSession.ConnectionInfo();
connInfo.SetPropertyL ( strP.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable() ), THTTPHdrVal (iSocketServ.Handle()) );
TInt connPtr = REINTERPRET_CAST(TInt, &(iConnection));
connInfo.SetPropertyL ( strP.StringF(HTTP::EHttpSocketConnection, RHTTPSession::GetTable() ), THTTPHdrVal (connPtr) );
// Install this class as the callback for authentication requests. When
// page requires authentication the framework calls GetCredentialsL to get
// user name and password.
InstallAuthenticationL( iSession );
iSessionOpened = true;
}
// ----------------------------------------------------------------------------
// CWebClientEngine::SetHeaderL()
// Used to set header value to HTTP request
// ----------------------------------------------------------------------------
//
void CWebClientEngine::SetHeaderL( RHTTPHeaders aHeaders,
TInt aHdrField,
const TDesC8& aHdrValue )
{
RStringF valStr = iSession.StringPool().OpenFStringL( aHdrValue );
CleanupClosePushL( valStr );
THTTPHdrVal val( valStr );
aHeaders.SetFieldL( iSession.StringPool().StringF( aHdrField,
RHTTPSession::GetTable() ), val );
CleanupStack::PopAndDestroy( &valStr );
}
// ----------------------------------------------------------------------------
// CWebClientEngine::DumpRespHeadersL(RHTTPTransaction& aTransaction)
// Used to display HTTP header field names and values
// ----------------------------------------------------------------------------
//
void CWebClientEngine::DumpRespHeadersL( RHTTPTransaction& aTransaction )
{
RHTTPResponse resp = aTransaction.Response();
RStringPool strP = aTransaction.Session().StringPool();
RHTTPHeaders hdr = resp.GetHeaderCollection();
THTTPHdrFieldIter it = hdr.Fields();
HBufC* headerField = HBufC::NewLC( KMaxHeaderNameLength + KMaxHeaderValueLength );
HBufC* fieldValBuf = HBufC::NewLC( KMaxHeaderValueLength );
while ( it.AtEnd() == EFalse )
{
RStringTokenF fieldName = it();
RStringF fieldNameStr = strP.StringF( fieldName );
THTTPHdrVal fieldVal;
if ( hdr.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
{
const TDesC8& fieldNameDesC = fieldNameStr.DesC();
headerField->Des().Copy( fieldNameDesC.Left( KMaxHeaderNameLength ));
fieldValBuf->Des().Zero();
switch ( fieldVal.Type() )
{
// the value is an integer
case THTTPHdrVal::KTIntVal:
fieldValBuf->Des().Num( fieldVal.Int() );
break;
// the value is a case-insensitive string
case THTTPHdrVal::KStrFVal:
{
RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
const TDesC8& fieldValDesC = fieldValStr.DesC();
fieldValBuf->Des().Copy( fieldValDesC.Left(KMaxHeaderValueLength ));
}
break;
// the value is a case-sensitive string
case THTTPHdrVal::KStrVal:
{
RString fieldValStr = strP.String( fieldVal.Str() );
const TDesC8& fieldValDesC = fieldValStr.DesC();
fieldValBuf->Des().Copy( fieldValDesC.Left(KMaxHeaderValueLength) );
}
break;
// the value is a date/time
case THTTPHdrVal::KDateVal:
{
TDateTime date = fieldVal.DateTime();
TBuf<KMaxDateTimeStringLength> dateTimeString;
TTime t( date );
t.FormatL( dateTimeString,KDateFormat );
fieldValBuf->Des().Copy( dateTimeString );
}
break;
// the value is type is unknown
default:
break;
}
// Display HTTP header field name and value
headerField->Des().Append( KColon );
headerField->Des().Append( *fieldValBuf );
iObserver.ClientHeaderReceivedL( *this, *headerField );
// Display realm for WWW-Authenticate header
RStringF wwwAuth = strP.StringF( HTTP::EWWWAuthenticate,RHTTPSession::GetTable() );
if ( 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 ) &&
( !hdr.GetParam( wwwAuth, realm, realmVal )))
{
RStringF realmValStr = strP.StringF( realmVal.StrF() );
fieldValBuf->Des().Copy( realmValStr.DesC() );
headerField->Des().Copy( Krealm );
headerField->Des().Append( *fieldValBuf );
iObserver.ClientHeaderReceivedL( *this, *headerField );
}
}
}
++it;
}
CleanupStack::PopAndDestroy( fieldValBuf );
CleanupStack::PopAndDestroy( headerField );
}
// ----------------------------------------------------------------------------
// CWebClientEngine::HandleRunErrorL()
// Called from MHFRunError() when *leave* occurs in handling of transaction event.
// ----------------------------------------------------------------------------
//
void CWebClientEngine::HandleRunErrorL( TInt aError )
{
iObserver.ClientRunErrorL( *this, aError );
}
// ----------------------------------------------------------------------------
// CWebClientEngine::IssueHTTPGetL()
// Start a new HTTP GET transaction.
// ----------------------------------------------------------------------------
//
void CWebClientEngine::IssueHTTPGetL( const TDesC8& aUri )
{
// Ensure the session is open
OpenSessionL();
// Parse string to URI (as defined in RFC2396)
TUriParser8 uri;
uri.Parse( aUri );
// Get request method string for HTTP GET
RStringF method = iSession.StringPool().StringF( HTTP::EGET,
RHTTPSession::GetTable());
// Open transaction with previous method and parsed uri. This class will
// receive transaction events in MHFRunL and MHFRunError.
iTransaction = iSession.OpenTransactionL( uri, *this, method );
// Set headers for request; user agent and accepted content type
RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
SetHeaderL( hdr, HTTP::EUserAgent, KUserAgent );
SetHeaderL( hdr, HTTP::EAccept, KAccept );
// Submit the transaction. After this the framework will give transaction
// events via MHFRunL and MHFRunError.
iTransaction.SubmitL();
iRunning = ETrue;
iObserver.ClientConnectingL( *this );
}
// ----------------------------------------------------------------------------
// CWebClientEngine::CancelTransactionL()
// Cancels currently running transaction and frees resources related to it.
// ----------------------------------------------------------------------------
//
void CWebClientEngine::CancelTransactionL()
{
if( !iRunning )
return;
// Close() also cancels transaction (Cancel() can also be used but
// resources allocated by transaction must be still freed with Close())
iTransaction.Close();
// Not running anymore
iRunning = EFalse;
iObserver.ClientConnectionCanceledL( *this );
}
// ----------------------------------------------------------------------------
// CWebClientEngine::MHFRunL()
// Inherited from MHTTPTransactionCallback
// Called by framework to pass transaction events.
// ----------------------------------------------------------------------------
//
void CWebClientEngine::MHFRunL( RHTTPTransaction aTransaction,
const THTTPEvent& aEvent )
{
switch ( aEvent.iStatus )
{
case THTTPEvent::EGotResponseHeaders:
{
// HTTP response headers have been received. Use
// aTransaction.Response() to get the response. However, it's not
// necessary to do anything with the response when this event occurs.
// Get HTTP status code from header (e.g. 200)
RHTTPResponse resp = aTransaction.Response();
TInt status = resp.StatusCode();
// Get status text (e.g. "OK")
TBuf<KMaxStatusTextLength> statusText;
statusText.Copy( resp.StatusText().DesC() );
// Display header field names and value
DumpRespHeadersL( aTransaction );
}
break;
case THTTPEvent::EGotResponseBodyData:
{
// Part (or all) of response's body data received. Use
// aTransaction.Response().Body()->GetNextDataPart() to get the actual
// body data.
// Get the body data supplier
MHTTPDataSupplier* body = aTransaction.Response().Body();
TPtrC8 dataChunk;
// GetNextDataPart() returns ETrue, if the received part is the last
// one.
TBool isLast = body->GetNextDataPart( dataChunk );
iObserver.ClientBodyReceivedL( *this, dataChunk );
// Always remember to release the body data.
body->ReleaseData();
}
break;
case THTTPEvent::EResponseComplete:
{
// Indicates that header & body of response is completely received.
// No further action here needed.
iObserver.ClientResponseCompleteL( *this );
}
break;
case THTTPEvent::ESucceeded:
{
// Indicates that transaction succeeded.
iObserver.ClientTransactionSucceededL( *this );
// Transaction can be closed now. It's not needed anymore.
aTransaction.Close();
iRunning = EFalse;
}
break;
case THTTPEvent::EFailed:
{
// Transaction completed with failure.
iObserver.ClientTransactionFailedL( *this );
aTransaction.Close();
iRunning = EFalse;
}
break;
default:
// There are more events in THTTPEvent, but they are not usually
// needed. However, event status smaller than zero should be handled
// correctly since it's error.
{
iObserver.ClientUnknownEventL( *this, aEvent.iStatus );
if ( aEvent.iStatus < 0 )
{
// Just close the transaction on errors
aTransaction.Close();
iRunning = EFalse;
}
}
break;
}
}
// ----------------------------------------------------------------------------
// CWebClientEngine::MHFRunError()
// Inherited from MHTTPTransactionCallback
// Called by framework when *leave* occurs in handling of transaction event.
// These errors must be handled, or otherwise HTTP-CORE 6 panic is thrown.
// ----------------------------------------------------------------------------
//
TInt CWebClientEngine::MHFRunError( TInt aError,
RHTTPTransaction /*aTransaction*/,
const THTTPEvent& /*aEvent*/)
{
// Handle error and return KErrNone.
TRAPD( err, HandleRunErrorL( aError ) );
if( err )
Panic( EClientEngine );
return KErrNone;
}
// ----------------------------------------------------------------------------
// CWebClientEngine::GetCredentialsL()
//
// Inherited from MHTTPAuthenticationCallback
// Called by framework when we requested authenticated page and framework
// needs to know username and password.
// ----------------------------------------------------------------------------
TBool CWebClientEngine::GetCredentialsL( const TUriC8& aUri,
RString aRealm,
RStringF /*aAuthenticationType*/,
RString& aUsername,
RString& aPassword)
{
TBuf<KMaxUserNameLength> userName;
TBuf<KMaxPasswordLength> password;
TBool haveCredentials = iObserver.ClientGetCredentialsL( *this, aUri, aRealm.DesC(), userName, password);
if (haveCredentials)
{
// Set aUsername and aPassword
TBuf8<KMaxUserNameLength> temp;
temp.Copy( userName );
TRAPD( err, aUsername = aRealm.Pool().OpenStringL( temp ));
if ( !err )
{
temp.Copy( password );
TRAP( err, aPassword = aRealm.Pool().OpenStringL( temp ));
if ( !err ) return ETrue;
}
}
return EFalse;
}