applayerprotocols/httpexamples/TestWebBrowser/src/testwebbrowser.cpp
changeset 0 b16258d2340f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/applayerprotocols/httpexamples/TestWebBrowser/src/testwebbrowser.cpp	Tue Feb 02 01:09:52 2010 +0200
@@ -0,0 +1,520 @@
+// Copyright (c) 2005-2009 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:
+//
+
+#include <e32base.h>
+#include <http.h>
+#include <escapeutils.h>
+
+#include "testwebbrowser.h"
+#include "httpexampleutils.h"
+
+
+const TInt KMaxURISize = 256;
+const TInt KMaxFilePathLength = 512;
+const TInt KHttpSchemeLength = 7;
+
+_LIT ( KDirPath, "c:\\TestWebBrowser\\");
+_LIT ( KDefaultFilePath, "index.html" );
+_LIT ( KQuit, "quit" );
+_LIT ( KSelectOption, " Select an option \n\n" );
+_LIT ( KPossibleSelectionsText, " 1 Download URL \n 2 Set Proxy\n 3 Quit \n" );
+_LIT ( KPossibleSelections,"123" );
+_LIT ( KEnterUrl, "Enter URL: " );
+_LIT ( KEnterProxy, "Enter Proxy Address: " );	
+		
+// Invalid characters that can appear in a URL. These values must be replaced
+// with a valid character to generate the full file path.
+_LIT ( KInvalidChars, "<>:\"|*?");
+
+const TUint KReplaceChar = '_';
+
+void ChangePathSeparator( TDes& aDesPtr, TUint aPathSeperatorFrom, TUint aPathSeperatorTo )
+	{
+	for( TInt offset = aDesPtr.Length() - 1; offset >= 0; offset-- )
+		{
+		if ( aDesPtr[offset] == aPathSeperatorFrom )
+			{	
+				aDesPtr[offset] = TUint16( aPathSeperatorTo );
+			}
+		}
+	}
+
+CTestWebBrowser::CTestWebBrowser ( CHttpExampleUtils& aUtils )
+: CActive ( EPriorityStandard ),
+iTestUtils ( aUtils ),
+iCurrentState ( EMainMenu )
+	{
+	//Add this active object to the active schedeler
+	CActiveScheduler::Add(this);
+	__ASSERT_DEBUG( !IsActive(),User::Panic(_L("Reader"), KErrCorrupt) );
+	
+	// Wait for request to be handled.
+	IssueAndCompleteRequest();		
+	}
+
+
+CTestWebBrowser::~CTestWebBrowser ()
+	{
+	// Close the HTTP session.
+	iHttpSession.Close();
+	
+	iTransArray.ResetAndDestroy ();
+	iTransArray.Close ();
+	
+	delete iBaseUri;
+	}
+	
+CTestWebBrowser* CTestWebBrowser::NewLC ( CHttpExampleUtils& aUtils )	
+	{
+	CTestWebBrowser* me = new (ELeave) CTestWebBrowser ( aUtils );
+	CleanupStack::PushL ( me );
+	me->ConstructL ();
+	return me;
+	}
+
+void CTestWebBrowser::ConstructL ()
+	{
+	// Open a HTTP session.
+	iHttpSession.OpenL ();
+	
+	// Install the callback into the session.
+	InstallAuthenticationL ( iHttpSession );
+	
+	iBaseUri = HBufC8::NewL ( KMaxURISize );
+	}
+
+CTestWebBrowser* CTestWebBrowser::NewL ( CHttpExampleUtils& aUtils )	
+	{
+	CTestWebBrowser* me = CTestWebBrowser::NewLC ( aUtils );
+	CleanupStack::Pop ( me );
+	return me;
+	}
+
+/**
+	Set HTTP proxy information for the session.
+	
+	@param aProxyAddr [in] Proxy address to set for the session
+ */	
+void CTestWebBrowser::SetProxyL ( const TDesC8& aProxyAddr )
+	{
+	
+	RHTTPConnectionInfo connInfo = iHttpSession.ConnectionInfo();
+	
+	// Set the proxy usage property.
+	THTTPHdrVal proxyUsage( iHttpSession.StringPool().StringF( HTTP::EUseProxy, RHTTPSession::GetTable() ) );
+	connInfo.SetPropertyL( iHttpSession.StringPool().StringF( HTTP::EProxyUsage, RHTTPSession::GetTable() ), proxyUsage );
+	
+	RStringF proxyAddr = iHttpSession.StringPool ().OpenFStringL ( aProxyAddr );
+	CleanupClosePushL ( proxyAddr );
+	
+	// Set the proxy address property.
+	THTTPHdrVal proxyAddrHdr( proxyAddr );
+    connInfo.SetPropertyL( iHttpSession.StringPool().StringF( HTTP::EProxyAddress, RHTTPSession::GetTable() ), proxyAddrHdr );
+    
+    CleanupStack::PopAndDestroy (); // Pop and destroy proxyAddr
+	return;		
+	}
+
+/**
+	Get the credentials from the user.
+	
+	@param aURI [in] The URI being requested
+	@param aRealm [out] The realm being requested
+	@param aAuthenticationType [out] The type of authentication.
+	@param aUsername [out] User name
+	@param aPassword [out] Pass word
+	
+	@return TBool ETrue if credentials being returned else EFalse
+ */		
+TBool CTestWebBrowser::GetCredentialsL( const TUriC8& aURI, 
+										RString aRealm, 
+									   	RStringF aAuthenticationType,
+									   	RString& aUsername, 
+									   	RString& aPassword )
+	{
+	// Convert to 16 bit to display
+	HBufC* uriDesBuf = HBufC::NewLC( aURI.UriDes().Length() );
+	TPtr uriDesPtr( uriDesBuf->Des() );
+	uriDesPtr.Copy( aURI.UriDes() );
+
+	HBufC* uriRealmBuf = HBufC::NewLC( aRealm.DesC().Length() );
+	TPtr uriRealmPtr( uriRealmBuf->Des() );
+	uriRealmPtr.Copy( aRealm.DesC() );
+	
+	HBufC* uriAuthenticationType = HBufC::NewLC ( aAuthenticationType.DesC().Length() );
+	TPtr uriAuthenticationPtr( uriAuthenticationType->Des() );
+	uriAuthenticationPtr.Copy ( aAuthenticationType.DesC() );
+	
+	
+	// Prompt user for input
+	iTestUtils.Test().Printf ( _L( "Enter credentials for URL %S, realm %S\n"), &uriDesPtr, &uriRealmPtr );
+	iTestUtils.Test().Printf ( _L("Using %S authentication\n"), &uriAuthenticationPtr );
+	CleanupStack::PopAndDestroy ( 3 ); // Pop and destroy uriDesBuf, uriRealmBuf and uriAuthenticationType
+	
+	HBufC* userDetails16 = HBufC::NewLC ( KMaxUserEntrySize );
+	HBufC8* userDetails8 = HBufC8::NewLC ( KMaxUserEntrySize );
+	TPtr userDetailsPtr16( userDetails16->Des() );
+	TPtr8 userDetailsPtr8( userDetails8->Des() );
+	
+	iTestUtils.GetAnEntry ( _L( "Username (or QUIT to give up): " ), userDetailsPtr16 );
+	TBool set = EFalse;
+	if ( userDetailsPtr16.CompareF ( KQuit ) )
+		{
+		userDetailsPtr8.Copy ( userDetailsPtr16 );
+		aUsername = aRealm.Pool().OpenStringL ( userDetailsPtr8 );
+		iTestUtils.GetAnEntry( _L( "Password: " ), userDetailsPtr16 );
+		userDetailsPtr8.Copy ( userDetailsPtr16 );
+		aPassword = aRealm.Pool().OpenStringL ( userDetailsPtr8 );
+		set = ETrue;		
+		}
+	CleanupStack::PopAndDestroy ( 2 ); // Pop and destroy userDetails16 & userDetails8
+	return set;	
+	}
+
+/**
+	Create a new transaction. Generate the full uri from a partial uri.
+	Also, generates the file path where the contents to be saved. Adds the transaction
+	object into array.
+	
+	@param aUri [in] URI to download.
+	@param aParseHtml [in] Parse the downloaded HTML content. Default value: EFalse. ETrue value to parse 
+	the HTML content. Typically the value will be set to ETrue only for the main page.
+ */
+void CTestWebBrowser::CreateTransactionL ( const TDesC8& aUri, TBool aParseHtml /* = EFalse */ )
+	{	
+	TUriParser8 baseUri;	
+	baseUri.Parse ( iBaseUri->Des() );
+	
+	TUriParser8 refUri;
+	refUri.Parse ( aUri );
+
+	// Resolve uri
+	CUri8* uriPtr = CUri8::ResolveL( baseUri, refUri );	
+	CleanupStack::PushL ( uriPtr );
+	
+	// Generate the file path from the full http uri.	
+	HBufC* filePath = GenerateFilePathL ( uriPtr->Uri() );
+	CleanupStack::PushL ( filePath );
+	
+	// Create a new HTTP transaction object.
+	CBrowserTransaction* newTrans = CBrowserTransaction::NewL ( iHttpSession, iTestUtils, this, *filePath, aParseHtml );
+	CleanupStack::PopAndDestroy ( filePath );
+	CleanupStack::PushL ( newTrans );
+	iTransArray.AppendL ( newTrans );
+	
+	// Open and submit the transaction.
+	newTrans->CreateTransactionL ( uriPtr->Uri().UriDes() );
+	newTrans->StartTransactionL ();
+	
+	CleanupStack::Pop ( newTrans ); 
+	CleanupStack::PopAndDestroy ( uriPtr );
+	return;		
+	}
+
+/**
+	To create a new transaction. This function is a calllback called from 
+	the CHTMLHandler when it finds a new URI to be downloaded.
+	
+	@param aUri [in] URI to download.
+ */	
+void CTestWebBrowser::OnTransactionCreateL ( const TDesC8& aUri, TBool aParseHtml )
+	{
+	CreateTransactionL ( aUri, aParseHtml );
+	return;		
+	}
+
+/**
+	Delete the transaction. Removes the transaction object from the transaction array
+	
+	@param aTrans [out] Transaction object to close.
+ */	
+void CTestWebBrowser::OnTransactionClose ( CBrowserTransaction* aTrans ) 
+	{	
+	// Find the transaction object to be deleted and remove it from the 
+	// transaction	array.
+	TInt numTrans = iTransArray.Count ();
+	for ( TInt i = 0; i < numTrans; ++i )
+		{
+		if ( iTransArray[ i ] == aTrans )			
+			{
+			delete aTrans;
+			iTransArray.Remove ( i );
+			break;
+			}
+		}	
+	
+	if ( iTransArray.Count () == 0 )
+		{
+		// All transactions are completed. 
+		iCurrentState = ETransactionCompleted;
+		IssueAndCompleteRequest ();
+		}
+	return;		
+	}
+
+/**
+	Issues a new request if the active object has no outstanding request.
+	
+ */	
+void CTestWebBrowser::IssueAndCompleteRequest()
+	{
+	if ( !IsActive() )		
+		{
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete( status, KErrNone );
+		SetActive();
+		}
+	}
+	
+void CTestWebBrowser::RunL ()
+	{
+	
+	switch ( iCurrentState )
+		{
+		case EMainMenu:
+			iTestUtils.Test().Printf ( _L ( "Main menu") );
+			ExecuteMainMenuL();
+			break;
+		
+		case EEnterUrl:
+			AcceptUrlL ();
+			break;
+		
+		case ESelectProxy:
+			AcceptProxyL ();
+			break;
+		
+		case EStop:		
+			CActiveScheduler::Stop();
+			break;
+		
+		case EStartTransaction:
+			{		
+			CreateTransactionL ( iBaseUri->Des(), ETrue );	
+			}
+			break;
+		
+		case ETransactionStarted:
+			{
+			iTestUtils.Test().Printf ( _L ( "Transaction started. Please wait...") );			
+			}
+			break;
+		
+		case ETransactionCompleted:
+			{
+			OnTransactionCompleted();
+			}
+			break;				
+			
+		default:
+			break;
+		}
+	}
+
+void CTestWebBrowser::DoCancel ()
+	{
+	// Do nothing...		
+	}
+
+/**
+	Checks whether a uri is valid or not. Will check whether the uri contains
+	scheme, host and path.
+	
+	@param aUri [in] URI to validate. Only scheme and host presence is validated.
+	
+	@return TBool ETrue if the URI is successfully validated else EFalse.
+ */	
+TBool CTestWebBrowser::ValidateUri ( const TDesC8& aUri )
+	{
+	TUriParser8 uriParser;
+	if ( uriParser.Parse ( aUri ) != KErrNone )
+		{
+		return EFalse;			
+		}
+	
+	// check for scheme
+	if ( !uriParser.IsPresent ( EUriScheme ) )
+		{
+		return EFalse;				
+		}
+	
+	// check for host
+	if ( !uriParser.IsPresent ( EUriHost) )
+		{
+		return EFalse;			
+		}
+	return ETrue;				
+	}
+
+/**
+	Generate the full file path based on the aUri.
+	
+	@param aUri [in] Full URI to generate the full file path.
+	
+	@return HBufC* Holds the full file path.
+ */	
+HBufC* CTestWebBrowser::GenerateFilePathL ( const TUriC8& aUri )
+	{
+	
+	HBufC* filePath = HBufC::NewLC ( KMaxFilePathLength );	
+	TPtr filePtr ( filePath->Des() );	
+	
+	// Append the base path
+	filePtr.Append ( KDirPath ); 
+	
+	// Get the full uri.
+	HBufC* completeUri = aUri.DisplayFormL();
+	CleanupStack::PushL ( completeUri );
+	
+	TPtr ptr = completeUri->Des();
+	// Chop off the scheme. ( http:// )
+	ptr.Delete ( 0, KHttpSchemeLength );
+	
+	// Reverse the slashes.
+	ChangePathSeparator ( ptr, '/', '\\' );
+	
+	// Replace invalid characters with '_'. Invalid characters: <>:"|* 	
+	TPtrC ptrInvalidChars ( KInvalidChars );
+	for ( TInt i = 0; i < KInvalidChars().Length(); ++i )
+		{
+		ChangePathSeparator ( ptr, ptrInvalidChars[i], KReplaceChar );					
+		}
+	
+	// Append the URI file path.	
+	filePtr.Append ( ptr );		
+	CleanupStack::PopAndDestroy ( completeUri );
+	
+	HBufC* uriTail = aUri.GetFileNameL ( EUriFileNameTail );
+	CleanupStack::PushL ( uriTail );	
+	
+	TBool fileExtPresent = uriTail->Des().Length() != 0;
+	
+	CleanupStack::PopAndDestroy ( uriTail );
+			
+	// Append a '\\' at the end of the completeUri if not present.
+	TInt len = filePtr.Length();
+	
+	if ( ( !fileExtPresent ) && ( len != 0 ) && ( filePtr[ len-1 ] != '\\') )
+		{
+		filePtr.Append ( '\\' );		
+		}
+
+	if ( !fileExtPresent )
+		{
+		// No file name present in the uri. Set the file name as index.html.		
+		filePtr.Append ( KDefaultFilePath() );
+		}	
+
+	CleanupStack::Pop ( filePath );
+	iTestUtils.LogIt ( _L("File Path: %S"), &filePtr );
+	return filePath;
+	}
+		
+void CTestWebBrowser::ExecuteMainMenuL ()
+	{
+	iTestUtils.Test().Console()->ClearScreen ();
+
+	iTestUtils.Test().Printf(KSelectOption);		
+	
+	
+	TInt selection = iTestUtils.GetSelection ( KPossibleSelectionsText, KPossibleSelections );	
+	
+	switch ( selection )
+		{
+		case EDownloadURL:
+		iCurrentState = EEnterUrl;
+		break;
+		
+		case ESetProxy:
+		iCurrentState = ESelectProxy;
+		break;
+		
+		case EQuit:
+		iCurrentState = EStop;
+		break;
+		
+		default:
+		break;
+		}
+		
+	IssueAndCompleteRequest ();
+	}
+
+/**
+	Accept the url from the user and validate.
+ */	
+void CTestWebBrowser::AcceptUrlL ()
+	{
+
+	HBufC* uri = HBufC::NewLC ( KMaxURISize );
+	TPtr ptr( uri->Des() );
+	iTestUtils.GetAnEntry ( KEnterUrl, ptr );
+	if ( iBaseUri->Des().MaxLength() < ptr.Length() )
+		{
+		iBaseUri = 	iBaseUri->ReAllocL ( ptr.Length() );
+		}
+		
+	iBaseUri->Des().Copy ( ptr );
+	
+	if ( ValidateUri( iBaseUri->Des() ) )
+		{
+		iCurrentState = EStartTransaction;
+		}
+	else
+		{
+		iTestUtils.Test().Printf ( _L("Invalid entry.") );
+		iTestUtils.PressAnyKey ();			
+		iCurrentState = EMainMenu;
+		}	
+	CleanupStack::PopAndDestroy ( uri );
+	
+	IssueAndCompleteRequest ();		
+	}
+
+/**
+	Accept proxy information from the user.
+ */	
+void CTestWebBrowser::AcceptProxyL ()
+	{	
+	HBufC* proxy16 = HBufC::NewLC ( 128 )		;
+	TPtr ptr( proxy16->Des() );
+	iTestUtils.GetAnEntry ( KEnterProxy, ptr );
+	
+	HBufC8* proxy8 = HBufC8::NewLC ( ptr.Length() );
+	proxy8->Des().Copy ( ptr );
+	
+	TRAPD ( err, SetProxyL ( proxy8->Des() ) );	
+	
+	if ( err != KErrNone )
+		{
+		iTestUtils.Test().Printf ( _L ( "Setting of proxy address failed." ) );
+		}
+	
+	iCurrentState = EMainMenu;
+	IssueAndCompleteRequest ();
+	}
+
+/**
+	Set the state to EMainMenu and issues a request to be processed by the RunL.	
+ */	
+void CTestWebBrowser::OnTransactionCompleted ()
+	{
+	iTestUtils.Test().Printf ( _L ("Transaction completed.") );
+	iTestUtils.PressAnyKey();
+	iCurrentState = EMainMenu;			
+	IssueAndCompleteRequest ();
+	}
+
+