|
1 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Symbian Foundation License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.symbianfoundation.org/legal/sfl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Contains implementation of CHttpEboClientStep class |
|
15 // @internalAll |
|
16 // |
|
17 // |
|
18 |
|
19 // User Include |
|
20 #include "testhttpeboclientstep.h" |
|
21 // Additional headers |
|
22 #include "CommDbConnPref.h" |
|
23 #include "CommDb.h" |
|
24 #include "es_sock.h" |
|
25 |
|
26 // Standard headers used by default |
|
27 _LIT8(KUserAgent, "TestHttpEboClient"); |
|
28 _LIT8(KAccept, "*/*"); |
|
29 |
|
30 /** |
|
31 Constructor: Sets the test step name. |
|
32 @internalTechnology |
|
33 @test |
|
34 */ |
|
35 CHttpEboClientStep::CHttpEboClientStep() |
|
36 { |
|
37 |
|
38 //Call base class method to set human readable name for test step |
|
39 SetTestStepName(KTestHttpEboClientStep); |
|
40 } |
|
41 |
|
42 |
|
43 /** |
|
44 Destructor |
|
45 @internalTechnology |
|
46 @test |
|
47 */ |
|
48 CHttpEboClientStep::~CHttpEboClientStep() |
|
49 { |
|
50 } |
|
51 |
|
52 |
|
53 /** |
|
54 Sets the proxy and HttpDataOptimiser implemetation to session |
|
55 based on the patameter values in ini file and calls InvokeHttpMethodL() |
|
56 @internalTechnology |
|
57 @test |
|
58 @param None |
|
59 @return None |
|
60 */ |
|
61 void CHttpEboClientStep::StartClientL() |
|
62 { |
|
63 TPtrC uri; |
|
64 TPtrC proxyPtr; |
|
65 TBool proxyUsage; |
|
66 TPtrC resbodyFilename; |
|
67 TBool sessHttpOptUsage; |
|
68 if (!GetStringFromConfig(ConfigSection(), KIniUri, uri) || |
|
69 !GetStringFromConfig(ConfigSection(), KIniFileName, resbodyFilename) || |
|
70 !GetBoolFromConfig(ConfigSection(), KIniSessProxyUsage, proxyUsage) |
|
71 ) |
|
72 { |
|
73 ERR_PRINTF4(_L("Problem in reading values from ini. \ |
|
74 \nExpected fields are: \n%S\n%S\n%S\n" |
|
75 ),&KIniUri, &KIniFileName, &KIniSessProxyUsage |
|
76 ); |
|
77 SetTestStepResult(EFail); |
|
78 return; |
|
79 } |
|
80 iOutputFilename.Set(resbodyFilename); |
|
81 if (proxyUsage) |
|
82 if(!GetStringFromConfig(ConfigSection(), KIniSessProxy, proxyPtr) |
|
83 ) |
|
84 { |
|
85 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
86 \nExpected field is: \n%S\n" |
|
87 ),&KIniSessProxy |
|
88 ); |
|
89 SetTestStepResult(EFail); |
|
90 return; |
|
91 } |
|
92 RStringPool strP = iSess.StringPool(); |
|
93 RStringF method; |
|
94 //setting proxy to session |
|
95 if(proxyUsage) |
|
96 { |
|
97 iSess.ConnectionInfo().SetPropertyL(iSess.StringPool().StringF(HTTP::EProxyUsage,RHTTPSession::GetTable()), iSess.StringPool().StringF(HTTP::EUseProxy,RHTTPSession::GetTable())); |
|
98 TBuf8<256> prox8; |
|
99 prox8.Copy(proxyPtr); |
|
100 RStringF proxy = iSess.StringPool().OpenFStringL(prox8); |
|
101 CleanupClosePushL(proxy); |
|
102 iSess.ConnectionInfo().SetPropertyL(iSess.StringPool().StringF(HTTP::EProxyAddress,RHTTPSession::GetTable()), proxy); |
|
103 CleanupStack::PopAndDestroy(&proxy); |
|
104 } |
|
105 // Setting HttpDataOptimiser to session |
|
106 if (!GetBoolFromConfig(ConfigSection(), KIniSessHttpOptUsage, sessHttpOptUsage)) |
|
107 { |
|
108 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
109 \nExpected fields are: \n%S\n" |
|
110 ),&KIniSessHttpOptUsage |
|
111 ); |
|
112 SetTestStepResult(EFail); |
|
113 return; |
|
114 } |
|
115 if (sessHttpOptUsage) |
|
116 iSess.SetupHttpDataOptimiser(*this); |
|
117 |
|
118 // method |
|
119 method = strP.StringF(HTTP::EGET,RHTTPSession::GetTable()); |
|
120 TBuf8<256> url8; |
|
121 url8.Copy(uri); |
|
122 TRAPD(err,InvokeHttpMethodL(url8, method)); |
|
123 if (err != KErrNone) |
|
124 { |
|
125 ERR_PRINTF2(_L("Teststep Failed: Leave occured in CTestHttpBaseStep::InvokeHttpMethodL: %D\n" |
|
126 ),err |
|
127 ); |
|
128 SetTestStepResult(EFail); |
|
129 } |
|
130 method.Close(); |
|
131 } |
|
132 |
|
133 |
|
134 /** |
|
135 Invoke the http method |
|
136 This actually creates the transaction, sets the headers and HttpDataOptimiser implemetation to transaction |
|
137 and then starts the transaction |
|
138 @internalTechnology |
|
139 @test |
|
140 @param aUri Requested uri |
|
141 @param aMethod Requested method |
|
142 @return None |
|
143 */ |
|
144 void CHttpEboClientStep::InvokeHttpMethodL(const TDesC8& aUri, RStringF aMethod) |
|
145 { |
|
146 |
|
147 TBool tranProxyUsage; |
|
148 TBool tranHttpOptUsage; |
|
149 TPtrC tranProxy; |
|
150 TUriParser8 uri; |
|
151 uri.Parse( aUri ); |
|
152 |
|
153 //This code has been added by Maciej Seroka to get rid of the access point selection dialog |
|
154 |
|
155 // Initialise the socket server session. |
|
156 RSocketServ socketServ; |
|
157 User::LeaveIfError(socketServ.Connect()); |
|
158 |
|
159 // Initialise the RConnection. |
|
160 RConnection connection; |
|
161 User::LeaveIfError(connection.Open(socketServ)); |
|
162 |
|
163 // open the IAP communications database |
|
164 CCommsDatabase* commDB = CCommsDatabase::NewL(EDatabaseTypeIAP); |
|
165 CleanupStack::PushL(commDB); |
|
166 |
|
167 // initialize a view |
|
168 CCommsDbConnectionPrefTableView* commDBView = |
|
169 commDB->OpenConnectionPrefTableInRankOrderLC(ECommDbConnectionDirectionOutgoing); |
|
170 |
|
171 // go to the first record |
|
172 User::LeaveIfError(commDBView->GotoFirstRecord()); |
|
173 |
|
174 // Declare a prefTableView Object. |
|
175 CCommsDbConnectionPrefTableView::TCommDbIapConnectionPref pref; |
|
176 |
|
177 // read the connection preferences |
|
178 commDBView->ReadConnectionPreferenceL(pref); |
|
179 TUint32 iapID = pref.iBearer.iIapId; |
|
180 |
|
181 // pop and destroy the IAP View |
|
182 CleanupStack::PopAndDestroy(commDBView); |
|
183 |
|
184 // pop and destroy the database object |
|
185 CleanupStack::PopAndDestroy(commDB); |
|
186 |
|
187 // Now we have the iap Id. Use it to connect for the connection. |
|
188 // Create a connection preference variable. |
|
189 TCommDbConnPref connectPref; |
|
190 |
|
191 // setup preferences |
|
192 connectPref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); |
|
193 connectPref.SetDirection(ECommDbConnectionDirectionOutgoing); |
|
194 connectPref.SetBearerSet(ECommDbBearerGPRS); |
|
195 connectPref.SetIapId(iapID); |
|
196 |
|
197 // start a synchronous connection |
|
198 TInt errConnect = connection.Start(connectPref); |
|
199 |
|
200 // Then, associate the current socket server session and rconnection object |
|
201 //used above with the HttpSession which u will be using. |
|
202 |
|
203 RStringPool strP = iSess.StringPool(); |
|
204 RHTTPConnectionInfo connInfo = iSess.ConnectionInfo(); |
|
205 connInfo.SetPropertyL ( strP.StringF(HTTP::EHttpSocketServ, RHTTPSession::GetTable() ), |
|
206 THTTPHdrVal (socketServ.Handle())); |
|
207 TInt connPtr = REINTERPRET_CAST(TInt, &(connection)); |
|
208 connInfo.SetPropertyL ( strP.StringF(HTTP::EHttpSocketConnection, |
|
209 RHTTPSession::GetTable() ), |
|
210 THTTPHdrVal (connPtr) ); |
|
211 |
|
212 //and it ends here. |
|
213 |
|
214 |
|
215 // Opening a transaction |
|
216 iTrans = iSess.OpenTransactionL(uri, *this, aMethod); |
|
217 RHTTPHeaders hdr = iTrans.Request().GetHeaderCollection(); |
|
218 // Add headers appropriate to all methods |
|
219 SetHeaderL(hdr, HTTP::EUserAgent, KUserAgent); |
|
220 SetHeaderL(hdr, HTTP::EAccept, KAccept); |
|
221 |
|
222 if (!GetBoolFromConfig(ConfigSection(), KIniTranProxyUsage, tranProxyUsage)) |
|
223 { |
|
224 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
225 \nExpected fields are: \n%S\n" |
|
226 ),&KIniTranProxyUsage |
|
227 ); |
|
228 SetTestStepResult(EFail); |
|
229 return; |
|
230 } |
|
231 if (tranProxyUsage) |
|
232 if (!GetStringFromConfig(ConfigSection(), KIniTranProxy, tranProxy)) |
|
233 { |
|
234 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
235 \nExpected field is: \n%S\n" |
|
236 ),&KIniTranProxy |
|
237 ); |
|
238 SetTestStepResult(EFail); |
|
239 return; |
|
240 } |
|
241 //setting transaction proxy |
|
242 RHTTPTransactionPropertySet transactionProperties = iTrans.PropertySet(); |
|
243 // RStringPool strP = iSess.StringPool(); |
|
244 if (tranProxyUsage) |
|
245 { |
|
246 TBuf8<256> tranProx8; |
|
247 tranProx8.Copy(tranProxy); |
|
248 RStringF proxyAddr = strP.OpenFStringL(tranProx8); |
|
249 CleanupClosePushL(proxyAddr); |
|
250 THTTPHdrVal proxyUsage(strP.StringF(HTTP::EUseProxy, RHTTPSession::GetTable())); |
|
251 transactionProperties.SetPropertyL(strP.StringF(HTTP::EProxyUsage,RHTTPSession::GetTable()), proxyUsage); |
|
252 transactionProperties.SetPropertyL(strP.StringF(HTTP::EProxyAddress,RHTTPSession::GetTable()), proxyAddr); |
|
253 CleanupStack::PopAndDestroy(1,&proxyAddr); |
|
254 } |
|
255 |
|
256 // Setting HttpDataOptimiser for transaction. |
|
257 if (!GetBoolFromConfig(ConfigSection(), KIniTranHttpOptUsage, tranHttpOptUsage)) |
|
258 { |
|
259 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
260 \nExpected fields are: \n%S\n" |
|
261 ),&KIniTranHttpOptUsage |
|
262 ); |
|
263 SetTestStepResult(EFail); |
|
264 return; |
|
265 } |
|
266 if (tranHttpOptUsage) |
|
267 iTrans.SetupHttpDataOptimiser(*this); |
|
268 // submit the transaction |
|
269 iTrans.SubmitL(); |
|
270 // Start the scheduler, once the transaction completes or is cancelled on an error the scheduler will be |
|
271 // stopped in the event handler |
|
272 CActiveScheduler::Start(); |
|
273 } |
|
274 |
|
275 |
|
276 /** |
|
277 This is the implementation of interface method MHttpDataOptimiser::MHFRunL |
|
278 If there is a reponse body it will be copied to a file. |
|
279 Just printing the fired events to the log file. |
|
280 @internalTechnology |
|
281 @test |
|
282 @param aTransaction Transaction which is being processed currently |
|
283 @param THTTPEvent Event for which it is called |
|
284 @return None |
|
285 */ |
|
286 void CHttpEboClientStep::MHFRunL(RHTTPTransaction aTransaction, const THTTPEvent& aEvent) |
|
287 { |
|
288 switch (aEvent.iStatus) |
|
289 { |
|
290 case THTTPEvent::EGotResponseHeaders: |
|
291 { |
|
292 // HTTP response headers have been received. We can determine now if there is |
|
293 // going to be a response body to save. |
|
294 RHTTPResponse resp = aTransaction.Response(); |
|
295 TInt status = resp.StatusCode(); |
|
296 RStringF statusStr = resp.StatusText(); |
|
297 TBuf<32> statusStr16; |
|
298 statusStr16.Copy(statusStr.DesC()); |
|
299 INFO_PRINTF3(_L("Status: %D (%S)\n"),status, &statusStr16); |
|
300 // Determine if the body will be saved to disk |
|
301 iSavingResponseBody = EFalse; |
|
302 if (resp.HasBody() && (status >= 200) && (status < 300) && (status != 204)) |
|
303 { |
|
304 TInt dataSize = resp.Body()->OverallDataSize(); |
|
305 if (dataSize >= 0) |
|
306 INFO_PRINTF2(_L("Response body size is %d\n"), dataSize); |
|
307 else |
|
308 INFO_PRINTF1(_L("Response body size is unknown\n")); |
|
309 |
|
310 // Save response to file in disk. |
|
311 iSavingResponseBody = ETrue; |
|
312 } |
|
313 |
|
314 if (iSavingResponseBody) // If we're saving, then open a file handle for the new file |
|
315 { |
|
316 // Check it exists and open a file handle |
|
317 TInt valid = iFileServ.IsValidName(iOutputFilename); |
|
318 if (!valid) |
|
319 { |
|
320 ERR_PRINTF1(_L("The specified filename is not valid!.\n")); |
|
321 iSavingResponseBody = EFalse; |
|
322 } |
|
323 else |
|
324 { |
|
325 TInt err = iRespBodyFile.Replace(iFileServ, |
|
326 iOutputFilename, |
|
327 EFileWrite|EFileShareExclusive); |
|
328 if (err) |
|
329 { |
|
330 iSavingResponseBody = EFalse; |
|
331 User::Leave(err); |
|
332 } |
|
333 } |
|
334 } |
|
335 |
|
336 } break; |
|
337 case THTTPEvent::EGotResponseBodyData: |
|
338 { |
|
339 // Get the body data supplier |
|
340 iRespBody = aTransaction.Response().Body(); |
|
341 |
|
342 // Append to the output file if we're saving responses |
|
343 if (iSavingResponseBody) |
|
344 { |
|
345 INFO_PRINTF1(_L("Saving response body...\n")); |
|
346 TPtrC8 bodyData; |
|
347 TBool lastChunk = iRespBody->GetNextDataPart(bodyData); |
|
348 iRespBodyFile.Write(bodyData); |
|
349 if (lastChunk) |
|
350 iRespBodyFile.Close(); |
|
351 } |
|
352 |
|
353 // Done with that bit of body data |
|
354 iRespBody->ReleaseData(); |
|
355 } break; |
|
356 case THTTPEvent::EResponseComplete: |
|
357 { |
|
358 // The transaction's response is complete |
|
359 INFO_PRINTF1(_L("\nTransaction Complete\n")); |
|
360 } break; |
|
361 case KErrHttpOptimiserFailsTrans: |
|
362 { |
|
363 INFO_PRINTF1(_L("Cancelling/Failing Transaction\n")); |
|
364 aTransaction.Fail(THTTPFilterHandle::EProtocolHandler); |
|
365 //CActiveScheduler::Stop(); |
|
366 } break; |
|
367 case THTTPEvent::ESucceeded: |
|
368 { |
|
369 INFO_PRINTF1(_L("Transaction Successful\n")); |
|
370 aTransaction.Close(); |
|
371 CActiveScheduler::Stop(); |
|
372 } break; |
|
373 case THTTPEvent::EFailed: |
|
374 { |
|
375 INFO_PRINTF1(_L("Transaction Failed\n")); |
|
376 aTransaction.Close(); |
|
377 CActiveScheduler::Stop(); |
|
378 //Line added to fail the test if no connection to a web server |
|
379 SetTestStepResult(EFail); |
|
380 } break; |
|
381 case THTTPEvent::ERedirectedPermanently: |
|
382 { |
|
383 INFO_PRINTF1(_L("Permanent Redirection\n")); |
|
384 } break; |
|
385 case THTTPEvent::ERedirectedTemporarily: |
|
386 { |
|
387 INFO_PRINTF1(_L("Temporary Redirection\n")); |
|
388 } break; |
|
389 case THTTPEvent::ERedirectRequiresConfirmation: |
|
390 { |
|
391 // 301(Moved Permanently), 302(Found) or 307(Temporary Redirect) status is received |
|
392 // from a transaction and hence ERedirectRequiresConfirmation is sent by filter |
|
393 // client has opted to close the transaction |
|
394 INFO_PRINTF1(_L("Redirect requires confirmation\n")); |
|
395 aTransaction.Close(); |
|
396 CActiveScheduler::Stop(); |
|
397 } break; |
|
398 default: |
|
399 { |
|
400 INFO_PRINTF2(_L("<unrecognised event: %D>\n"), aEvent.iStatus); |
|
401 // close off the transaction if it's an error |
|
402 if (aEvent.iStatus < 0) |
|
403 { |
|
404 aTransaction.Close(); |
|
405 CActiveScheduler::Stop(); |
|
406 } |
|
407 //Line added to fail the test if no connection to a web server |
|
408 SetTestStepResult(EFail); |
|
409 } break; |
|
410 } |
|
411 } |
|
412 |
|
413 |
|
414 /** |
|
415 This is the implementation of interface method MHttpDataOptimiser::MHFRunError |
|
416 @internalTechnology |
|
417 @test |
|
418 @param aError Error which has been raised. |
|
419 @param aTransaction Transaction which is being processed currently |
|
420 @param THTTPEvent Event which it is being handled currently. |
|
421 @return None |
|
422 */ |
|
423 TInt CHttpEboClientStep::MHFRunError(TInt aError, RHTTPTransaction /*aTransaction*/, const THTTPEvent& /*aEvent*/) |
|
424 { |
|
425 INFO_PRINTF2(_L("MHFRunError fired with error code %D\n"), aError); |
|
426 return KErrNone; |
|
427 } |
|
428 |
|
429 |
|
430 /** |
|
431 It enocodes the request data. |
|
432 @internalTechnology |
|
433 @test |
|
434 @param aHttpData Actual request. |
|
435 @param aEncodedData Encoded request. |
|
436 @return None |
|
437 */ |
|
438 void CHttpEboClientStep::EncodeL (const TDesC8& /*aHttpData*/, HBufC8* &aEncodedData) |
|
439 { |
|
440 |
|
441 INFO_PRINTF1(_L("######## CHttpEboClientStep::EncodeL ########\n")); |
|
442 TBool isEncoded; |
|
443 if (!GetBoolFromConfig(ConfigSection(), KIniIsEncoded, isEncoded)) |
|
444 { |
|
445 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
446 \nExpected fields are: \n%S\n" |
|
447 ),&KIniIsEncoded |
|
448 ); |
|
449 SetTestStepResult(EFail); |
|
450 return; |
|
451 } |
|
452 // Checking whether enocoding is needed. |
|
453 if (isEncoded) |
|
454 { |
|
455 // Encoding: Changing the request data to http://www.google.co.uk/ |
|
456 _LIT8(KTestRequest, "GET http://www.google.co.uk/ HTTP/1.1\r\nHost: www.google.co.uk\r\nAccept: */*\r\nUser-Agent: TestHttpEboClient\r\n\r\n"); |
|
457 const TDesC8& encodedReq(KTestRequest); |
|
458 TRAPD(err, |
|
459 { |
|
460 aEncodedData = encodedReq.AllocLC(); |
|
461 CleanupStack::Pop(); |
|
462 }); |
|
463 if (err != KErrNone) |
|
464 { |
|
465 ERR_PRINTF2(_L("Test step failed: Leave occured while encoding the request: %D\n"), err); |
|
466 SetTestStepResult(EFail); |
|
467 } |
|
468 else |
|
469 { |
|
470 INFO_PRINTF1(_L("Encoded/Changed the request\n")); |
|
471 } |
|
472 } |
|
473 else |
|
474 INFO_PRINTF1(_L("Not encoding the request [passing NULL]\n")); |
|
475 } |
|
476 |
|
477 |
|
478 /** |
|
479 It decodes the responsing data before parsing. |
|
480 @internalTechnology |
|
481 @test |
|
482 @param aHttpData Actual response. |
|
483 @param aEncodedData Decoded response. |
|
484 @return None |
|
485 */ |
|
486 void CHttpEboClientStep::DecodeL (const TDesC8& aData, HBufC8*& aHttpData, TBool& aTransFail) |
|
487 { |
|
488 INFO_PRINTF1(_L("######## CHttpEboClientStep::DecodeL ########\n")); |
|
489 TBool isDecoded; |
|
490 TBool failTransaction; |
|
491 if (!GetBoolFromConfig(ConfigSection(), KIniIsDecoded, isDecoded)) |
|
492 { |
|
493 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
494 \nExpected fields are: \n%S\n" |
|
495 ),&KIniIsDecoded |
|
496 ); |
|
497 SetTestStepResult(EFail); |
|
498 return; |
|
499 } |
|
500 // Checking whether decoding is needed. |
|
501 if (isDecoded) |
|
502 { |
|
503 TRAPD(err, |
|
504 { |
|
505 // Copying same actual response to decoded response |
|
506 aHttpData = aData.AllocLC(); |
|
507 CleanupStack::Pop(); |
|
508 }); |
|
509 if (err != KErrNone) |
|
510 { |
|
511 ERR_PRINTF2(_L("Test step failed: Leave occured while decoding the response: %D\n"), err); |
|
512 SetTestStepResult(EFail); |
|
513 } |
|
514 else |
|
515 { |
|
516 INFO_PRINTF1(_L("Sent the actual response as a decoded response\n")); |
|
517 } |
|
518 } |
|
519 else |
|
520 INFO_PRINTF1(_L("Not decoding the response [passing NULL]\n")); |
|
521 |
|
522 if(!GetBoolFromConfig(ConfigSection(), KIniFailTransaction, failTransaction)) |
|
523 { |
|
524 ERR_PRINTF2(_L("Problem in reading values from ini. \ |
|
525 \nExpected fields are: \n%S\n" |
|
526 ),&KIniFailTransaction |
|
527 ); |
|
528 SetTestStepResult(EFail); |
|
529 return; |
|
530 } |
|
531 // Checking to fail the transaction. |
|
532 if (failTransaction) |
|
533 { |
|
534 aTransFail = ETrue; |
|
535 INFO_PRINTF1(_L("CHttpEboClientStep::DecodeL returing ETrue(intend to fail the transaction)\n")); |
|
536 } |
|
537 else |
|
538 { |
|
539 aTransFail = EFalse; |
|
540 INFO_PRINTF1(_L("CHttpEboClientStep::DecodeL returing EFalse(not failing the transaction)\n")); |
|
541 } |
|
542 } |