S60 3rd Edition SDK for Symbian OS
Example Applications Guide

WebClientEngine.cpp

00001 /*
00002 * ==============================================================================
00003 *  Name        : WebClientEngine.cpp
00004 *  Part of     : WebClient
00005 *  Interface   : 
00006 *  Description : 
00007 *  Version     : 
00008 *
00009 *  Copyright (c) 2005-2006 Nokia Corporation.
00010 *  This material, including documentation and any related 
00011 *  computer programs, is protected by copyright controlled by 
00012 *  Nokia Corporation.
00013 * ==============================================================================
00014 */
00015 
00016 // INCLUDE FILES
00017 #include <avkon.hrh>
00018 #include <aknnotewrappers.h>
00019 #include <stringloader.h>
00020 #include <http.h>
00021 #include <WebClient.rsg>
00022 #include "WebClient.pan"
00023 #include "WebClient.hrh"
00024 #include "WebClientEngine.h"
00025 #include "WebClientAppUi.h"
00026 
00027 // ----------------------------------------------------------------------------
00028 // CWebClientEngine::NewL()
00029 // Creates instance of CWebClientEngine.
00030 // ----------------------------------------------------------------------------
00031 //
00032 CWebClientEngine* CWebClientEngine::NewL( MWebClientObserver& aObserver )
00033     {
00034     CWebClientEngine* self = CWebClientEngine::NewLC( aObserver );
00035     CleanupStack::Pop( self );
00036     return self;
00037     }
00038 
00039 
00040 // ----------------------------------------------------------------------------
00041 // CWebClientEngine::NewLC()
00042 // Creates instance of CWebClientEngine.
00043 // ----------------------------------------------------------------------------
00044 //
00045 CWebClientEngine* CWebClientEngine::NewLC( MWebClientObserver& aObserver )
00046     {
00047     CWebClientEngine* self = new (ELeave) CWebClientEngine( aObserver );
00048     CleanupStack::PushL( self );
00049     self->ConstructL();
00050     return self;
00051     }
00052 
00053 
00054 // ----------------------------------------------------------------------------
00055 // CWebClientEngine::CWebClientEngine()
00056 // First phase constructor.
00057 // ----------------------------------------------------------------------------
00058 //
00059 CWebClientEngine::CWebClientEngine( MWebClientObserver& aObserver )
00060 :    iObserver( aObserver ),
00061      iRunning( EFalse ),
00062      iApplicationUi( NULL )
00063     {
00064     // no implementation required
00065     }
00066 
00067 
00068 // ----------------------------------------------------------------------------
00069 // CWebClientEngine::~CWebClientEngine()
00070 // Destructor.
00071 // ----------------------------------------------------------------------------
00072 //
00073 CWebClientEngine::~CWebClientEngine()
00074     {
00075     iSession.Close();
00076     iApplicationUi = NULL;
00077     }
00078 
00079 
00080 // ----------------------------------------------------------------------------
00081 // CWebClientEngine::ConstructL()
00082 // Second phase construction.
00083 // ----------------------------------------------------------------------------
00084 //
00085 void CWebClientEngine::ConstructL()
00086     {
00087     // Open RHTTPSession with default protocol ("HTTP/TCP")
00088     TRAPD( err, iSession.OpenL() );
00089     if( err != KErrNone ) {
00090         // Most common error; no access point configured, and session creation
00091         // leaves with KErrNotFound.
00092         // Load a string from the resource file and add the error code to string
00093         HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_IAP_CONF_ERR, err );
00094         CAknErrorNote* errorNote;
00095         errorNote = new (ELeave) CAknErrorNote;
00096         // Show the error Note with textResource loaded with StringLoader.
00097         errorNote->ExecuteLD( *textResource);
00098         // Pop HBuf from CleanUpStack and Destroy it.
00099         CleanupStack::PopAndDestroy( textResource );
00100         User::Leave( err );
00101     }
00102 
00103     // Install this class as the callback for authentication requests. When 
00104     // page requires authentication the framework calls GetCredentialsL to get 
00105     // user name and password.
00106     InstallAuthenticationL( iSession );
00107     }
00108 
00109 
00110 // ----------------------------------------------------------------------------
00111 // CWebClientEngine::SetHeaderL()
00112 // Used to set header value to HTTP request
00113 // ----------------------------------------------------------------------------
00114 //
00115 void CWebClientEngine::SetHeaderL( RHTTPHeaders aHeaders, 
00116                                    TInt aHdrField, 
00117                                    const TDesC8& aHdrValue )
00118     {
00119     RStringF valStr = iSession.StringPool().OpenFStringL( aHdrValue );
00120     CleanupClosePushL( valStr );
00121     THTTPHdrVal val( valStr );
00122     aHeaders.SetFieldL( iSession.StringPool().StringF( aHdrField,
00123         RHTTPSession::GetTable() ), val );
00124     CleanupStack::PopAndDestroy( &valStr );
00125     }
00126 
00127 // ----------------------------------------------------------------------------
00128 // CWebClientEngine::DumpRespHeadersL(RHTTPTransaction& aTransaction)
00129 // Used to display HTTP header field names and values
00130 // ----------------------------------------------------------------------------
00131 //
00132 void CWebClientEngine::DumpRespHeadersL( RHTTPTransaction& aTransaction )
00133     {
00134     RHTTPResponse resp = aTransaction.Response();
00135     RStringPool strP = aTransaction.Session().StringPool();
00136     RHTTPHeaders hdr = resp.GetHeaderCollection();
00137     THTTPHdrFieldIter it = hdr.Fields();
00138 
00139     HBufC* headerField = HBufC::NewLC( KMaxHeaderNameLength + KMaxHeaderValueLength );
00140     HBufC* fieldValBuf = HBufC::NewLC( KMaxHeaderValueLength );
00141 
00142     while ( it.AtEnd() == EFalse )
00143         {
00144         RStringTokenF fieldName = it();
00145         RStringF fieldNameStr = strP.StringF( fieldName );
00146         THTTPHdrVal fieldVal;
00147         if ( hdr.GetField( fieldNameStr, 0, fieldVal ) == KErrNone )
00148             {
00149             const TDesC8& fieldNameDesC = fieldNameStr.DesC();
00150             headerField->Des().Copy( fieldNameDesC.Left( KMaxHeaderNameLength ));
00151             fieldValBuf->Des().Zero();
00152             switch ( fieldVal.Type() )
00153                 {
00154             // the value is an integer
00155             case THTTPHdrVal::KTIntVal:
00156                 fieldValBuf->Des().Num( fieldVal.Int() );
00157                 break;
00158             // the value is a case-insensitive string
00159             case THTTPHdrVal::KStrFVal:
00160                 {
00161                 RStringF fieldValStr = strP.StringF( fieldVal.StrF() );
00162                 const TDesC8& fieldValDesC = fieldValStr.DesC();
00163                 fieldValBuf->Des().Copy( fieldValDesC.Left(KMaxHeaderValueLength ));
00164                 }
00165                 break;
00166             // the value is a case-sensitive string
00167             case THTTPHdrVal::KStrVal:
00168                 {
00169                 RString fieldValStr = strP.String( fieldVal.Str() );
00170                 const TDesC8& fieldValDesC = fieldValStr.DesC();
00171                 fieldValBuf->Des().Copy( fieldValDesC.Left(KMaxHeaderValueLength) );
00172                 }
00173                 break;
00174             // the value is a date/time
00175             case THTTPHdrVal::KDateVal:
00176                 {
00177                 TDateTime date = fieldVal.DateTime();
00178                 TBuf<KMaxDateTimeStringLength> dateTimeString;
00179                 TTime t( date );
00180                 t.FormatL( dateTimeString,KDateFormat );
00181                 fieldValBuf->Des().Copy( dateTimeString );
00182                 } 
00183                 break;
00184             // the value is type is unknown
00185             default:
00186                 break;
00187                 }
00188 
00189             // Display HTTP header field name and value
00190             headerField->Des().Append( KColon );
00191             headerField->Des().Append( *fieldValBuf );
00192             iObserver.ClientHeaderReceived( *headerField );
00193             
00194             // Display realm for WWW-Authenticate header
00195             RStringF wwwAuth = strP.StringF( HTTP::EWWWAuthenticate,RHTTPSession::GetTable() );
00196             if ( fieldNameStr == wwwAuth )
00197                 {
00198                 // check the auth scheme is 'basic'
00199                 RStringF basic = strP.StringF( HTTP::EBasic,RHTTPSession::GetTable() );
00200                 RStringF realm = strP.StringF( HTTP::ERealm,RHTTPSession::GetTable() );
00201                 THTTPHdrVal realmVal;
00202                 if (( fieldVal.StrF() == basic ) && 
00203                     ( !hdr.GetParam( wwwAuth, realm, realmVal )))
00204                     {
00205                     RStringF realmValStr = strP.StringF( realmVal.StrF() );
00206                     fieldValBuf->Des().Copy( realmValStr.DesC() );
00207                     headerField->Des().Copy( Krealm );
00208                     headerField->Des().Append( *fieldValBuf );
00209                     iObserver.ClientHeaderReceived( *headerField );
00210                     }
00211                 }
00212             }
00213         ++it;
00214         }
00215         CleanupStack::PopAndDestroy( fieldValBuf );
00216         CleanupStack::PopAndDestroy( headerField );
00217     }
00218 
00219 // ----------------------------------------------------------------------------
00220 // CWebClientEngine::HandleRunErrorL()
00221 // Called from MHFRunError() when *leave* occurs in handling of transaction event.
00222 // ----------------------------------------------------------------------------
00223 //
00224 void CWebClientEngine::HandleRunErrorL( TInt aError )
00225     {
00226     // Load a string from the resource file and add the leave code to string
00227     HBufC* textResource = StringLoader::LoadL( R_WEBCLIENT_MHFRUN_ERROR, aError );
00228     // Notify about the error
00229     iObserver.ClientEvent( *textResource );
00230     CleanupStack ::PopAndDestroy( textResource );
00231     if ( iApplicationUi )
00232         iApplicationUi->RemoveWaitDialogL();
00233     }
00234 
00235 // ----------------------------------------------------------------------------
00236 // CWebClientEngine::IssueHTTPGetL()
00237 // Start a new HTTP GET transaction.
00238 // ----------------------------------------------------------------------------
00239 //
00240 void CWebClientEngine::IssueHTTPGetL( const TDesC8& aUri )
00241     {
00242     // Parse string to URI (as defined in RFC2396)
00243     TUriParser8 uri;
00244     uri.Parse( aUri );
00245 
00246     // Get request method string for HTTP GET
00247     RStringF method = iSession.StringPool().StringF( HTTP::EGET,
00248         RHTTPSession::GetTable());
00249 
00250     // Open transaction with previous method and parsed uri. This class will
00251     // receive transaction events in MHFRunL and MHFRunError.
00252     iTransaction = iSession.OpenTransactionL( uri, *this, method );
00253 
00254     // Set headers for request; user agent and accepted content type
00255     RHTTPHeaders hdr = iTransaction.Request().GetHeaderCollection();
00256     SetHeaderL( hdr, HTTP::EUserAgent, KUserAgent );
00257     SetHeaderL( hdr, HTTP::EAccept, KAccept );
00258 
00259     // Submit the transaction. After this the framework will give transaction
00260     // events via MHFRunL and MHFRunError.
00261     iTransaction.SubmitL();
00262 
00263     iRunning = ETrue;
00264 
00265     // Load a string from the resource file 
00266     HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_CONNECTING );
00267     iObserver.ClientEvent( *textResource );
00268     CleanupStack::PopAndDestroy( textResource );
00269     }
00270 
00271 
00272 // ----------------------------------------------------------------------------
00273 // CWebClientEngine::CancelTransactionL()
00274 // Cancels currently running transaction and frees resources related to it.
00275 // ----------------------------------------------------------------------------
00276 //
00277 void CWebClientEngine::CancelTransactionL()
00278     {
00279     if( !iRunning ) 
00280         return;
00281 
00282     // Close() also cancels transaction (Cancel() can also be used but 
00283     // resources allocated by transaction must be still freed with Close())
00284     iTransaction.Close();
00285 
00286     // Not running anymore
00287     iRunning = EFalse;
00288 
00289     // Load a string from the resource file 
00290     HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_TRANSACTION_CANCEL );
00291     iObserver.ClientEvent( *textResource );
00292     CleanupStack::PopAndDestroy( textResource );
00293     }
00294 
00295 // ----------------------------------------------------------------------------
00296 // CWebClientEngine::SetCallBack()
00297 // Set pointer to CApplicationUi instance
00298 // ----------------------------------------------------------------------------
00299 //
00300 void CWebClientEngine::SetCallBack( CWebClientAppUi* aCallBack )
00301     {
00302     iApplicationUi = aCallBack;
00303     }
00304 
00305 // ----------------------------------------------------------------------------
00306 // CWebClientEngine::MHFRunL()
00307 // Inherited from MHTTPTransactionCallback
00308 // Called by framework to pass transaction events.
00309 // ----------------------------------------------------------------------------
00310 //
00311 void CWebClientEngine::MHFRunL( RHTTPTransaction aTransaction, 
00312                                 const THTTPEvent& aEvent )
00313     {
00314 
00315     switch ( aEvent.iStatus ) 
00316         {
00317         case THTTPEvent::EGotResponseHeaders:
00318             {
00319             // HTTP response headers have been received. Use
00320             // aTransaction.Response() to get the response. However, it's not
00321             // necessary to do anything with the response when this event occurs.
00322 
00323             // Get HTTP status code from header (e.g. 200)
00324             RHTTPResponse resp = aTransaction.Response();
00325             TInt status = resp.StatusCode();
00326 
00327             // Get status text (e.g. "OK")
00328             TBuf<KMaxStatusTextLength> statusText;
00329             statusText.Copy( resp.StatusText().DesC() );
00330 
00331             // Load a string from the resource file and add status and status text
00332             HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_HEADER_RECEIVED,
00333                                                         statusText, status );
00334             iObserver.ClientEvent( *textResource );
00335             CleanupStack::PopAndDestroy( textResource );
00336 
00337             // Display header field names and value
00338             DumpRespHeadersL( aTransaction );
00339 
00340             }
00341             break;
00342 
00343         case THTTPEvent::EGotResponseBodyData:
00344             {
00345             // Part (or all) of response's body data received. Use 
00346             // aTransaction.Response().Body()->GetNextDataPart() to get the actual
00347             // body data.
00348 
00349             // Get the body data supplier
00350             MHTTPDataSupplier* body = aTransaction.Response().Body();
00351             TPtrC8 dataChunk;
00352 
00353             // GetNextDataPart() returns ETrue, if the received part is the last 
00354             // one.
00355             TBool isLast = body->GetNextDataPart( dataChunk );
00356             iObserver.ClientBodyReceived( dataChunk );
00357 
00358             // Load a string from the resource file and add data length to string
00359             HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_BODY_PART_RECEIVED,
00360                                                         dataChunk.Length() );
00361             iObserver.ClientEvent( *textResource );
00362             CleanupStack::PopAndDestroy( textResource );
00363         
00364             // NOTE: isLast may not be ETrue even if last data part received.
00365             // (e.g. multipart response without content length field)
00366             // Use EResponseComplete to reliably determine when body is completely
00367             // received.
00368             if (isLast)
00369                 {
00370                 HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_BODY_RECEIVED );
00371                 iObserver.ClientEvent( *textResource );
00372                 CleanupStack::PopAndDestroy( textResource );
00373                 }
00374 
00375             // Always remember to release the body data.
00376             body->ReleaseData();
00377             }
00378             break;
00379 
00380         case THTTPEvent::EResponseComplete:
00381             {
00382             // Indicates that header & body of response is completely received.
00383             // No further action here needed.
00384             HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_TRANSACTION_COMPLETE );
00385             iObserver.ClientEvent( *textResource );
00386             CleanupStack::PopAndDestroy( textResource );
00387             }
00388             break;
00389 
00390         case THTTPEvent::ESucceeded:
00391             {
00392             // Indicates that transaction succeeded. 
00393             HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_TRANSACTION_SUCCEED );
00394             iObserver.ClientEvent( *textResource );
00395             CleanupStack::PopAndDestroy( textResource );
00396             if ( iApplicationUi )
00397                 iApplicationUi->RemoveWaitDialogL();
00398 
00399             // Transaction can be closed now. It's not needed anymore.
00400             aTransaction.Close();
00401             iRunning = EFalse;
00402             }
00403             break;
00404 
00405         case THTTPEvent::EFailed:
00406             {
00407             // Transaction completed with failure. 
00408             HBufC* textResource = StringLoader::LoadLC( R_WEBCLIENT_TRANSACTION_FAILED );
00409             iObserver.ClientEvent( *textResource );
00410             CleanupStack::PopAndDestroy( textResource );
00411             if ( iApplicationUi )
00412                 iApplicationUi->RemoveWaitDialogL();
00413             aTransaction.Close();
00414             iRunning = EFalse;
00415             }
00416             break;
00417 
00418         default:
00419             // There are more events in THTTPEvent, but they are not usually 
00420             // needed. However, event status smaller than zero should be handled 
00421             // correctly since it's error.
00422             {
00423             HBufC* textResource;
00424             if ( aEvent.iStatus < 0 )
00425                 {
00426                 // Load a string from the resource file and add status to string
00427                 textResource = StringLoader::LoadLC( R_WEBCLIENT_TRANSACTION_ERROR,
00428                                                      aEvent.iStatus );
00429                 if ( iApplicationUi )
00430                     iApplicationUi->RemoveWaitDialogL();
00431                 // Just close the transaction on errors
00432                 aTransaction.Close();
00433                 iRunning = EFalse;
00434                 } else {
00435                 // Other events are not errors (e.g. permanent and temporary redirections)
00436                 textResource = StringLoader::LoadLC( R_WEBCLIENT_UNRECOGNISED_EVENT,
00437                                                      aEvent.iStatus );
00438                 }
00439             iObserver.ClientEvent( *textResource );
00440             CleanupStack::PopAndDestroy( textResource );
00441             }
00442             break;
00443         }
00444     }
00445 
00446 // ----------------------------------------------------------------------------
00447 // CWebClientEngine::MHFRunError()
00448 // Inherited from MHTTPTransactionCallback
00449 // Called by framework when *leave* occurs in handling of transaction event.
00450 // These errors must be handled, or otherwise HTTP-CORE 6 panic is thrown.
00451 // ----------------------------------------------------------------------------
00452 //
00453 TInt CWebClientEngine::MHFRunError( TInt aError, 
00454                                     RHTTPTransaction /*aTransaction*/, 
00455                                     const THTTPEvent& /*aEvent*/)
00456     {
00457     // Handle error and return KErrNone.
00458     TRAPD( err, HandleRunErrorL( aError ) );
00459     if( err )
00460         Panic( EClientEngine );
00461     return KErrNone;
00462     }
00463 
00464 // ----------------------------------------------------------------------------
00465 // CWebClientEngine::GetCredentialsL()
00466 //
00467 // Inherited from MHTTPAuthenticationCallback
00468 // Called by framework when we requested authenticated page and framework 
00469 // needs to know username and password.
00470 // ----------------------------------------------------------------------------
00471 TBool CWebClientEngine::GetCredentialsL( const TUriC8& /*aUri*/,
00472                                                RString aRealm, 
00473                                                RStringF /*aAuthenticationType*/,
00474                                                RString& aUsername, 
00475                                                RString& aPassword) 
00476     {
00477     // aURI, aReal and aAuthenticationType are informational only. We only need 
00478     // to set aUsername and aPassword and return ETrue, if aUsername and 
00479     // aPassword are provided by user.
00480 
00481     // Query user name and password
00482     TBuf<KMaxUserNameLength> userName;
00483     TBuf<KMaxPasswordLength> password;
00484     CAknMultiLineDataQueryDialog* dlg = 
00485         CAknMultiLineDataQueryDialog::NewL( userName, password );
00486 
00487     if ( !dlg->ExecuteLD( R_WEBCLIENT_DIALOG_USER_PASSWORD_QUERY ))
00488         return EFalse; // No credentials given; must return EFalse
00489 
00490     // Set aUsername and aPassword
00491     TBuf8<KMaxUserNameLength> temp;
00492     temp.Copy( userName );
00493     TRAPD( err, aUsername = aRealm.Pool().OpenStringL( temp ));
00494     if ( !err ) 
00495         {
00496         temp.Copy( password );
00497         TRAP( err, aPassword = aRealm.Pool().OpenStringL( temp ));
00498         if ( !err ) return ETrue;
00499         }
00500 
00501     // Return ETrue if user has given credentials (username and password), 
00502     // otherwise EFlase
00503     return EFalse;
00504     }
00505 

© Nokia 2006

Back to top