webengine/osswebengine/WebCore/platform/network/symbian/HttpConnection.cpp
changeset 0 dd21522fd290
child 13 10e98eab6f85
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  
       
    15 *
       
    16 */
       
    17 
       
    18 #include <Uri8.h>
       
    19 #include <EscapeUtils.h>
       
    20 #include <http/rhttpheaders.h>
       
    21 #include <http/mhttpdatasupplier.h>
       
    22 #include <thttpfields.h>
       
    23 #include "ResourceHandle.h"
       
    24 #include "ResourceHandleInternal.h"
       
    25 #include "ResourceRequest.h"
       
    26 #include "HttpConnection.h"
       
    27 #include "ResourceHandleManagerSymbian.h"
       
    28 #include "StaticObjectsContainer.h"
       
    29 #include "ResourceLoaderDelegate.h"
       
    30 #include "HttpCacheSupply.h"
       
    31 #include "HttpPostDataSupplier.h"
       
    32 #include <HttpFilterCommonStringsExt.h>
       
    33 #include <BrCtlDefs.h>
       
    34 #include "BrCtl.h"
       
    35 #include "BrCtlSpecialLoadObserver.h"
       
    36 #include "Frame.h"
       
    37 #include "FrameLoader.h"
       
    38 #include "DocumentLoader.h"
       
    39 #include "HttpUiCallbacks.h"
       
    40 #include "HttpRequestHeaderManager.h"
       
    41 #include "HttpConnUtils.h"
       
    42 #include "MultipartContentHandler.h"
       
    43 #include "UnknownContentHandler.h"
       
    44 #include <wtf/Vector.h>
       
    45 
       
    46 _LIT8(KHttps, "https");
       
    47 _LIT8( KAppUid, "Appuid" );
       
    48 
       
    49 using namespace WebCore;
       
    50 
       
    51 DefersData::DefersData(void* ctx, DefersDataCallback callback) : CActive(CActive::EPriorityStandard)
       
    52 {
       
    53     m_ctx = ctx;
       
    54     m_callback = callback;
       
    55     CActiveScheduler::Add(this);
       
    56 }
       
    57 
       
    58 DefersData::~DefersData()
       
    59 {
       
    60     Cancel();
       
    61     delete m_response;
       
    62 
       
    63     Vector<HBufC8*>::const_iterator it = m_bodyParts.begin();
       
    64     Vector<HBufC8*>::const_iterator end = m_bodyParts.end();
       
    65     while (it != end) {
       
    66         HBufC8* buf = m_bodyParts.first();
       
    67         m_bodyParts.remove(0);
       
    68         delete buf;
       
    69         it = m_bodyParts.begin();
       
    70         end = m_bodyParts.end();
       
    71     }
       
    72 }
       
    73 
       
    74 void DefersData::RunL()
       
    75 {
       
    76     m_callback(m_ctx);
       
    77 }
       
    78 
       
    79 TInt DefersData::RunError(TInt aError)
       
    80 {
       
    81     return KErrNone;
       
    82 }
       
    83 
       
    84 void DefersData::Activate()
       
    85 {
       
    86     SetActive();
       
    87     iStatus = KRequestPending;
       
    88     TRequestStatus* status = &iStatus;
       
    89     User::RequestComplete( status, KErrNone );
       
    90 }
       
    91 
       
    92 
       
    93 ReceivedFinished::ReceivedFinished(void* ctx, ReceivedFinishedCallback callback) : CActive(CActive::EPriorityStandard)
       
    94 {
       
    95     m_ctx = ctx;
       
    96     m_callback = callback;
       
    97     m_done = true;
       
    98     m_error = KErrNone;
       
    99     CActiveScheduler::Add(this);
       
   100 }
       
   101 
       
   102 ReceivedFinished::~ReceivedFinished()
       
   103 {
       
   104     Cancel();
       
   105 }
       
   106 
       
   107 void ReceivedFinished::RunL()
       
   108 {
       
   109     m_callback(m_ctx, m_error);
       
   110     m_done = true;
       
   111 }
       
   112 
       
   113 TInt ReceivedFinished::RunError(TInt aError)
       
   114 {
       
   115     return KErrNone;
       
   116 }
       
   117 
       
   118 void ReceivedFinished::Activate(TInt errorCode)
       
   119 {
       
   120     m_done = false;
       
   121     m_error = errorCode;
       
   122     SetActive();
       
   123     iStatus = KRequestPending;
       
   124     TRequestStatus* status = &iStatus;
       
   125     User::RequestComplete( status, KErrNone );
       
   126 }
       
   127 
       
   128 void ReceivedFinished::done(bool status)
       
   129 {
       
   130     m_done = status;
       
   131 }
       
   132 
       
   133 HttpConnection::HttpConnection(ResourceHandle* _handle, Frame* _frame) : MUrlConnection(_handle)
       
   134 {
       
   135     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   136     httpSessionMgr->addRequest(this, m_handle);
       
   137     m_frag = NULL;
       
   138     m_transaction = NULL;
       
   139     m_urlResponse = NULL;
       
   140     m_contentType = NULL;
       
   141     m_encoding = NULL;
       
   142     m_cacheSupply = NULL;
       
   143     m_postDataSupplier = NULL;
       
   144     m_maxSize = 0;
       
   145     m_frame = _frame;
       
   146     m_IsMultipart = false;
       
   147     m_isDone = false;
       
   148     m_certInfo = NULL;
       
   149     m_accumulatedSize = 0;
       
   150     m_defersData = NULL; // requests will not be propagated if loading is blocked
       
   151     m_receivedFinished = NULL;
       
   152     m_unknownContentHandler = NULL;
       
   153 }
       
   154 
       
   155 HttpConnection::~HttpConnection()
       
   156 {
       
   157     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   158     if (m_transaction) {
       
   159         RHTTPSession& session = httpSessionMgr->httpSession();
       
   160         // remove own address from transaction properties
       
   161         m_transaction->PropertySet().RemoveProperty( session.StringPool().StringF(HttpFilterCommonStringsExt::ESelfPtr,
       
   162             HttpFilterCommonStringsExt::GetTable()));
       
   163     }
       
   164     httpSessionMgr->removeRequest(this);
       
   165     delete m_frag;
       
   166     delete m_urlResponse;
       
   167     delete m_contentType;
       
   168     delete m_encoding;
       
   169     delete m_defersData;
       
   170     delete m_receivedFinished;
       
   171     delete m_unknownContentHandler;
       
   172     delete m_cacheSupply;
       
   173     delete m_postDataSupplier;
       
   174     delete m_transaction;
       
   175 }
       
   176 
       
   177 HttpConnection* HttpConnection::connectionFromTransaction(RHTTPTransaction& transaction)
       
   178 {
       
   179     RHTTPTransactionPropertySet propSet = transaction.PropertySet();
       
   180     THTTPHdrVal propRetVal;
       
   181     // Get the name of the property
       
   182     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   183     RHTTPSession& session = httpSessionMgr->httpSession();
       
   184     RStringF propName = session.StringPool().StringF( HttpFilterCommonStringsExt::ESelfPtr, HttpFilterCommonStringsExt::GetTable() );
       
   185     // if it is set . .
       
   186     if( propSet.Property( propName, propRetVal ) ){
       
   187         return (HttpConnection*)(TInt(propRetVal));
       
   188     }
       
   189     return NULL;
       
   190 }
       
   191 
       
   192 int HttpConnection::submit()
       
   193 {
       
   194     TRAPD(error, submitL());
       
   195     return error;
       
   196 }
       
   197 
       
   198 void HttpConnection::submitL()
       
   199 {
       
   200     __ASSERT_DEBUG( !m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
   201 
       
   202     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   203     User::LeaveIfNull(httpSessionMgr);
       
   204     httpSessionMgr->openHttpSessionIfNeededL();
       
   205     TPtrC8 urlPtr( m_handle->request().url().des() );
       
   206     m_transaction = new (ELeave) RHTTPTransaction;
       
   207     RHTTPSession& session = httpSessionMgr->httpSession();
       
   208     RStringPool stringPool = session.StringPool();
       
   209     const TStringTable& stringTable = RHTTPSession::GetTable();
       
   210     TUriParser8 uriParser;
       
   211     uriParser.Parse(urlPtr);
       
   212     // fragment
       
   213     if(uriParser.IsPresent(EUriFragment)) {
       
   214         m_frag = uriParser.Extract(EUriFragment).AllocL();
       
   215         // url without frag
       
   216         uriParser.UriWithoutFragment(urlPtr);
       
   217         // and reparse url
       
   218         uriParser.Parse(urlPtr);
       
   219         }
       
   220 
       
   221     // open transaction
       
   222     RStringF method;
       
   223     if (m_handle->request().httpMethod() == "GET") {
       
   224         method = stringPool.StringF( HTTP::EGET, stringTable );
       
   225     }
       
   226     else if (m_handle->request().httpMethod() == "POST") {
       
   227         method = stringPool.StringF( HTTP::EPOST, stringTable );
       
   228     }
       
   229     else if (m_handle->request().httpMethod() == "PUT") {
       
   230         method = stringPool.StringF( HTTP::EPUT, stringTable );
       
   231     }
       
   232     else if (m_handle->request().httpMethod() == "DELETE") {
       
   233         method = stringPool.StringF( HTTP::EDELETE, stringTable );
       
   234     }
       
   235     else {
       
   236         User::Leave(KErrArgument);
       
   237     }
       
   238     *m_transaction = session.OpenTransactionL( uriParser, *(httpSessionMgr->transactionCallback()), method );
       
   239     // add transaction attributes such as default headers, cache properties
       
   240     addRequestHeadersL();
       
   241     RHTTPTransactionPropertySet propSet = m_transaction->PropertySet();
       
   242     
       
   243     RStringF appuid = stringPool.OpenFStringL( KAppUid );
       
   244     
       
   245     TUint appuidValue = control(m_frame)->webView()->getWidgetId();
       
   246     if(appuidValue){
       
   247         propSet.SetPropertyL(appuid,THTTPHdrVal(appuidValue));
       
   248     }
       
   249     
       
   250     appuid.Close();
       
   251     // Add IMEI Notify property to the transaction
       
   252     // It is not needed, as it is done in UA-Prof filter
       
   253     // addIMEINotifyPropertiesL();
       
   254 
       
   255     // add http request headers
       
   256     RHTTPHeaders httpHeaders = m_transaction->Request().GetHeaderCollection();
       
   257     httpSessionMgr->requestHeaderManager()->AddAllHeadersL(httpHeaders, m_handle->request());
       
   258     // Create a dataSupplier object to supply the request body to http stack.
       
   259     if ((m_handle->request().httpMethod() == "POST" ||
       
   260         m_handle->request().httpMethod() == "PUT") && m_handle->request().httpBody()){
       
   261         // 2 steps constructor
       
   262         m_postDataSupplier = new(ELeave)HttpPostDataSupplier( m_transaction, control(m_frame));
       
   263         m_postDataSupplier->initL(m_handle->request().httpBody());
       
   264         m_transaction->Request().SetBody( *m_postDataSupplier);
       
   265     }
       
   266     // create cache supplier
       
   267     m_cacheSupply = CHttpCacheSupply::NewL( this );
       
   268     TBrCtlDefs::TBrCtlCacheMode cacheMode;
       
   269     switch (m_handle->request().cachePolicy())
       
   270     {
       
   271     default:
       
   272     case UseProtocolCachePolicy:
       
   273         cacheMode = TBrCtlDefs::ECacheModeNormal;
       
   274         break;
       
   275     case ReloadIgnoringCacheData:
       
   276         cacheMode = TBrCtlDefs::ECacheModeNoCache;
       
   277         break;
       
   278     case ReturnCacheDataElseLoad:
       
   279         cacheMode = TBrCtlDefs::ECacheModeHistory;
       
   280         break;
       
   281     case ReturnCacheDataDontLoad:
       
   282         cacheMode = TBrCtlDefs::ECacheModeOnlyCache;
       
   283         break;
       
   284     };
       
   285 	IsUrlInCacheL(m_transaction->Request().URI().UriDes() );
       
   286     if( m_cacheSupply->StartRequestL( cacheMode ) != KErrNone ) {
       
   287         // check if the response must come from the cache
       
   288         if( cacheMode != TBrCtlDefs::ECacheModeOnlyCache ) {
       
   289             m_transaction->SubmitL();
       
   290         }
       
   291         else {
       
   292             // cache failed
       
   293             complete( KErrGeneral );
       
   294         }
       
   295     }
       
   296 }
       
   297 
       
   298 void HttpConnection::cancel()
       
   299 {
       
   300     complete( KErrCancel );
       
   301 }
       
   302 
       
   303 void HttpConnection::download(WebCore::ResourceHandle* handle,
       
   304                               const WebCore::ResourceRequest& request,
       
   305                               const WebCore::ResourceResponse& response)
       
   306 {
       
   307     StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager()->download(handle,
       
   308         request, response, this);
       
   309 }
       
   310 
       
   311 void HttpConnection::setDefersLoading(bool defers)
       
   312 {
       
   313     if (m_receivedFinished && !m_receivedFinished->isDone()) {
       
   314         // Don't set defer loading when in ReceivedFinished process
       
   315         return;
       
   316     }
       
   317 
       
   318     if (defers) {
       
   319         if (m_defersData) {
       
   320             m_defersData ->Cancel(); // This would happen if we did not finish sending the accumulated content, and a second JavaScript dialog is displayed.
       
   321         } else {
       
   322             m_defersData = new DefersData(this, processDefersData);
       
   323         }
       
   324         if (m_cacheSupply) {
       
   325             m_cacheSupply->PauseSupply();
       
   326         }
       
   327     }
       
   328     else {
       
   329         if (m_defersData) {
       
   330             m_defersData->Activate();
       
   331         }
       
   332         if (m_cacheSupply) {
       
   333             m_cacheSupply->ResumeSupply();
       
   334         }
       
   335     }
       
   336 }
       
   337 
       
   338 void HttpConnection::handleError(int error)
       
   339 {
       
   340     complete(error);
       
   341 }
       
   342 
       
   343 void HttpConnection::MHFRunL(const THTTPEvent &aEvent)
       
   344     {
       
   345     if (m_cancelled) {
       
   346         return;
       
   347         }
       
   348 
       
   349     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
   350 
       
   351     // Using this flag to prevent caching of secure items
       
   352     TBool nonsecure = ETrue;
       
   353     TUriParser8 requestedParser;
       
   354     if(requestedParser.Parse(m_transaction->Request().URI().UriDes()) == KErrNone) {
       
   355         if( requestedParser.Extract( EUriScheme ).Compare(KHttps) == 0 ) {
       
   356             nonsecure = EFalse;
       
   357             }
       
   358         }
       
   359     switch( aEvent.iStatus )
       
   360         {
       
   361         case THTTPEvent::EGotResponseHeaders:
       
   362             {
       
   363             if ( nonsecure ) {
       
   364                 // pass headers to the cache first
       
   365                 TRAP_IGNORE(m_cacheSupply->HeadersReceivedL());
       
   366                 }
       
   367             int httpStatus( m_transaction->Response().StatusCode() );
       
   368             if (httpStatus == KErrCompletion) {
       
   369                 return;
       
   370             }
       
   371 
       
   372             // Add certificate only if https, and top level request
       
   373             if( m_handle->request().mainLoad() ) {
       
   374                 if ( m_transaction->Request().URI().Extract( EUriScheme ).FindF( KHttps ) == 0 && !m_isInCache ) {
       
   375                     m_certInfo = new(ELeave)TCertInfo;
       
   376                     m_transaction->ServerCert( *m_certInfo );
       
   377                     }
       
   378                 // certinfo will be set/overwritten only if top load request
       
   379                 control(m_frame)->setCertInfo( m_certInfo );
       
   380             }
       
   381 
       
   382             // authentication
       
   383             bool handled( EFalse );
       
   384             //in case of bad Auth Header(aError = -7276), transaction is cancelled already in the filter,
       
   385             //should be passed to Error Handler, otherwise handle Auth request normally.
       
   386             if( ( httpStatus == 401 /*EHttpUnauthorized*/ ) ||
       
   387                 ( httpStatus == 407 /*EHttpProxyAuthenticationRequired*/ ) )
       
   388                 {
       
   389                 // Move the transaction to the Auth queue,
       
   390                 // and wait for Authentication callback
       
   391                 // This is proventing the transaction from being deleted
       
   392                 // in case the network dropped automatically for example
       
   393                 // during the data call connection.
       
   394                 m_transaction->Cancel();
       
   395                 HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   396                 httpSessionMgr->removeRequest(this);
       
   397                 httpSessionMgr->addAuthRequest(this, m_handle);
       
   398                 TInt authRet = handleAuthRequestL( httpStatus );
       
   399                 handled = (authRet == KErrNone);
       
   400                 // trans is cancelled at this point. if
       
   401                 // authentication is failed (not handled) then
       
   402                 // just complete this transaction
       
   403                 if( !handled )
       
   404                     {
       
   405                     //
       
   406                     complete( authRet );
       
   407                     return;
       
   408                     }
       
   409                 }
       
   410             if ( !handled )
       
   411                 {
       
   412                 // url
       
   413                 m_urlResponse = NULL;
       
   414                 if(m_frag) {
       
   415                     m_urlResponse = HBufC8::NewL(m_transaction->Request().URI().UriDes().Length() + m_frag->Length() + 1);
       
   416                     TPtr8 responsePtr(m_urlResponse->Des());
       
   417                     responsePtr.Copy(m_transaction->Request().URI().UriDes());
       
   418                     responsePtr.Append(_L("#"));
       
   419                     responsePtr.Append(*m_frag);
       
   420                 }
       
   421                 else {
       
   422                     m_urlResponse = HBufC8::NewL(m_transaction->Request().URI().UriDes().Length());
       
   423                     m_urlResponse->Des().Copy(m_transaction->Request().URI().UriDes());
       
   424                 }
       
   425                 // content type
       
   426                 THTTPHdrVal hdrVal;
       
   427                 RHTTPHeaders httpHeaders = m_transaction->Response().GetHeaderCollection();
       
   428                 RStringPool stringPool = m_transaction->Session().StringPool();
       
   429                 const TStringTable& stringTable = RHTTPSession::GetTable();
       
   430                 if( httpHeaders.GetField( stringPool.StringF( HTTP::EContentType, stringTable ), 0,
       
   431                     hdrVal) == KErrNone ) {
       
   432                     m_contentType = hdrVal.StrF().DesC().AllocL();
       
   433                 }
       
   434                 else {
       
   435                     m_contentType = KNullDesC8().AllocL();
       
   436                 }
       
   437                 // content encoding
       
   438                 if( httpHeaders.GetParam( stringPool.StringF( HTTP::EContentType, stringTable ),
       
   439                     stringPool.StringF( HTTP::ECharset, stringTable ), hdrVal ) == KErrNone ) {
       
   440                     m_encoding = hdrVal.StrF().DesC().AllocL();
       
   441                 }
       
   442                 else {
       
   443                     m_encoding = KNullDesC8().AllocL();
       
   444                 }
       
   445                 // content length
       
   446                 if( httpHeaders.GetField( stringPool.StringF( HTTP::EContentLength,
       
   447                     stringTable ), 0, hdrVal ) == KErrNone ) {
       
   448                     m_maxSize = hdrVal.Int();
       
   449                 }
       
   450                 String encoding;
       
   451                 if (m_encoding && m_encoding->Length()) {
       
   452                     encoding = m_encoding->Des();
       
   453                 }
       
   454                 ResourceResponse response(m_urlResponse->Des(), m_contentType->Des(), m_maxSize, encoding, String() );
       
   455                 response.setHTTPStatusCode(m_transaction->Response().StatusCode());
       
   456                 //HTTP status text
       
   457                 response.setHTTPStatusText(((m_transaction->Response()).StatusText().DesC()));
       
   458                 
       
   459                 if (m_contentType && m_contentType->Length()) {
       
   460                     response.setHTTPHeaderField("Content-Type", *m_contentType);
       
   461                 }
       
   462 		
       
   463 				TPtrC8 result;
       
   464 
       
   465                 if( httpHeaders.GetRawField( stringPool.StringF( HTTP::EContentDisposition, stringTable ), result) == KErrNone )
       
   466                 	response.setHTTPHeaderField("Content-Disposition", result);
       
   467 
       
   468                 if (m_handle->request().mainLoad()) {
       
   469                     if(m_handle->request().url() != response.url()) {
       
   470                         // Relative URLs are resolved based on the request URL, not response URL.
       
   471                         // If a redirect happens, the request URL must be updated.
       
   472                         m_handle->getInternal()->m_request.setURL(response.url());
       
   473                         m_frame->loader()->activeDocumentLoader()->request().setURL(response.url());
       
   474                     }
       
   475                     if(MultipartContentHandler::IsSupported(response)) {
       
   476                         m_IsMultipart = true;
       
   477                         m_MultipartContentHandler = MultipartContentHandler::NewL();
       
   478                         m_MultipartContentHandler->HandleResponseHeadersL(response, *m_transaction);
       
   479                         return;
       
   480                     }
       
   481                     if (UnknownContentHandler::isUnknownContent(response)) {
       
   482                         m_unknownContentHandler = UnknownContentHandler::NewL(this, response);
       
   483                         return;
       
   484                     }
       
   485                 }
       
   486                 // If loading is defered, don't send the headers now
       
   487                 if (m_defersData) {
       
   488                     ResourceResponse* resp = new ResourceResponse(m_urlResponse->Des(), m_contentType->Des(), m_maxSize, encoding, String());
       
   489                     if (resp == NULL) {
       
   490                         complete(KErrNoMemory);
       
   491                     }
       
   492                     else {
       
   493                         m_defersData->m_response = resp;
       
   494                     }
       
   495                 }
       
   496                 else {
       
   497                     CResourceHandleManager::self()->receivedResponse(m_handle, response, this);
       
   498                 }
       
   499                 // transaction is complete (must have been cancelled in receivedResponse call
       
   500                 if (m_isDone)
       
   501                     return;
       
   502                 // transaction is taken, we need to cleanup this resource.
       
   503                 if (!m_transaction) {
       
   504                     derefHandle();
       
   505                     // this object might be invalid at this point
       
   506                     return;
       
   507                     }
       
   508                 }
       
   509             break;
       
   510         }
       
   511         case THTTPEvent::EGotResponseBodyData:
       
   512             {
       
   513             if ( nonsecure ) {
       
   514                 // pass chunk to the cache first
       
   515                 TRAP_IGNORE( m_cacheSupply->BodyReceivedL() );
       
   516                 }
       
   517             MHTTPDataSupplier* body = m_transaction->Response().Body();
       
   518             // get it from the transaction
       
   519             TPtrC8 chunkPtr;
       
   520             body->GetNextDataPart( chunkPtr );
       
   521             m_accumulatedSize += chunkPtr.Length();
       
   522 
       
   523             if (chunkPtr.Length()) {
       
   524                 if(m_IsMultipart) {
       
   525                     m_MultipartContentHandler->HandleResponseBodyL(chunkPtr);
       
   526                 } else {
       
   527                     if (m_unknownContentHandler) {
       
   528                         m_unknownContentHandler->updateContentTypeL(chunkPtr);
       
   529                         if (m_defersData) {
       
   530                             m_defersData ->m_response = m_unknownContentHandler->handOffResponse();
       
   531                         }
       
   532                         else {
       
   533                             ResourceResponse* response = m_unknownContentHandler->handOffResponse();
       
   534                             CResourceHandleManager::self()->receivedResponse(m_handle, *response, this);
       
   535                             delete response;
       
   536                             // transaction is complete (must have been cancelled in receivedResponse call
       
   537                             if (m_isDone)
       
   538                                 return;
       
   539                             // transaction is taken, we need to cleanup this resource.
       
   540                             if (!m_transaction) {
       
   541                                 derefHandle();
       
   542                                 // this object might be invalid at this point
       
   543                                 return;
       
   544                             }
       
   545                         }
       
   546                         delete m_unknownContentHandler;
       
   547                         m_unknownContentHandler = NULL;
       
   548                     }
       
   549                     // If loading is defered, don't send the body now
       
   550                     if (m_defersData) {
       
   551                         HBufC8* buf = NULL;
       
   552                         buf = chunkPtr.AllocL(); // ok to leave on error because it will trigger HandleError
       
   553                         m_defersData->m_bodyParts.append(buf);
       
   554                     }
       
   555                     else {
       
   556                         WebCore::ResourceHandle* rh = handle();
       
   557                         if (rh) { rh->ref(); }
       
   558                             
       
   559                         CResourceHandleManager::self()->receivedData(m_handle, chunkPtr, 
       
   560                         m_maxSize == 0 ? chunkPtr.Length() : m_maxSize, this);
       
   561                         
       
   562                         if ( m_transaction) 
       
   563                             body->ReleaseData();
       
   564                                     
       
   565                         if (rh) { rh->deref(); }
       
   566                         
       
   567                         // this object might be invalid at this point
       
   568                         return;
       
   569                     }
       
   570                 }
       
   571             }
       
   572             /* If the transaction is closed - through extensive processing through receivedData(), above - the transaction may
       
   573                already have been deleted (by HttpConnection::complete).  Check for existence of transaction
       
   574                before releasing data (ReleaseData()) to prevent attempts to double delete memory. */
       
   575             if ( m_transaction)
       
   576                 body->ReleaseData();
       
   577             break;
       
   578             }
       
   579         case THTTPEvent::EResponseComplete:
       
   580             {
       
   581             // do not mix it up with the ESucceeded
       
   582             // The transaction's response is complete. An incoming event.
       
   583             if ( nonsecure ) {
       
   584                 TRAP_IGNORE( m_cacheSupply->ResponseCompleteL() );
       
   585                 }
       
   586             break;
       
   587             }
       
   588         case THTTPEvent::ESucceeded:
       
   589             {
       
   590             complete(KErrNone);
       
   591             break;
       
   592             }
       
   593         case THTTPEvent::ERequestComplete:
       
   594             {
       
   595             // request is all set
       
   596             if ( nonsecure ) {
       
   597                 m_cacheSupply->CloseRequest();
       
   598                 }
       
   599             break;
       
   600             }
       
   601         case THTTPEvent::EFailed:
       
   602         case THTTPEvent::EMoreDataReceivedThanExpected:
       
   603         case THTTPEvent::EUnrecoverableError:
       
   604         case KErrAbort:
       
   605             {
       
   606                 if (!m_transaction) {
       
   607                     // this object might be invalid at this point.
       
   608                     return;
       
   609                     }
       
   610                 int statusCode = m_transaction->Response().StatusCode();
       
   611                 if ( statusCode != 200) {
       
   612                     complete(-25000 - m_transaction->Response().StatusCode());
       
   613                 }
       
   614                 else if (statusCode == 200 && aEvent.iStatus == THTTPEvent::EFailed) {
       
   615                     // this is a weird combination, it is caused by cached supplier when a response only has the
       
   616                     // response header, but no response body is sent by the HTTP stack.  It is a legitimate senario though.
       
   617                     complete(KErrNone);
       
   618                 }
       
   619                 else {
       
   620                     complete(aEvent.iStatus);
       
   621                 }
       
   622 
       
   623             break;
       
   624             }
       
   625         case THTTPEvent::ERedirectRequiresConfirmation:
       
   626             {
       
   627             TInt method = m_transaction->Request().Method().Index(RHTTPSession::GetTable());
       
   628             TInt statusCode = m_transaction->Response().StatusCode();
       
   629 
       
   630             if( (statusCode == 301 ) &&
       
   631                 !((method==HTTP::EGET) || (method==HTTP::EHEAD)) )
       
   632                  {
       
   633                     RHTTPRequest request = m_transaction->Request();
       
   634                     RHTTPHeaders requestHeaders(request.GetHeaderCollection());
       
   635                     RStringPool p = m_transaction->Session().StringPool();
       
   636                     requestHeaders.RemoveField(p.StringF(HTTP::EContentLength,RHTTPSession::GetTable()));
       
   637                     requestHeaders.RemoveField(p.StringF(HTTP::EContentType,RHTTPSession::GetTable()));
       
   638                     m_transaction->Request().RemoveBody();
       
   639                     m_transaction->Response().RemoveBody();
       
   640                     m_transaction->Request().SetMethod(p.StringF(HTTP::EGET, RHTTPSession::GetTable()));
       
   641                 }
       
   642             int ret = HandleSpecialEvent(THTTPEvent::ERedirectRequiresConfirmation);
       
   643             if (ret != KErrNone) {
       
   644                 handleError(ret);
       
   645                 }
       
   646             break;
       
   647             }
       
   648         case THTTPEvent::ERedirectedPermanently:
       
   649         case THTTPEvent::ERedirectedTemporarily:
       
   650             {
       
   651             // for redirects, we must ensure that we properly handle
       
   652             // any new or changed uri fragment
       
   653             TUriParser8 uriParser;
       
   654             uriParser.Parse( m_transaction->Request().URI().UriDes() );
       
   655             // check for fragment
       
   656             if(uriParser.IsPresent(EUriFragment)) {
       
   657                 // first extract the portion without fragment to
       
   658                 // return to Http framework
       
   659                 TPtrC8 uriNoFrag;
       
   660                 // extract non-fragment portion into uriNoFrag
       
   661                 uriParser.UriWithoutFragment( uriNoFrag );
       
   662                 TUriParser8 parserNoFrag;
       
   663                 parserNoFrag.Parse( uriNoFrag );
       
   664                 m_transaction->Request().SetURIL( parserNoFrag );
       
   665                 // now save the fragment for later use
       
   666                 const TDesC8& fragment = uriParser.Extract( EUriFragment );
       
   667                 delete m_frag;
       
   668                 m_frag = NULL;
       
   669                 m_frag = fragment.AllocL();
       
   670                 }
       
   671             HandleSpecialEvent(aEvent.iStatus);
       
   672             break;
       
   673             }
       
   674         case THTTPEvent::EGotResponseTrailerHeaders:
       
   675             {
       
   676             break;// We don't process this event
       
   677             }
       
   678         default:
       
   679             {
       
   680             // error handling
       
   681             handleError(aEvent.iStatus);
       
   682             break;
       
   683             }
       
   684         }
       
   685     }
       
   686 
       
   687 int HttpConnection::HandleSpecialEvent(int event)
       
   688 {
       
   689     int ret( KErrNone );
       
   690     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   691     switch( event )
       
   692         {
       
   693         case THTTPEvent::ERedirectRequiresConfirmation:
       
   694             {
       
   695                 // Display a Redirect Confirmation dialog, before proceeding
       
   696                 ret = httpSessionMgr->uiCallback()->aboutToLoadPage(control(m_frame), HttpUiCallbacks::ERedirectConfirmation);
       
   697                 if (ret == KErrNone) {
       
   698                     // submit redirected transaction
       
   699                     TRAP(ret, m_transaction->SubmitL());
       
   700                     return ret;
       
   701                 }
       
   702                 else {
       
   703                     return KErrCancel;
       
   704                 }
       
   705                 break;
       
   706             }
       
   707         case THTTPEvent::ERedirectedPermanently:
       
   708         case THTTPEvent::ERedirectedTemporarily:
       
   709             {
       
   710             // Cancel transaction first and resubmit it if the user accepted a secure connection
       
   711             m_transaction->Cancel();
       
   712             if (CheckForSecurityStatusChange() != KErrNone) {
       
   713                 return KErrCancel;
       
   714                 }
       
   715             else {
       
   716                 ret = CheckForNonHttpRedirect();
       
   717                 if (ret == KErrNone) {
       
   718                     // submit redirected transaction only in case of http request.
       
   719                     TRAP(ret, m_transaction->SubmitL());
       
   720                     return ret;
       
   721                     }
       
   722                 else {
       
   723                     return KErrCancel;
       
   724                     }
       
   725                 }
       
   726             break;
       
   727             }
       
   728         case KErrNotSupported:
       
   729         default:
       
   730             {
       
   731                 break;
       
   732             }
       
   733         }
       
   734     return ret;
       
   735 }
       
   736 
       
   737 void HttpConnection::complete(int error)
       
   738 {
       
   739     if (m_defersData) {
       
   740         m_defersData->m_done = true;
       
   741         m_defersData->m_error = error;
       
   742         return;
       
   743     }
       
   744     
       
   745     // protect this function from re-entry
       
   746     if (m_isDone)
       
   747         return;
       
   748     m_isDone = true;
       
   749 
       
   750     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
   751 
       
   752     if(m_IsMultipart && error == KErrNone) {
       
   753         TInt status = m_MultipartContentHandler->ResponseComplete();
       
   754         if(status == KErrNone) {
       
   755             TPtrC8 encoding(*m_encoding);
       
   756             if (m_MultipartContentHandler->MarkupCharset().Length()) {
       
   757                 encoding.Set(m_MultipartContentHandler->MarkupCharset());
       
   758             }
       
   759             ResourceResponse response(m_urlResponse->Des(), m_MultipartContentHandler->MarkupContentType(),
       
   760                 m_maxSize, encoding, String() );
       
   761             response.setHTTPStatusCode(m_transaction->Response().StatusCode());
       
   762             response.setHTTPStatusText(m_transaction->Response().StatusText().DesC());
       
   763             if(m_handle->request().url() != response.url()) {
       
   764                 // Relative URLs are resolved based on the request URL, not response URL.
       
   765                 // If a redirect happens, the request URL must be updated.
       
   766                 m_handle->getInternal()->m_request.setURL(response.url());
       
   767                 m_frame->loader()->activeDocumentLoader()->request().setURL(response.url());
       
   768             }
       
   769             CResourceHandleManager::self()->receivedResponse(m_handle, response, this);
       
   770             CResourceHandleManager::self()->receivedData(m_handle,
       
   771                 m_MultipartContentHandler->MarkupContent(), m_maxSize, this);
       
   772         }
       
   773         delete m_MultipartContentHandler;
       
   774     }
       
   775     if (!error) {
       
   776         // Spawn active object for call to return immediately, to avoid blocking
       
   777         activateReceivedFinished(error);  
       
   778     }
       
   779 
       
   780     if (m_cacheSupply) {
       
   781         delete m_cacheSupply;
       
   782         m_cacheSupply = NULL;
       
   783     }
       
   784     if (m_postDataSupplier) {
       
   785         delete m_postDataSupplier;
       
   786         m_postDataSupplier = NULL;
       
   787     }
       
   788     if (m_transaction) {
       
   789         m_transaction->Cancel();
       
   790         m_transaction->Close();
       
   791         delete m_transaction;
       
   792         m_transaction = NULL;
       
   793     }
       
   794     if (error) {
       
   795         CResourceHandleManager::self()->receivedFinished(m_handle, error, this);
       
   796         derefHandle();
       
   797     }
       
   798 }
       
   799 
       
   800 // -----------------------------------------------------------------------------
       
   801 // HttpConnection::handleAuthRequestL
       
   802 //
       
   803 // -----------------------------------------------------------------------------
       
   804 //
       
   805 int HttpConnection::handleAuthRequestL(
       
   806     int status )
       
   807     {
       
   808     int ret( KErrNone );
       
   809     THTTPHdrVal usernameVal;
       
   810     THTTPHdrVal passwordVal;
       
   811     THTTPHdrVal realmVal;
       
   812     THTTPHdrVal staleVal;
       
   813     RHTTPTransactionPropertySet propSet = m_transaction->PropertySet();
       
   814     RHTTPSession& session = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager()->httpSession();
       
   815     RStringPool strP = session.StringPool();
       
   816     const TStringTable& stringTable = RHTTPSession::GetTable();
       
   817 
       
   818     bool isProxy( EFalse );
       
   819     bool needClose( EFalse );
       
   820     bool pwdClose( EFalse );
       
   821     bool realmClose( EFalse );
       
   822     bool stale( propSet.Property( strP.StringF( HTTP::EStale, stringTable ), staleVal ) );
       
   823 
       
   824     _LIT8( KStrNull, "" );
       
   825     //
       
   826     switch( status )
       
   827         {
       
   828         case EHttpUnauthorized:
       
   829             {
       
   830             if( !propSet.Property( strP.StringF( HTTP::ERealm, stringTable ), realmVal ) )
       
   831                 {
       
   832                 realmClose = ETrue;
       
   833                 realmVal = strP.OpenStringL( KStrNull );
       
   834                 }
       
   835             if( !propSet.Property( strP.StringF( HTTP::EUsername, stringTable ), usernameVal ) )
       
   836                 {
       
   837                 needClose = ETrue;
       
   838                 usernameVal = strP.OpenStringL( KStrNull );
       
   839                 }
       
   840             if( !propSet.Property(strP.StringF( HTTP::EPassword, stringTable ), passwordVal ) )
       
   841                 {
       
   842                 pwdClose = ETrue;
       
   843                 passwordVal = strP.OpenStringL( KStrNull );
       
   844                 }
       
   845             break;
       
   846             }
       
   847         case EHttpProxyAuthenticationRequired:
       
   848             {
       
   849             const TStringTable& stringTableEx = HttpFilterCommonStringsExt::GetTable();
       
   850             //
       
   851             isProxy = ETrue;
       
   852             if( !propSet.Property(strP.StringF( HttpFilterCommonStringsExt::EProxyRealm,
       
   853                 stringTableEx ), realmVal ) )
       
   854                 {
       
   855                 return KErrHttpDecodeUnknownAuthScheme;
       
   856                 }
       
   857             if( !propSet.Property( strP.StringF( HttpFilterCommonStringsExt::EProxyUsername,
       
   858                 stringTableEx ), usernameVal ) )
       
   859                 {
       
   860                 needClose = ETrue;
       
   861                 usernameVal = strP.OpenStringL( KStrNull );
       
   862                 }
       
   863             if( !propSet.Property( strP.StringF( HTTP::EPassword, stringTable ), passwordVal ) )
       
   864                 {
       
   865                 pwdClose = ETrue;
       
   866                 passwordVal = strP.OpenStringL( KStrNull );
       
   867                 }
       
   868             break;
       
   869             }
       
   870         default:
       
   871             {
       
   872             __ASSERT_DEBUG( EFalse, THttpConnUtils::PanicLoader( KErrArgument ) );
       
   873             break;
       
   874             }
       
   875         }
       
   876 
       
   877     TRAP( ret, SendAuthRequestL( usernameVal, realmVal, isProxy, stale, passwordVal ) );
       
   878     if (realmClose)
       
   879       {
       
   880         realmVal.Str().Close();
       
   881         }
       
   882     if( needClose )
       
   883         {
       
   884         usernameVal.Str().Close();
       
   885         }
       
   886     if( pwdClose )
       
   887         {
       
   888         passwordVal.Str().Close();
       
   889         }
       
   890     return(ret);
       
   891     }
       
   892 
       
   893 // -----------------------------------------------------------------------------
       
   894 // HttpConnection::SendAuthRequestL
       
   895 //
       
   896 // -----------------------------------------------------------------------------
       
   897 //
       
   898 void HttpConnection::SendAuthRequestL(
       
   899     THTTPHdrVal& aUsernameVal,
       
   900     THTTPHdrVal& aRealmVal,
       
   901     bool aIsProxy,
       
   902     bool aStale,
       
   903     THTTPHdrVal& aPasswordVal )
       
   904     {
       
   905 
       
   906     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   907     RHTTPSession& session = httpSessionMgr->httpSession();
       
   908     int popCount( 0 );
       
   909 
       
   910     // prepare uri param
       
   911     int len = m_transaction->Request().URI().UriDes().Length() + 1;
       
   912     TUint16* uri = new(ELeave) TUint16 [ len ];
       
   913     CleanupStack::PushL( uri );
       
   914     popCount++;
       
   915     TPtr uriPtr( uri, len );
       
   916     uriPtr.Copy( m_transaction->Request().URI().UriDes() );
       
   917     uriPtr.ZeroTerminate();
       
   918 
       
   919     // prepare username param
       
   920     len = aUsernameVal.Str().DesC().Length() + 1;
       
   921     TUint16* username = new(ELeave) TUint16 [ len ];
       
   922     CleanupStack::PushL( username );
       
   923     popCount++;
       
   924     TPtr usernamePtr( username, len );
       
   925     usernamePtr.Copy( aUsernameVal.Str().DesC() );
       
   926     usernamePtr.ZeroTerminate();
       
   927 
       
   928     // prepare realm param
       
   929     len = aRealmVal.Str().DesC().Length() + 1;
       
   930     TUint16* realm = new(ELeave) TUint16 [ len ];
       
   931     CleanupStack::PushL( realm );
       
   932     popCount++;
       
   933     TPtr realmPtr( realm, len );
       
   934     realmPtr.Copy( aRealmVal.Str().DesC() );
       
   935     realmPtr.ZeroTerminate();
       
   936 
       
   937     // prepare password param
       
   938     len = aPasswordVal.Str().DesC().Length() + 1;
       
   939     TUint16* password = new(ELeave) TUint16 [ len ];
       
   940     CleanupStack::PushL( password );
       
   941     popCount++;
       
   942     TPtr passwordPtr( password, len );
       
   943     passwordPtr.Copy( aPasswordVal.Str().DesC() );
       
   944     passwordPtr.ZeroTerminate();
       
   945 
       
   946     // Get the authentication type
       
   947     bool basicAuthentication( EFalse );
       
   948     RHTTPTransactionPropertySet propSet = m_transaction->PropertySet();
       
   949     THTTPHdrVal propRetVal;
       
   950 
       
   951     // Get the name of the property
       
   952     RStringF propName = session.StringPool().StringF( HTTP::EBasic, RHTTPSession::GetTable() );
       
   953 
       
   954     // if it is set . .
       
   955     if( propSet.Property( propName, propRetVal ) )
       
   956         {
       
   957         // . . then we have basic auth
       
   958         basicAuthentication = ETrue;
       
   959         }
       
   960 
       
   961     // send data to dialog layer for user input.  Data from user is provided
       
   962     // back to http transaction. by UiCallbacks calling HttpConnection::AuthenticationResponse
       
   963     // Completion of this authentication process will therefore occur before
       
   964     // the call below returns.
       
   965     httpSessionMgr->uiCallback()->AuthenticationRequest( this, uriPtr, usernamePtr,
       
   966         realmPtr, aIsProxy, aStale, passwordPtr, basicAuthentication );
       
   967     CleanupStack::PopAndDestroy( popCount ); // password, realm, username, uri
       
   968     }
       
   969 
       
   970 // -----------------------------------------------------------------------------
       
   971 // HttpConnection::AuthenticationResponse
       
   972 //
       
   973 //
       
   974 // -----------------------------------------------------------------------------
       
   975 //
       
   976 void HttpConnection::AuthenticationResponse(
       
   977     TPtr& aUsername,
       
   978     TPtr& aPassword,
       
   979     bool aProxy,
       
   980     int aError)
       
   981     {
       
   982     TUint16* username = (TUint16*) aUsername.Ptr();
       
   983     TUint16* password = (TUint16*) aPassword.Ptr();
       
   984 
       
   985     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
   986 
       
   987     int ret = KErrNone;
       
   988 
       
   989     // Execution is back from the dialog, move the transaction
       
   990     // from the authentication listback into active list
       
   991     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
   992     httpSessionMgr->removeAuthRequest(this);
       
   993     httpSessionMgr->addRequest(this, m_handle);
       
   994 
       
   995     switch (aError)
       
   996         {
       
   997         case KErrNone:
       
   998             {
       
   999             TRAP( ret, this->AddAuthenticationPropertiesL( aUsername, aPassword, aProxy) );
       
  1000             if (ret == KErrNone)
       
  1001                 {
       
  1002                 m_transaction->SubmitL();
       
  1003                 break;
       
  1004                 }
       
  1005             aError = ret;
       
  1006             }
       
  1007         case KErrCancel:
       
  1008         case KErrNoMemory:
       
  1009         default:
       
  1010             {
       
  1011             delete username;
       
  1012             delete password;
       
  1013             this->complete( aError );
       
  1014             break;
       
  1015             }
       
  1016         }
       
  1017     }
       
  1018 
       
  1019 // -----------------------------------------------------------------------------
       
  1020 // HttpConnection::AddAuthenticationPropertiesL
       
  1021 // Add username and password properties to the transaction.
       
  1022 // -----------------------------------------------------------------------------
       
  1023 //
       
  1024 void HttpConnection::AddAuthenticationPropertiesL(
       
  1025     TPtr& aUsername,
       
  1026     TPtr& aPassword,
       
  1027     bool aProxy )
       
  1028     {
       
  1029     TUint16* username = (TUint16*) aUsername.Ptr();
       
  1030     TUint16* password = (TUint16*) aPassword.Ptr();
       
  1031     __ASSERT_DEBUG( username != NULL && password != NULL, THttpConnUtils::PanicLoader( KErrArgument ) );
       
  1032 
       
  1033     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
  1034 
       
  1035     RString usernameStr;
       
  1036     RString passwordStr;
       
  1037     RStringPool stringPool = m_transaction->Session().StringPool();
       
  1038     RHTTPTransactionPropertySet propSet = m_transaction->PropertySet();
       
  1039     //
       
  1040     User::LeaveIfError( THttpConnUtils::OpenStringFromUnicode( stringPool, username, usernameStr ) );
       
  1041     CleanupClosePushL( usernameStr );
       
  1042     User::LeaveIfError( THttpConnUtils::OpenStringFromUnicode( stringPool, password, passwordStr ) );
       
  1043     CleanupClosePushL( passwordStr );
       
  1044     // set proxy authentication
       
  1045     if( aProxy )
       
  1046         {
       
  1047         propSet.RemoveProperty( stringPool.StringF( HttpFilterCommonStringsExt::EProxyUsername,
       
  1048             HttpFilterCommonStringsExt::GetTable() ) );
       
  1049 
       
  1050         propSet.SetPropertyL( stringPool.StringF( HttpFilterCommonStringsExt::EProxyUsername,
       
  1051             HttpFilterCommonStringsExt::GetTable() ), usernameStr);
       
  1052 
       
  1053         propSet.RemoveProperty( stringPool.StringF( HttpFilterCommonStringsExt::EProxyPassword,
       
  1054             HttpFilterCommonStringsExt::GetTable() ) );
       
  1055 
       
  1056         propSet.SetPropertyL( stringPool.StringF( HttpFilterCommonStringsExt::EProxyPassword,
       
  1057             HttpFilterCommonStringsExt::GetTable()), passwordStr );
       
  1058         }
       
  1059     else
       
  1060         {
       
  1061         propSet.RemoveProperty( stringPool.StringF( HTTP::EUsername, RHTTPSession::GetTable() ) );
       
  1062 
       
  1063         propSet.SetPropertyL( stringPool.StringF( HTTP::EUsername, RHTTPSession::GetTable() ),
       
  1064             usernameStr );
       
  1065 
       
  1066         propSet.RemoveProperty( stringPool.StringF( HTTP::EPassword, RHTTPSession::GetTable() ) );
       
  1067 
       
  1068         propSet.SetPropertyL( stringPool.StringF( HTTP::EPassword, RHTTPSession::GetTable() ),
       
  1069             passwordStr );
       
  1070         }
       
  1071     CleanupStack::PopAndDestroy( 2 ); // passwordStr, usernameStr
       
  1072     }
       
  1073 
       
  1074 // -----------------------------------------------------------------------------
       
  1075 // HttpConnection::CheckForSecurityStatusChange
       
  1076 //
       
  1077 // -----------------------------------------------------------------------------
       
  1078 //
       
  1079 int HttpConnection::CheckForSecurityStatusChange()
       
  1080     {
       
  1081     int error(KErrNone);
       
  1082     bool requestedSecScheme(EFalse);
       
  1083     bool redirectedSecScheme(EFalse);
       
  1084 
       
  1085     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
  1086 
       
  1087     if (m_handle->request().mainLoad() && !m_frame->ownerElement())
       
  1088         {
       
  1089         TUriParser8 redirectedParser;
       
  1090         if(redirectedParser.Parse( m_transaction->Request().URI().UriDes() ) == KErrNone)
       
  1091             {
       
  1092             //
       
  1093             if( redirectedParser.Extract( EUriScheme ).Compare(KHttps) == 0 )
       
  1094                 {
       
  1095                     redirectedSecScheme = ETrue;
       
  1096                 }
       
  1097             }
       
  1098         TUriParser8 requestedParser;
       
  1099         if(m_handle->request().url().des().Length() != 0 )
       
  1100             {
       
  1101             error = requestedParser.Parse(m_handle->request().url().des());
       
  1102             }
       
  1103         else
       
  1104             {
       
  1105             error = requestedParser.Parse(m_transaction->Request().URI().UriDes());
       
  1106             }
       
  1107         if(error == KErrNone)
       
  1108             {
       
  1109             //
       
  1110             if( requestedParser.Extract( EUriScheme ).Compare(KHttps) == 0 )
       
  1111                 {
       
  1112                 requestedSecScheme = ETrue;
       
  1113                 }
       
  1114             }
       
  1115         //When submitting the request iSecurePage was set based on the request url
       
  1116         //Check the redirect url and see if the scheme has changed
       
  1117         HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
  1118         if(requestedSecScheme && !redirectedSecScheme) //redirection from a secure page to an unsecure one
       
  1119             {
       
  1120             error = httpSessionMgr->uiCallback()->aboutToLoadPage(control(m_frame), HttpUiCallbacks::EExitingSecurePage);
       
  1121             }
       
  1122         else if(redirectedSecScheme && !requestedSecScheme) //redirection to unsecurepage when secure page was requested
       
  1123             {
       
  1124             error = httpSessionMgr->uiCallback()->aboutToLoadPage(control(m_frame), HttpUiCallbacks::EEnteringSecurePage );
       
  1125             }
       
  1126         }
       
  1127     return error;
       
  1128     }
       
  1129 
       
  1130 // -----------------------------------------------------------------------------
       
  1131 // HttpConnection::CheckForNonHttpRedirect
       
  1132 //
       
  1133 // -----------------------------------------------------------------------------
       
  1134 //
       
  1135 TInt HttpConnection::CheckForNonHttpRedirect()
       
  1136     {
       
  1137     TUriParser8 uriParser;
       
  1138 
       
  1139     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
  1140 
       
  1141     if(uriParser.Parse( m_transaction->Request().URI().UriDes() ) == KErrNone)
       
  1142         {
       
  1143         if (uriParser.IsPresent(EUriHost) && uriParser.IsPresent(EUriScheme)) // looking only for absolue Url path and schemes other than http(s)
       
  1144             {
       
  1145             const TDesC8& scheme = uriParser.Extract(EUriScheme);
       
  1146             if (scheme.FindF(_L8("http")) == KErrNotFound) // everything but http(s)
       
  1147                 {
       
  1148                 TPtrC8 ptr(uriParser.UriDes());
       
  1149                 // these arrays are pushed into CleanupStack in case leave
       
  1150                 // if no leave, they will be freed below
       
  1151                 RArray<TUint>* typeArray = new (ELeave) RArray<TUint>(1);
       
  1152                 CleanupStack::PushL(typeArray);
       
  1153 
       
  1154                 CDesCArrayFlat* desArray = new (ELeave) CDesCArrayFlat(1);
       
  1155                 CleanupStack::PushL(desArray);
       
  1156 
       
  1157                 User::LeaveIfError(typeArray->Append(EParamRequestUrl));
       
  1158 
       
  1159                 HBufC16* urlbuf = HBufC16::NewLC( ptr.Length()  + 1); // +1 for zero terminate
       
  1160                 urlbuf->Des().Copy( ptr );
       
  1161                 TPtr16 bufDes16 = urlbuf->Des();
       
  1162                 bufDes16.ZeroTerminate();
       
  1163 
       
  1164                 desArray->AppendL(bufDes16);
       
  1165                 CleanupStack::Pop();
       
  1166 
       
  1167                 MBrCtlSpecialLoadObserver* loadObserver = control(m_frame)->brCtlSpecialLoadObserver();
       
  1168 
       
  1169                 if (loadObserver)
       
  1170                     {
       
  1171                     TRAP_IGNORE(loadObserver->HandleRequestL(typeArray, desArray));
       
  1172                     }
       
  1173 
       
  1174                 // No leave, so pop here and clean up
       
  1175                 CleanupStack::Pop(desArray);
       
  1176                 CleanupStack::Pop(typeArray);
       
  1177 
       
  1178                 // cleanup arrays
       
  1179                 if (typeArray)
       
  1180                     {
       
  1181                     // Closes the array and frees all memory allocated to the array
       
  1182                     typeArray->Close();
       
  1183                     delete typeArray;
       
  1184                     }
       
  1185 
       
  1186                 if (desArray)
       
  1187                     {
       
  1188                     // Deletes all descriptors from the array and frees the memory allocated to the array buffer
       
  1189                     desArray->Reset();
       
  1190                     delete desArray;
       
  1191                     }
       
  1192 
       
  1193                 return KErrCancel;
       
  1194                 }
       
  1195             }
       
  1196         }
       
  1197     return KErrNone;
       
  1198     }
       
  1199 
       
  1200 RHTTPTransaction* HttpConnection::takeOwnershipHttpTransaction()
       
  1201 {
       
  1202     __ASSERT_DEBUG( m_transaction, THttpConnUtils::PanicLoader( KErrArgument ) );
       
  1203 
       
  1204     RHTTPTransaction* trans = m_transaction;
       
  1205     RHTTPSession& session = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager()->httpSession();
       
  1206     // remove own address from transaction properties
       
  1207     m_transaction->PropertySet().RemoveProperty(session.StringPool().StringF(HttpFilterCommonStringsExt::ESelfPtr,
       
  1208         HttpFilterCommonStringsExt::GetTable()));
       
  1209     m_transaction = NULL;
       
  1210     return trans;
       
  1211 }
       
  1212 
       
  1213 // -----------------------------------------------------------------------------
       
  1214 // HttpConnection::addIMEINotifyPropertiesL
       
  1215 // Keeping for completeness, but currently is not needed as functionality is implemented
       
  1216 // in User-Agent Profile Filter
       
  1217 // Add IMEINotify properties to the transaction.
       
  1218 // -----------------------------------------------------------------------------
       
  1219 //
       
  1220 /*
       
  1221 void HttpConnection::addIMEINotifyPropertiesL()
       
  1222 {
       
  1223     // Get IMEI Notify enable/disable setting
       
  1224     HttpSessionManager* httpSessionMgr = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager();
       
  1225     bool imeiNotify = httpSessionMgr->imeiEnabled();
       
  1226 
       
  1227     RHTTPTransactionPropertySet propSet = m_transaction->PropertySet();
       
  1228 
       
  1229     RStringPool stringPool = m_transaction->Session().StringPool();
       
  1230     propSet.RemoveProperty( stringPool.StringF(
       
  1231         HttpFilterCommonStringsExt::EIMEINotify, HttpFilterCommonStringsExt::GetTable() ) );
       
  1232     //
       
  1233     propSet.SetPropertyL( stringPool.StringF( HttpFilterCommonStringsExt::EIMEINotify,
       
  1234         HttpFilterCommonStringsExt::GetTable() ), THTTPHdrVal( imeiNotify ) );
       
  1235 }
       
  1236 */
       
  1237 
       
  1238 // -----------------------------------------------------------------------------
       
  1239 // HttpLoaderUtils::IsUrlInCache
       
  1240 //
       
  1241 // Returns ETrue if Cache Manager finds the Url in cache, EFalse otherwise
       
  1242 // -----------------------------------------------------------------------------
       
  1243 //
       
  1244 bool HttpConnection::IsUrlInCacheL(
       
  1245     const TDesC8& aUrl )
       
  1246 {
       
  1247     TBool inCache( EFalse );  // not in cache by default
       
  1248 	m_isInCache = EFalse;
       
  1249 
       
  1250     CHttpCacheManager* cache = StaticObjectsContainer::instance()->resourceLoaderDelegate()->httpSessionManager()->cacheManager();
       
  1251 
       
  1252     if ( cache )
       
  1253     {
       
  1254         // call cache manager to check for url in cache
       
  1255         inCache = cache->Find( aUrl );
       
  1256     }
       
  1257 	m_isInCache = inCache;
       
  1258     return inCache;
       
  1259 }
       
  1260 
       
  1261 void HttpConnection::processDefersData(void* ctx)
       
  1262 {
       
  1263     HttpConnection* self = static_cast<HttpConnection*>(ctx);
       
  1264     DefersData* defersData = self->m_defersData;
       
  1265     if (self->m_cancelled)
       
  1266         return;
       
  1267     if (self->m_defersData->m_response) {
       
  1268         CResourceHandleManager::self()->receivedResponse(self->m_handle, *(self->m_defersData->m_response), self);
       
  1269         // transaction is complete (must have been cancelled in receivedResponse call
       
  1270         if (self->m_isDone)
       
  1271             return;
       
  1272         // transaction is taken, we need to cleanup this resource.
       
  1273         if (!self->m_transaction) {
       
  1274             self->derefHandle();
       
  1275             // this object might be invalid at this point
       
  1276             return;
       
  1277         }
       
  1278         delete self->m_defersData->m_response;
       
  1279         self->m_defersData->m_response = NULL;
       
  1280         self->m_defersData->Activate();
       
  1281         return;
       
  1282     }
       
  1283     if (self->m_defersData->m_bodyParts.size()) {
       
  1284         HBufC8* buf = self->m_defersData->m_bodyParts.first();
       
  1285         self->m_defersData->m_bodyParts.remove(0);
       
  1286         CResourceHandleManager::self()->receivedData(self->m_handle, *buf, self->m_maxSize, self);
       
  1287         delete buf;
       
  1288         self->m_defersData->Activate();
       
  1289         return;
       
  1290     }
       
  1291     if (self->m_defersData->m_done) {
       
  1292         self->m_defersData = NULL;
       
  1293         self->complete(defersData->m_error);
       
  1294     }
       
  1295     self->m_defersData = NULL;
       
  1296     delete defersData;
       
  1297 }
       
  1298 
       
  1299 
       
  1300 void HttpConnection::activateReceivedFinished(TInt errorCode) 
       
  1301 {
       
  1302         if (m_receivedFinished) {
       
  1303             if (m_receivedFinished->isDone()) {
       
  1304                 delete m_receivedFinished;
       
  1305             } else {
       
  1306                 // This would happen if processing of a previous transaction is hung.
       
  1307                 // We should never get in here.
       
  1308                 m_receivedFinished ->Cancel();
       
  1309                 return;
       
  1310             }
       
  1311         }
       
  1312             
       
  1313         m_receivedFinished = new ReceivedFinished(this, processReceivedFinished);
       
  1314         m_receivedFinished->Activate(errorCode);
       
  1315 }
       
  1316 
       
  1317 void HttpConnection::processReceivedFinished(void* ctx, TInt errorCode)
       
  1318 {
       
  1319     HttpConnection* self = static_cast<HttpConnection*>(ctx);
       
  1320     CResourceHandleManager::self()->receivedFinished(self->m_handle, errorCode, self);
       
  1321 
       
  1322     self->derefHandle();
       
  1323 }
       
  1324 
       
  1325 
       
  1326 // end of file