|
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 |