|
1 /* |
|
2 * Copyright (c) 2009-2010 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 "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 * CDownloadHandler implementation |
|
16 * |
|
17 * |
|
18 */ |
|
19 |
|
20 |
|
21 #include <aknappui.h> |
|
22 #include <COEUTILS.H> |
|
23 #include <wlanerrorcodes.h> //For download error handling |
|
24 #include <etelpckt.h> //For download error handling |
|
25 #include <exterror.h> //For download error handling |
|
26 #include <httpdownloadmgrcommon.h> // For download error handling (not in S60 5.0 SDK) |
|
27 |
|
28 #include "ADM.hrh" |
|
29 #include "ADMDownloadHandler.h" |
|
30 #include "ADMAppUi.h" |
|
31 #include "networkstatuslistener.h" |
|
32 |
|
33 #include "globals.h" |
|
34 #include "macros.h" |
|
35 /* |
|
36 #ifdef USE_LOGFILE |
|
37 #include "debug.h" |
|
38 #undef LOG |
|
39 #undef LOG2 |
|
40 #undef LOG3 |
|
41 #undef LOG4 |
|
42 #undef LOG5 |
|
43 #undef LOG6 |
|
44 #undef LOG7 |
|
45 #undef LOG8 |
|
46 #undef LOG8_2 |
|
47 |
|
48 #define LOG( aMsg ) { _LIT(KMsg, aMsg); iAppUi.iLog.Write( KMsg ); RDebug::Print( KMsg ); } |
|
49 #define LOG2( aMsg, aParam1 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1 ); RDebug::Print( KMsg, aParam1 ); } |
|
50 #define LOG3( aMsg, aParam1, aParam2 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1, aParam2 ); RDebug::Print( KMsg, aParam1, aParam2 ); } |
|
51 #define LOG4( aMsg, aParam1, aParam2, aParam3 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1, aParam2, aParam3 ); RDebug::Print( KMsg, aParam1, aParam2, aParam3 ); } |
|
52 #define LOG5( aMsg, aParam1, aParam2, aParam3, aParam4 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1, aParam2, aParam3, aParam4 ); RDebug::Print( KMsg, aParam1, aParam2, aParam3, aParam4 ); } |
|
53 #define LOG6( aMsg, aParam1, aParam2, aParam3, aParam4, aParam5 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1, aParam2, aParam3, aParam4, aParam5 ); RDebug::Print( KMsg, aParam1, aParam2, aParam3, aParam4, aParam5 ); } |
|
54 #define LOG7( aMsg, aParam1, aParam2, aParam3, aParam4, aParam5, aParam6 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1, aParam2, aParam3, aParam4, aParam5, aParam6 ); RDebug::Print( KMsg, aParam1, aParam2, aParam3, aParam4, aParam5, aParam6 ); } |
|
55 #define LOG8( aMsg, aParam1, aParam2, aParam3, aParam4, aParam5, aParam6, aParam7 ) { _LIT(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1, aParam2, aParam3, aParam4, aParam5, aParam6, aParam7 ); RDebug::Print( KMsg, aParam1, aParam2, aParam3, aParam4, aParam5, aParam6, aParam7 ); } |
|
56 #define LOG8_2( aMsg, aParam1 ) { _LIT8(KMsg, aMsg); iAppUi.iLog.WriteFormat( KMsg, aParam1 ); RDebug::Print(_L("RDebug _L8() at line %d"), __LINE__); } |
|
57 #endif |
|
58 */ |
|
59 #ifdef USE_LOGFILE |
|
60 // Logging version |
|
61 // --------------------------------------------------------------------------- |
|
62 // |
|
63 // --------------------------------------------------------------------------- |
|
64 // |
|
65 CDownloadHandler* CDownloadHandler::NewL(MDownloadClient* aDlClient, RFileLogger& aLogger, const TBool aMasterInstance) |
|
66 { |
|
67 CDownloadHandler* object = new ( ELeave ) CDownloadHandler(aDlClient, aLogger, aMasterInstance); |
|
68 CleanupStack::PushL( object ); |
|
69 object->ConstructL(); |
|
70 CleanupStack::Pop(); |
|
71 return object; |
|
72 } |
|
73 |
|
74 // --------------------------------------------------------------------------- |
|
75 // |
|
76 // --------------------------------------------------------------------------- |
|
77 // |
|
78 CDownloadHandler::CDownloadHandler(MDownloadClient* aDlClient, RFileLogger& aLogger, const TBool aMasterInstance) : |
|
79 iLog(aLogger), |
|
80 iDlClient(aDlClient), |
|
81 iMasterInstance(aMasterInstance), |
|
82 iPtrToResponseBodyFileName(0,0) |
|
83 { |
|
84 } |
|
85 #else |
|
86 // --------------------------------------------------------------------------- |
|
87 // |
|
88 // --------------------------------------------------------------------------- |
|
89 // |
|
90 CDownloadHandler* CDownloadHandler::NewLC(MDownloadClient* aDlClient, const TBool aMasterInstance) |
|
91 { |
|
92 CDownloadHandler* object = new ( ELeave ) CDownloadHandler(aDlClient, aMasterInstance); |
|
93 CleanupStack::PushL( object ); |
|
94 object->ConstructL(); |
|
95 return object; |
|
96 } |
|
97 |
|
98 CDownloadHandler* CDownloadHandler::NewL(MDownloadClient* aDlClient, const TBool aMasterInstance) |
|
99 { |
|
100 CDownloadHandler* object = CDownloadHandler::NewLC(aDlClient, aMasterInstance); |
|
101 CleanupStack::Pop(); |
|
102 return object; |
|
103 } |
|
104 |
|
105 CDownloadHandler::CDownloadHandler(MDownloadClient* aDlClient, const TBool aMasterInstance) : |
|
106 iDlClient(aDlClient), |
|
107 iMasterInstance(aMasterInstance), |
|
108 iPtrToResponseBodyFileName(0,0) |
|
109 { |
|
110 } |
|
111 #endif |
|
112 |
|
113 // --------------------------------------------------------------------------- |
|
114 // Default destructor |
|
115 // --------------------------------------------------------------------------- |
|
116 // |
|
117 CDownloadHandler::~CDownloadHandler() |
|
118 { |
|
119 DELETE_IF_NONNULL( iUrl ); |
|
120 DELETE_IF_NONNULL( iResponseBodyFileName ); |
|
121 |
|
122 delete iNetworkStatusListener; |
|
123 iDownloadManager.DeleteAll(); |
|
124 iDownloadManager.Close(); |
|
125 } |
|
126 |
|
127 // --------------------------------------------------------------------------- |
|
128 // |
|
129 // --------------------------------------------------------------------------- |
|
130 // |
|
131 void CDownloadHandler::ConstructL() |
|
132 { |
|
133 // TBool masterInstance(!(iADMAppUiObj->EikonEnv()->StartedAsServerApp())); |
|
134 const TUid uid = {_UID3}; |
|
135 iDownloadManager.ConnectL(uid , *this, iMasterInstance ); |
|
136 iNetworkStatusListener = CNetworkStatusListener::NewL( *this ); |
|
137 } |
|
138 |
|
139 // --------------------------------------------------------------------------- |
|
140 // |
|
141 // --------------------------------------------------------------------------- |
|
142 // |
|
143 void CDownloadHandler::SetIAP(TUint32 aIAP) |
|
144 { |
|
145 iIAP = aIAP; |
|
146 if ( iIAP > 0) |
|
147 { |
|
148 LOG2( "CDownloadHandler::SetIap(): %d", aIAP ); |
|
149 // Set the download manager to silent mode |
|
150 iDownloadManager.SetBoolAttribute( EDlMgrSilentMode, ETrue ); |
|
151 iDownloadManager.SetIntAttribute( EDlMgrIap, iIAP ); |
|
152 iNetworkStatusListener->SetIapIdToMonitor(iIAP); |
|
153 } |
|
154 } |
|
155 |
|
156 #ifdef USE_LOGFILE |
|
157 void CDownloadHandler::Log(TRefByValue<const TDesC16> aFmt, ...) |
|
158 { |
|
159 VA_LIST list; |
|
160 VA_START(list, aFmt); |
|
161 TBuf<0x100> buf; |
|
162 buf.AppendFormatList(aFmt, list); |
|
163 iLog.Write(buf); |
|
164 } |
|
165 #endif |
|
166 |
|
167 // ----------------------------------------------------------------------------- |
|
168 // Callback for CNetworkStatusObserver |
|
169 // |
|
170 // Called when the connection status changes |
|
171 // ----------------------------------------------------------------------------- |
|
172 // |
|
173 void CDownloadHandler::HandleNetworkStatusChangedL(const TInt aStatus) |
|
174 { |
|
175 LOG2( "+ HandleNetworkStatusChangedL(): %d", aStatus ); |
|
176 |
|
177 // Did we lose the network connection? |
|
178 if (aStatus == EConnMonStatusNotAvailable) |
|
179 { |
|
180 iNetworkLost = ETrue; |
|
181 } |
|
182 |
|
183 //LOG2( "- HandleNetworkStatusChangedL(): %d", iNetworkLost ); |
|
184 } |
|
185 |
|
186 // ----------------------------------------------------------------------------- |
|
187 // Processes download errors and sets aDownloadError |
|
188 // |
|
189 // @param aGlErrId Global error ID from download manager. |
|
190 // @param aErrId Error ID from download manager. |
|
191 // @param aDownloadError Reference to the download error variable function is |
|
192 // going to set in case of known error. |
|
193 // ----------------------------------------------------------------------------- |
|
194 // |
|
195 TBool CDownloadHandler::ProcessDlErrors(const TInt32 aGlErrId, const TInt32 aErrId, EDownloadError& aDownloadError) |
|
196 { |
|
197 if (iFetchType && (aGlErrId || aErrId)) |
|
198 LOG4( "+ ProcessDlErrors(%d, %d, %d)", aGlErrId, aErrId, aDownloadError ); |
|
199 TBool requestRestart = EFalse; |
|
200 // Process the error codes |
|
201 switch (aErrId) |
|
202 { |
|
203 case KErrNone: |
|
204 // everything a-OK! |
|
205 break; |
|
206 case EConnectionFailed: |
|
207 aDownloadError = EDlErrDownloadFailure; |
|
208 break; |
|
209 case ETransactionFailed: |
|
210 // We set the download error to network failure as that's the |
|
211 // error propagated to TState::DownloadFailed(). |
|
212 // The state machine will try to restart the download, if the |
|
213 // error code is EDlErrDownloadFailure, but NOT for EDlErrNetworkFailure. |
|
214 aDownloadError = EDlErrDownloadFailure; |
|
215 requestRestart = ETrue; |
|
216 break; |
|
217 case EObjectNotFound: |
|
218 aDownloadError = EDlErrFileNotFound; |
|
219 break; |
|
220 default: |
|
221 LOG2( "Unhandled ErrId %d", aErrId ); |
|
222 aDownloadError = EDlErrDownloadFailure; |
|
223 break; |
|
224 } |
|
225 // Process the global error code |
|
226 switch (aGlErrId) |
|
227 { |
|
228 case KErrNone: |
|
229 // everything a-OK! |
|
230 break; |
|
231 case KErrCancel: |
|
232 case KErrAbort: |
|
233 // The user has cancelled the download / IAP selection box |
|
234 aDownloadError = EDlErrCancelled; |
|
235 break; |
|
236 case KErrDiskFull: |
|
237 // Disk full |
|
238 aDownloadError = EDlErrNotEnoughSpace; |
|
239 break; |
|
240 case KErrUnknown: |
|
241 // act on KErrUnknown only, if error ID is not set |
|
242 if (aErrId == KErrNone) |
|
243 { |
|
244 aDownloadError = EDlErrDownloadFailure; |
|
245 requestRestart = ETrue; |
|
246 } |
|
247 break; |
|
248 case KErrNotFound: |
|
249 case KErrBadName: |
|
250 case KErrNotSupported: |
|
251 case KErrCommsLineFail: |
|
252 case KErrTimedOut: |
|
253 case KErrCouldNotConnect: |
|
254 case KErrDisconnected: |
|
255 case KErrGprsServicesNotAllowed: |
|
256 case KErrGsmMMNetworkFailure: |
|
257 // WLAN network related errors: |
|
258 case KErrWlanNetworkNotFound: |
|
259 case KErrWlanRoamingFailed: |
|
260 case KErrWlanNetworkLost: |
|
261 #if 0 |
|
262 case KErrBadName: |
|
263 case KErrNotSupported: |
|
264 case KErrWlanOpenAuthFailed: |
|
265 case KErrWlanSharedKeyAuthRequired: |
|
266 case KErrWlanSharedKeyAuthFailed: |
|
267 case KErrWlanWpaAuthRequired: |
|
268 case KErrWlanIllegalEncryptionKeys: |
|
269 case KErrWlanPskModeRequired: |
|
270 case KErrWlanEapModeRequired: |
|
271 case KErrWlanSimNotInstalled: |
|
272 case KErrWlanNotSubscribed: |
|
273 case KErrWlanAccessBarred: |
|
274 case KErrWlanPasswordExpired: |
|
275 case KErrWlanNoDialinPermissions: |
|
276 case KErrWlanAccountDisabled: |
|
277 case KErrWlanRestrictedLogonHours: |
|
278 case KErrWlanServerCertificateExpired: |
|
279 case KErrWlanCerficateVerifyFailed: |
|
280 case KErrWlanNoUserCertificate: |
|
281 case KErrWlanNoCipherSuite: |
|
282 case KErrWlanUserRejected: |
|
283 case KErrWlanUserCertificateExpired: |
|
284 // less fatal, but still needs to fail the download: |
|
285 case KErrWlanWpaAuthFailed: |
|
286 case KErrWlan802dot1xAuthFailed: |
|
287 case KErrWlanIllegalWpaPskKey: |
|
288 case KErrWlanEapSimFailed: |
|
289 case KErrWlanEapTlsFailed: |
|
290 case KErrWlanEapPeapFailed: |
|
291 case KErrWlanEapMsChapv2: |
|
292 case KErrWlanEapAkaFailed: |
|
293 case KErrWlanEapTtlsFailed: |
|
294 case KErrWlanLeapFailed: |
|
295 case KErrWlanEapGtcFailed: |
|
296 #endif |
|
297 // A fatal network error has occured, don't retry the download |
|
298 requestRestart = EFalse; |
|
299 aDownloadError = EDlErrNetworkFailure; |
|
300 break; |
|
301 default: |
|
302 if (!requestRestart) |
|
303 { |
|
304 // We assume all the other error codes to be 'hard' network errors |
|
305 LOG2( "Unhandled GlErrId %d", aGlErrId ); |
|
306 aDownloadError = EDlErrNetworkFailure; |
|
307 } |
|
308 break; |
|
309 } |
|
310 if (iFetchType && aDownloadError != ENoError) |
|
311 LOG3( "- ProcessDlErrors(): %d, %d", requestRestart, aDownloadError ); |
|
312 return requestRestart; |
|
313 } |
|
314 |
|
315 // --------------------------------------------------------------------------- |
|
316 // |
|
317 // --------------------------------------------------------------------------- |
|
318 // |
|
319 void CDownloadHandler::HandleDMgrEventL( RHttpDownload& aDownload, THttpDownloadEvent aEvent ) |
|
320 { |
|
321 TInt32 glErrId = KErrNone; |
|
322 TInt32 errId = ENoError; |
|
323 |
|
324 // Get error IDs |
|
325 aDownload.GetIntAttribute( EDlAttrGlobalErrorId, glErrId ); |
|
326 aDownload.GetIntAttribute( EDlAttrErrorId, errId ); |
|
327 |
|
328 #ifdef DO_LOG |
|
329 if (iFetchType) |
|
330 { |
|
331 _LIT(KFmt, ", GlErrId=%6d, ErrId=%d"); |
|
332 TBuf<64> buf; |
|
333 |
|
334 if ( ((glErrId != KErrNone) || (errId != ENoError)) && glErrId != KErrUnknown ) |
|
335 { |
|
336 buf.AppendFormat(KFmt, glErrId, errId); |
|
337 } |
|
338 |
|
339 if ( ( iDownloadState != aEvent.iDownloadState ) || |
|
340 ( iProgressState != aEvent.iProgressState ) ) |
|
341 { |
|
342 iDownloadState = aEvent.iDownloadState; |
|
343 iProgressState = aEvent.iProgressState; |
|
344 |
|
345 LOG5( "DlSt=%5d, PrSt=%5d, L=%d%S", iDownloadState, iProgressState, iNetworkLost, &buf ); |
|
346 } |
|
347 } |
|
348 #endif |
|
349 |
|
350 if (iNetworkLost && !iCancelled) |
|
351 { |
|
352 TBuf<KMaxPath> fn; |
|
353 aDownload.GetStringAttribute( EDlAttrDestFilename, fn ); |
|
354 iDownloadError = EDlErrNetworkFailure; |
|
355 LOG2( "Connection lost! Cancelling '%S' download.", &fn ); |
|
356 DoHandleHttpFetchFailure(fn, glErrId, errId); |
|
357 return; |
|
358 } |
|
359 |
|
360 switch ( aEvent.iDownloadState ) |
|
361 { |
|
362 case EHttpDlCreated: |
|
363 { |
|
364 break; |
|
365 } |
|
366 case EHttpDlInprogress: |
|
367 { |
|
368 // Already downloaded content size |
|
369 TInt32 downloadedSize( 0 ); |
|
370 // Total download size |
|
371 TInt32 dlLength( 0 ); |
|
372 |
|
373 if ( aEvent.iProgressState == EHttpProgConnected ) |
|
374 { |
|
375 TInt32 iap; |
|
376 // Get the selected IAP (ignore any errors from Get()) |
|
377 iDownloadManager.GetIntAttribute( EDlMgrIap, iap ); |
|
378 if (iIAP != iap) |
|
379 { |
|
380 LOG2( "* Using IAP %d", iap ); |
|
381 iIAP = iap; |
|
382 iDlClient->HandleIapChanged(iIAP); |
|
383 } |
|
384 } |
|
385 |
|
386 aDownload.GetIntAttribute( EDlAttrDownloadedSize, downloadedSize ); |
|
387 aDownload.GetIntAttribute( EDlAttrLength, dlLength ); |
|
388 |
|
389 UpdateDownloadSpeed(downloadedSize); |
|
390 |
|
391 iDlClient->HandleHttpFetchInProgress( downloadedSize, dlLength, iDlAvgSpeed ); |
|
392 break; |
|
393 } |
|
394 case EHttpDlPaused: |
|
395 case EHttpDlFailed: |
|
396 // These two fill fold to EHttpDlFailed. We don't want to process failure events twice. |
|
397 // case EHttpDlNonPausableNetworkLoss: |
|
398 // case EHttpDlMultipleMOFailed: |
|
399 { |
|
400 TBuf<KMaxPath> buf; |
|
401 |
|
402 aDownload.GetStringAttribute( EDlAttrDestFilename, buf ); |
|
403 |
|
404 // We just monitor the progress state and start download, when |
|
405 // content-type is received. Any errors are ignored in this state. |
|
406 if ( |
|
407 // we have to check error codes in EHttpProgNone state, otherwise |
|
408 // we'll end up infinite loop, for instance, in AP selection cancellation |
|
409 ( aEvent.iProgressState == EHttpContentTypeReceived ) || |
|
410 ( ( aEvent.iProgressState == EHttpProgNone ) && ( errId == ENoError) ) ) |
|
411 { |
|
412 // TODO: Should we check glErrId and do Reset() before starting download? |
|
413 // need to start the download if not already started |
|
414 LOG( "Starting download" ); |
|
415 aDownload.Start(); |
|
416 // Start timing the download |
|
417 iDlStartTime.UniversalTime(); |
|
418 // ignore any errors, so we can start the download |
|
419 break; |
|
420 } |
|
421 if ( ProcessDlErrors(glErrId, errId, iDownloadError) ) |
|
422 { |
|
423 if (++iConnectionAttempt < KDownloadConnectionRetries) |
|
424 { |
|
425 LOG4( "Restarting download due to network failure (%d: %d, %d)", iConnectionAttempt, glErrId, errId ); |
|
426 // TODO: Do we need to do a Reset() before Start()? |
|
427 aDownload.Start(); |
|
428 // We don't restart the download timer on purpose |
|
429 // |
|
430 // Clear the error id so it doesn't get caught below |
|
431 // as this is not an error situation. |
|
432 iDownloadError = EDlErrNoError; |
|
433 } |
|
434 else |
|
435 { |
|
436 LOG4( "Too many retries, cancelling download (%d; %d, %d)", iDownloadError, glErrId, errId ); |
|
437 // iDownloadError has been set properly by ProcessDlErrors() |
|
438 } |
|
439 } |
|
440 if ( iDownloadError != KErrNone ) |
|
441 { |
|
442 if (iFetchType) |
|
443 LOG2( "DlErr=%d", iDownloadError ); |
|
444 // Inform about it |
|
445 DoHandleHttpFetchFailure(buf, glErrId, errId); |
|
446 // TODO: Just in case: don't delete the download in HandleDMgrEventL |
|
447 // That seems to cause problems on different devices. |
|
448 // Download failed, delete it |
|
449 // aDownload.Delete(); |
|
450 } |
|
451 break; |
|
452 } |
|
453 case EHttpDlCompleted: |
|
454 { |
|
455 TBuf<KMaxPath> buf; |
|
456 // Download Manager total Length of the download |
|
457 TInt32 dlLength( 0 ); |
|
458 aDownload.GetIntAttribute( EDlAttrLength, dlLength ); |
|
459 aDownload.GetStringAttribute( EDlAttrDestFilename, buf ); |
|
460 const TInt64 dlTime = UpdateDownloadSpeed(dlLength); |
|
461 iDlClient->HandleHttpFetchCompleted(buf, iFetchType, dlLength, iDlAvgSpeed, dlTime); |
|
462 break; |
|
463 } |
|
464 case EHttpDlDeleting: |
|
465 // Signal that we're deleting the download |
|
466 iDlClient->HandleDownloadDeleting(); |
|
467 break; |
|
468 default: |
|
469 { |
|
470 break; |
|
471 } |
|
472 } // switch |
|
473 } |
|
474 |
|
475 // ----------------------------------------------------------------------------- |
|
476 // Updates the average download speed counter |
|
477 // @param aBytesDownloaded Bytes downloaded during this download |
|
478 // @returns Time in microseconds spend in this download |
|
479 // ----------------------------------------------------------------------------- |
|
480 // |
|
481 TInt64 CDownloadHandler::UpdateDownloadSpeed(const TInt32 aBytesDownloaded) |
|
482 { |
|
483 TInt64 fromDlStart = 0; |
|
484 if (aBytesDownloaded > 0) |
|
485 { |
|
486 TTime time; |
|
487 time.UniversalTime(); |
|
488 |
|
489 fromDlStart = time.MicroSecondsFrom(iDlStartTime).Int64(); |
|
490 |
|
491 // Use ifs to avoid divide-by-zero |
|
492 if (fromDlStart > 0) |
|
493 { |
|
494 iDlAvgSpeed = aBytesDownloaded*1000000.0 / fromDlStart; |
|
495 } |
|
496 } |
|
497 return fromDlStart; |
|
498 } |
|
499 |
|
500 // ----------------------------------------------------------------------------- |
|
501 // |
|
502 // ----------------------------------------------------------------------------- |
|
503 // |
|
504 void CDownloadHandler::CancelAllDownloads() |
|
505 { |
|
506 // Remove all downloads |
|
507 iDownloadManager.DeleteAll(); |
|
508 } |
|
509 |
|
510 // ----------------------------------------------------------------------------- |
|
511 // Handles client callback when download fails |
|
512 // ----------------------------------------------------------------------------- |
|
513 // |
|
514 void CDownloadHandler::DoHandleHttpFetchFailure(const TDesC& aDlFilename, const TInt aGlobalErrorId, const TInt aErrorId) |
|
515 { |
|
516 if (!iCancelled) |
|
517 { |
|
518 iDlClient->HandleHttpFetchFailure(aDlFilename, aGlobalErrorId, aErrorId, iFetchType); |
|
519 iCancelled = ETrue; |
|
520 } |
|
521 else |
|
522 { |
|
523 LOG( "DoHandleHttpFetchFailure(): Called, but already cancelled" ); |
|
524 } |
|
525 } |
|
526 |
|
527 // ----------------------------------------------------------------------------- |
|
528 // |
|
529 // ----------------------------------------------------------------------------- |
|
530 // |
|
531 void CDownloadHandler::StartDownloadL(const TDesC8& aDepUrl, const TDesC& aFileName, |
|
532 const TDesC& aDownloadPath, const TInt aFetchType) |
|
533 { |
|
534 __ASSERT_ALWAYS( (aDepUrl.Length() > 0) && (aFileName.Length() > 0) && (aDownloadPath.Length() > 0), User::Leave( KErrArgument) ); |
|
535 |
|
536 // Cleanup is required in case the API is called |
|
537 // multiple times. |
|
538 DELETE_IF_NONNULL( iUrl ); |
|
539 DELETE_IF_NONNULL( iResponseBodyFileName ); |
|
540 |
|
541 // Set the full Url after appending the filename. +1 for '/' |
|
542 iUrl = HBufC8::NewL( aDepUrl.Length() + aFileName.Length() + 1 ); |
|
543 TPtr8 ptr(iUrl->Des()); |
|
544 ptr.Copy(aDepUrl); |
|
545 // Append forward slash if that's missing |
|
546 if (ptr.Right(1)[0] != '/') |
|
547 ptr.Append('/'); |
|
548 |
|
549 ptr.Append(aFileName); |
|
550 |
|
551 iDownloadError = EDlErrNoError; |
|
552 iCancelled = EFalse; |
|
553 iConnectionAttempt = 0; |
|
554 |
|
555 // Create a new download |
|
556 TBool retried = EFalse; |
|
557 TBool isNewDl = ETrue; |
|
558 iPtrToUrl.Set(*iUrl); |
|
559 |
|
560 // Set the full response body file name |
|
561 // based on the actual filename to be downloaded. |
|
562 iResponseBodyFileName = HBufC::NewL(aDownloadPath.Length()+ aFileName.Length()); |
|
563 iPtrToResponseBodyFileName.Set(iResponseBodyFileName->Des()); |
|
564 iPtrToResponseBodyFileName.Copy(aDownloadPath); |
|
565 iPtrToResponseBodyFileName.Append(aFileName); |
|
566 |
|
567 ConeUtils::EnsurePathExistsL(iPtrToResponseBodyFileName); |
|
568 |
|
569 TBuf<KMaxFileName> buf; |
|
570 buf.Copy(ptr); |
|
571 retry: |
|
572 if (aFetchType) |
|
573 { |
|
574 LOG2( "+ StartDownload(): '%S'", &buf ); |
|
575 LOG2( " to '%S'", &iPtrToResponseBodyFileName ); |
|
576 } |
|
577 |
|
578 RHttpDownload& dl = iDownloadManager.CreateDownloadL( iPtrToUrl, isNewDl ); |
|
579 |
|
580 if (isNewDl) |
|
581 { |
|
582 // Start download |
|
583 dl.SetStringAttribute( EDlAttrDestFilename, iPtrToResponseBodyFileName ); |
|
584 User::LeaveIfError( dl.Start() ); |
|
585 // This timer will be reset, when content-type is received, but if it's not |
|
586 // we need to have a sane starting time, otherwise dl avg speed calculation |
|
587 // does not work properly. |
|
588 iDlStartTime.UniversalTime(); |
|
589 iFetchType = aFetchType; |
|
590 iDlAvgSpeed = 0.0; |
|
591 } |
|
592 else |
|
593 { |
|
594 LOG( "Download exists, deleting all" ); |
|
595 // Remove any downloads |
|
596 iDownloadManager.DeleteAll(); |
|
597 if (!retried) |
|
598 { |
|
599 LOG( "Download exists, retrying.." ); |
|
600 retried = ETrue; |
|
601 // we leave isNewDl set to ETrue, so we would accept any existing download for the same URL |
|
602 goto retry; |
|
603 } |
|
604 LOG( "Download exists, retry failed. Panic!" ); |
|
605 User::Leave( KErrAlreadyExists ); |
|
606 } |
|
607 } |
|
608 // EOF |