|
1 /** |
|
2 This file is part of CWRT package ** |
|
3 |
|
4 Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** |
|
5 |
|
6 This program is free software: you can redistribute it and/or modify |
|
7 it under the terms of the GNU (Lesser) General Public License as |
|
8 published by the Free Software Foundation, version 2.1 of the License. |
|
9 This program is distributed in the hope that it will be useful, but |
|
10 WITHOUT ANY WARRANTY; without even the implied warranty of |
|
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
|
12 (Lesser) General Public License for more details. You should have |
|
13 received a copy of the GNU (Lesser) General Public License along |
|
14 with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 */ |
|
16 |
|
17 #include "oma2downloadbackend.h" |
|
18 #include "omaddparser.h" |
|
19 #include "downloadmanager.h" |
|
20 #include "download.h" |
|
21 #include "clientdownload.h" |
|
22 #include "downloadcore.h" |
|
23 #include "downloadevent.h" |
|
24 #include <QCoreApplication> |
|
25 #include <QFileInfo> |
|
26 |
|
27 #ifdef Q_OS_LINUX |
|
28 #include <sys/statvfs.h> |
|
29 #endif |
|
30 |
|
31 #ifdef Q_OS_LINUX |
|
32 static double freeSpace(const char *path) |
|
33 #else |
|
34 static double freeSpace(const char* /*path*/) |
|
35 #endif |
|
36 { |
|
37 #ifdef Q_OS_LINUX |
|
38 struct statvfs fiData; |
|
39 if ((statvfs(path,&fiData)) < 0 ) |
|
40 return 0; |
|
41 else { |
|
42 qint64 blockSize = fiData.f_bsize/1024; |
|
43 qint64 freeSize = (fiData.f_bavail)*blockSize; |
|
44 freeSize = freeSize/1024; |
|
45 return freeSize; |
|
46 } |
|
47 #endif |
|
48 return 0; |
|
49 } |
|
50 |
|
51 // Constants |
|
52 const char* const SuppressUserConfirmation_Never = "Never"; |
|
53 |
|
54 // private implementation |
|
55 class OMA2DownloadBackendPrivate { |
|
56 DM_DECLARE_PUBLIC(OMA2DownloadBackend); |
|
57 public: |
|
58 OMA2DownloadBackendPrivate(); |
|
59 ~OMA2DownloadBackendPrivate(); |
|
60 DownloadCore *m_downloadCore; |
|
61 ClientDownload *m_download; |
|
62 OMADownloadDescParser *m_parser; // for parsing oma descriptor |
|
63 OMADownloadDescriptor *m_downloadDesc; |
|
64 bool m_isMediaDownload; // flag to indicate if media download is happening |
|
65 MediaDownloadList m_mediaDownloadList; // media downloads |
|
66 int m_currDownloadIndex; |
|
67 int m_currProductIndex; |
|
68 qint64 m_dlCompletedSize; |
|
69 QMap<int, int> m_mediaObjIdStateMap; // map to have the list of Media Objects' id and it's state. |
|
70 QList<QVariant> m_childIds; |
|
71 OMA2DownloadProduct *m_currProduct; |
|
72 OMA2DownloadMediaObj *m_currMediaObj; |
|
73 }; |
|
74 |
|
75 OMA2DownloadBackendPrivate::OMA2DownloadBackendPrivate():m_downloadCore(0) |
|
76 ,m_download(0) |
|
77 ,m_parser(0) |
|
78 ,m_downloadDesc(0) |
|
79 ,m_isMediaDownload(false) |
|
80 ,m_currDownloadIndex(-1) |
|
81 ,m_currProductIndex(0) |
|
82 ,m_dlCompletedSize(0) |
|
83 { } |
|
84 |
|
85 OMA2DownloadBackendPrivate::~OMA2DownloadBackendPrivate() |
|
86 { |
|
87 if (m_parser) { |
|
88 delete m_parser; |
|
89 m_parser = 0; |
|
90 m_downloadDesc = 0; |
|
91 } |
|
92 // In case of persistent storage |
|
93 if (m_downloadDesc) { |
|
94 delete m_downloadDesc; |
|
95 m_downloadDesc = 0; |
|
96 } |
|
97 |
|
98 int count = m_mediaDownloadList.count(); |
|
99 for (int i = 0; i < count; i++) |
|
100 delete m_mediaDownloadList[i]; |
|
101 } |
|
102 |
|
103 OMA2DownloadBackend::OMA2DownloadBackend(DownloadCore *dlCore, ClientDownload *dl) |
|
104 :DownloadBackend(dlCore, dl) |
|
105 { |
|
106 DM_INITIALIZE(OMA2DownloadBackend); |
|
107 priv->m_downloadCore = dlCore; |
|
108 priv->m_download = dl; |
|
109 } |
|
110 |
|
111 OMA2DownloadBackend::~OMA2DownloadBackend() |
|
112 { |
|
113 DM_UNINITIALIZE(OMA2DownloadBackend); |
|
114 } |
|
115 |
|
116 int OMA2DownloadBackend::pause() |
|
117 { |
|
118 DM_PRIVATE(OMA2DownloadBackend); |
|
119 if (priv->m_isMediaDownload) { |
|
120 priv->m_mediaDownloadList[priv->m_currDownloadIndex]->pause(); |
|
121 setDownloadState(DlPaused); |
|
122 } |
|
123 return 0; |
|
124 } |
|
125 |
|
126 int OMA2DownloadBackend::resume() |
|
127 { |
|
128 DM_PRIVATE(OMA2DownloadBackend); |
|
129 if (priv->m_isMediaDownload) |
|
130 return (priv->m_mediaDownloadList[priv->m_currDownloadIndex]->resume()); |
|
131 |
|
132 // Ready to download after the descriptor is parsed |
|
133 // capability check on the descriptor information |
|
134 if (checkDownloadDescriptor()) { |
|
135 ProductList product = priv->m_downloadDesc->productList(); |
|
136 int count = product[priv->m_currProductIndex]->mediaCount(); |
|
137 |
|
138 for (int i=0; i < count; i++) { |
|
139 QUrl baseUrl = priv->m_downloadCore->url(); |
|
140 QUrl relativeUrl = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjServer).toString(); |
|
141 QString url = baseUrl.resolved(relativeUrl).toString(); |
|
142 // create download for media object |
|
143 // id's of media downloads are unique under its parent oma download |
|
144 ClientDownload *dl = new ClientDownload(priv->m_download->downloadManager(), url, (i+1), Parallel |
|
145 , priv->m_download->id() ); |
|
146 if (NULL == dl) |
|
147 return -1; |
|
148 // functions for persistent storage |
|
149 serializeData(dl, i); |
|
150 setValueForChild(DownloadInfo::EUrl, url, dl->id()); |
|
151 setValueForChild(DownloadInfo::EDlState, DlCreated, dl->id()); |
|
152 long state; |
|
153 getValue(DownloadInfo::EDlState, state); |
|
154 priv->m_mediaObjIdStateMap[dl->id()] = state; |
|
155 addtoDownloadList(dl); |
|
156 } |
|
157 setValue(DownloadInfo::EChildIdList, priv->m_childIds); |
|
158 qint64 tSize = product[priv->m_currProductIndex]->albumSize(); |
|
159 setTotalSize(tSize); |
|
160 priv->m_currDownloadIndex = 0; |
|
161 priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start(); |
|
162 priv->m_isMediaDownload = true; |
|
163 return 0; |
|
164 } |
|
165 return -1; |
|
166 } |
|
167 |
|
168 int OMA2DownloadBackend::cancel() |
|
169 { |
|
170 DM_PRIVATE(OMA2DownloadBackend); |
|
171 if (priv->m_isMediaDownload) |
|
172 priv->m_mediaDownloadList[priv->m_currDownloadIndex]->cancel(); |
|
173 else |
|
174 DownloadBackend::cancel(); |
|
175 return 0; |
|
176 } |
|
177 |
|
178 QVariant OMA2DownloadBackend::getAttribute(DownloadAttribute attr) |
|
179 { |
|
180 DM_PRIVATE(OMA2DownloadBackend); |
|
181 // moIndex is zero because when product name is empty the name of 0th Mediaobject should be shown in dd and also the type is of the 0th Mediaobject |
|
182 const int moIndex = 0; |
|
183 QString text = ""; |
|
184 ProductList product; |
|
185 if (priv->m_downloadDesc) |
|
186 product = priv->m_downloadDesc->productList(); |
|
187 switch(attr) { |
|
188 case OMADownloadDescriptorName: |
|
189 { |
|
190 if (product[priv->m_currProductIndex]) { |
|
191 QString name = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString(); |
|
192 if (!name.isEmpty()) |
|
193 return name; |
|
194 if (product[priv->m_currProductIndex]->mediaCount() > 0) |
|
195 return product[priv->m_currProductIndex]->mediaObjList()[moIndex]->getAttribute(OMA2DownloadDescMediaObjName); |
|
196 return text; |
|
197 } |
|
198 return text; |
|
199 } |
|
200 |
|
201 case OMADownloadDescriptorType: |
|
202 { |
|
203 if (product[priv->m_currProductIndex]) { |
|
204 if (product[priv->m_currProductIndex]->mediaCount() > 0) |
|
205 return product[priv->m_currProductIndex]->mediaObjList()[moIndex]->getAttribute(OMA2DownloadDescMediaObjType); |
|
206 return text; |
|
207 } |
|
208 return text; |
|
209 } |
|
210 |
|
211 case OMADownloadDescriptorSize: |
|
212 { |
|
213 qint64 size = 0; |
|
214 if (product[priv->m_currProductIndex]) |
|
215 return product[priv->m_currProductIndex]->albumSize(); |
|
216 return size; |
|
217 } |
|
218 |
|
219 case OMADownloadDescriptorNextURL: |
|
220 { |
|
221 return priv->m_downloadDesc->getAttribute(OMADownloadDescNextURL); |
|
222 } |
|
223 |
|
224 case DlFileName: |
|
225 { |
|
226 if (!priv->m_isMediaDownload) { |
|
227 QString url = priv->m_downloadCore->url(); |
|
228 QFileInfo fileUrl(url); |
|
229 return QVariant(fileUrl.fileName()); |
|
230 } |
|
231 // If the product tag doesn't have a name then display the media object's name in the download list. |
|
232 // This is helpful for single OMA2 download and is done for better user readability |
|
233 if (product[priv->m_currProductIndex]) { |
|
234 QString name = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString(); |
|
235 if (!name.isEmpty()) |
|
236 return name; |
|
237 if (product[priv->m_currProductIndex]->mediaCount() > 0) |
|
238 return product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjName); |
|
239 return text; |
|
240 } |
|
241 return text; |
|
242 } |
|
243 |
|
244 case DlContentType: |
|
245 { |
|
246 if (!priv->m_isMediaDownload) |
|
247 return DownloadBackend::getAttribute(DlContentType); |
|
248 QString contentType = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlContentType).toString(); |
|
249 if (contentType != "") |
|
250 return contentType; |
|
251 QString mediaObjContentType; |
|
252 getValueForChild(DownloadInfo::EContentType, mediaObjContentType, priv->m_childIds[priv->m_currDownloadIndex].toInt()); |
|
253 return mediaObjContentType; |
|
254 } |
|
255 |
|
256 default: |
|
257 return DownloadBackend::getAttribute(attr); |
|
258 } |
|
259 return QVariant(); |
|
260 } |
|
261 |
|
262 int OMA2DownloadBackend::setAttribute(DownloadAttribute attr, const QVariant& value) |
|
263 { |
|
264 return DownloadBackend::setAttribute(attr, value); |
|
265 } |
|
266 |
|
267 // stores the data in storage |
|
268 void OMA2DownloadBackend::store(QByteArray /*data*/, bool /*lastChunk=false*/) |
|
269 { |
|
270 return; |
|
271 } |
|
272 |
|
273 // deletes the storage |
|
274 void OMA2DownloadBackend::deleteStore() |
|
275 { |
|
276 return; |
|
277 } |
|
278 |
|
279 // returns the size of stored data |
|
280 qint64 OMA2DownloadBackend::storedDataSize() |
|
281 { |
|
282 return 0; |
|
283 } |
|
284 |
|
285 void OMA2DownloadBackend::bytesRecieved(qint64 /*bytesRecieved*/, qint64 /*bytesTotal*/) |
|
286 { |
|
287 //Do nothing. This is here to avoid this signal to reach to base class' slot. |
|
288 return; |
|
289 } |
|
290 |
|
291 void OMA2DownloadBackend::bytesUploaded(qint64 bytesUploaded, qint64 bytesTotal) |
|
292 { |
|
293 DM_PRIVATE(OMA2DownloadBackend); |
|
294 // once data is uploaded, cancel the transaction |
|
295 if (bytesUploaded == bytesTotal) |
|
296 priv->m_downloadCore->abort() ; |
|
297 |
|
298 } |
|
299 |
|
300 void OMA2DownloadBackend::handleFinished() |
|
301 { |
|
302 DM_PRIVATE(OMA2DownloadBackend); |
|
303 QString contentType = priv->m_downloadCore->contentType(); |
|
304 if (contentType == OMA2_CONTENT_TYPE) { |
|
305 bool bSucceeded = parseDownloadDescriptor(); |
|
306 priv->m_downloadDesc = priv->m_parser->downloadDescriptor(); |
|
307 if (bSucceeded) { |
|
308 ProductList product = priv->m_downloadDesc->productList(); |
|
309 int count = product[priv->m_currProductIndex]->mediaCount(); |
|
310 if (count == 0) { |
|
311 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor")); |
|
312 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
313 priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor")); |
|
314 setDownloadState(DlFailed); |
|
315 postEvent(Error, NULL); |
|
316 return; |
|
317 } |
|
318 for (int i=0; i < count; i++) { |
|
319 QString server = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjServer).toString(); |
|
320 QString size = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjSize).toString(); |
|
321 QString type = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjType).toString(); |
|
322 if (server.isEmpty() || size.isEmpty() || type.isEmpty()) { |
|
323 QString string; |
|
324 string = product[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjInstallNotifyURI).toString(); |
|
325 priv->m_downloadCore->post(string, QByteArray("905 Attribute Mismatch")); |
|
326 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
327 priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor")); |
|
328 setDownloadState(DlFailed); |
|
329 postEvent(Error, NULL); |
|
330 return; |
|
331 } |
|
332 } |
|
333 // if download is restarted OR suppressUserConfirmation is true, do not show descriptor |
|
334 if (suppressUserConfirmation() || (DlDescriptorUpdated == downloadState())) { |
|
335 resume(); |
|
336 } else { |
|
337 setDownloadState(DlPaused); |
|
338 postEvent(OMADownloadDescriptorReady, NULL); |
|
339 } |
|
340 } else { |
|
341 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor")); |
|
342 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
343 priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor")); |
|
344 setDownloadState(DlFailed); |
|
345 postEvent(Error, NULL); |
|
346 } |
|
347 } |
|
348 } |
|
349 |
|
350 bool OMA2DownloadBackend::parseDownloadDescriptor() |
|
351 { |
|
352 DM_PRIVATE(OMA2DownloadBackend); |
|
353 priv->m_parser = new OMADownloadDescParser(); |
|
354 QXmlInputSource source(priv->m_downloadCore->reply()); |
|
355 QXmlSimpleReader reader; |
|
356 reader.setContentHandler(priv->m_parser); |
|
357 reader.setErrorHandler(priv->m_parser); |
|
358 return reader.parse(source); |
|
359 } |
|
360 |
|
361 // capability check on the descriptor |
|
362 bool OMA2DownloadBackend::checkDownloadDescriptor() |
|
363 { |
|
364 #ifdef Q_OS_LINUX |
|
365 DM_PRIVATE(OMA2DownloadBackend); |
|
366 ProductList product = priv->m_downloadDesc->productList(); |
|
367 double fileSize = product[priv->m_currProductIndex]->albumSize(); |
|
368 double mbFactor = 1024*1024; |
|
369 fileSize = fileSize/mbFactor; //fileSize in MB |
|
370 double spaceLeft = freeSpace(ROOT_PATH); //spaze left in MB |
|
371 |
|
372 if (fileSize > spaceLeft) { |
|
373 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("901 Insufficient memory")); |
|
374 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
375 priv->m_downloadCore->setLastErrorString(tr("901 Insufficient Memory")); |
|
376 setDownloadState(DlFailed); |
|
377 postEvent(Error, NULL); |
|
378 return false; |
|
379 } |
|
380 #endif |
|
381 return true; |
|
382 } |
|
383 |
|
384 bool OMA2DownloadBackend::event(QEvent *event) |
|
385 { |
|
386 DM_PRIVATE(OMA2DownloadBackend); |
|
387 ProductList product = priv->m_downloadDesc->productList(); |
|
388 DownloadEvent* downloadEvent = dynamic_cast<DownloadEvent*>(event); |
|
389 DEventType type = (DEventType)event->type(); |
|
390 switch(type) { |
|
391 case Started: |
|
392 break; |
|
393 case HeaderReceived: |
|
394 { |
|
395 int dlId = ((DownloadEvent*)event)->getId(); |
|
396 if (downloadEvent) { |
|
397 int statusCode = downloadEvent->getAttribute(HeaderReceivedStatusCode).toInt(); |
|
398 handleStatusCode(statusCode); |
|
399 } |
|
400 ClientDownload *dl = findDownload(dlId); |
|
401 // Check the mismatch in total size returned by server with the size given in the descriptor. |
|
402 //This piece of code is commented as-of-now. when needed in future , will be uncommented |
|
403 /*qint64 totalSize = dl->getAttribute(DlTotalSize).toInt(); |
|
404 if(product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjSize).toInt() != totalSize) { |
|
405 postInstallNotifyEvent("905 Attribut Mismatch"); |
|
406 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed; |
|
407 } */ |
|
408 // Check the mismatch in content type returned by server with the content type given in the descriptor. |
|
409 QString contentType = dl->getAttribute(DlContentType).toString(); |
|
410 if(product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjType).toString() != contentType) { |
|
411 postInstallNotifyEvent("905 Attribute Mismatch"); |
|
412 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed; |
|
413 if (priv->m_currDownloadIndex < product[priv->m_currProductIndex]->mediaCount()-1) { |
|
414 priv->m_currDownloadIndex++; |
|
415 priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start(); |
|
416 } |
|
417 } |
|
418 break; |
|
419 } |
|
420 |
|
421 case Progress: |
|
422 { |
|
423 QVariant curDlsize = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlDownloadedSize); |
|
424 qint64 currentDlSize = priv->m_dlCompletedSize + (curDlsize.toInt()); |
|
425 setDownloadedDataSize(currentDlSize); |
|
426 setDownloadState(DlInprogress); |
|
427 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlInprogress; |
|
428 setValueForChild(DownloadInfo::EDlState, DlInprogress, downloadEvent->getId()); |
|
429 postEvent(Progress, NULL); |
|
430 break; |
|
431 } |
|
432 case Paused: |
|
433 { |
|
434 setDownloadState(DlPaused); |
|
435 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlPaused; |
|
436 setValueForChild(DownloadInfo::EDlState, DlPaused, downloadEvent->getId()); |
|
437 postEvent(Paused, NULL); |
|
438 break; |
|
439 } |
|
440 case NetworkLoss: |
|
441 { |
|
442 postEvent(NetworkLoss, NULL); |
|
443 break; |
|
444 } |
|
445 case Cancelled: |
|
446 { |
|
447 postInstallNotifyEvent("902 User Cancelled"); |
|
448 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlCancelled; |
|
449 setValueForChild(DownloadInfo::EDlState, DlCancelled, downloadEvent->getId()); |
|
450 setDownloadState(DlCancelled); |
|
451 postEvent(Cancelled, NULL); |
|
452 break; |
|
453 } |
|
454 case Completed: |
|
455 { |
|
456 postInstallNotifyEvent("900 Success"); |
|
457 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlCompleted; |
|
458 setValueForChild(DownloadInfo::EDlState, DlCompleted, downloadEvent->getId()); |
|
459 QVariant curDlsize = priv->m_mediaDownloadList[priv->m_currDownloadIndex]->getAttribute(DlDownloadedSize); |
|
460 priv->m_dlCompletedSize = priv->m_dlCompletedSize + (curDlsize.toInt()); |
|
461 if (priv->m_currDownloadIndex < product[priv->m_currProductIndex]->mediaCount()-1) { |
|
462 priv->m_currDownloadIndex++; |
|
463 priv->m_mediaDownloadList[priv->m_currDownloadIndex]->start(); |
|
464 } else if (priv->m_currDownloadIndex == product[priv->m_currProductIndex]->mediaCount()-1) |
|
465 verifyDownloads(); |
|
466 break; |
|
467 } |
|
468 case Error: |
|
469 { |
|
470 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
471 priv->m_downloadCore->setLastErrorString(tr("905 Attribute Mismatch")); |
|
472 setDownloadState(DlFailed); |
|
473 postEvent(Error, NULL); |
|
474 priv->m_mediaObjIdStateMap[downloadEvent->getId()] = DlFailed; |
|
475 setValueForChild(DownloadInfo::EDlState, DlFailed, downloadEvent->getId()); |
|
476 break; |
|
477 } |
|
478 default: |
|
479 break; |
|
480 } |
|
481 return true; |
|
482 } |
|
483 |
|
484 void OMA2DownloadBackend::getChildren(QList<Download*>& list) |
|
485 { |
|
486 DM_PRIVATE(OMA2DownloadBackend); |
|
487 for (int i = 0; i < priv->m_mediaDownloadList.count(); i++) |
|
488 list.append(priv->m_mediaDownloadList[i]); |
|
489 |
|
490 } |
|
491 |
|
492 bool OMA2DownloadBackend::suppressUserConfirmation() |
|
493 { |
|
494 DM_PRIVATE(OMA2DownloadBackend); |
|
495 |
|
496 ProductList productList = priv->m_downloadDesc->productList(); |
|
497 QString suppressValue = productList[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductSuppressConfirmation).toString(); |
|
498 QString suppressUserConfirmNever(SuppressUserConfirmation_Never); |
|
499 |
|
500 // If suppressUserConfirmation attribute is present for Product tag, use it and don't check media objects |
|
501 // for this attribute |
|
502 if (!suppressValue.isEmpty()) { |
|
503 if (suppressValue == suppressUserConfirmNever) |
|
504 return false; |
|
505 return true; |
|
506 } |
|
507 |
|
508 int mediaCount = productList[priv->m_currProductIndex]->mediaCount(); |
|
509 // If suppressUserConfirmation is present and it is NOT "Never" for even a single media object, |
|
510 // then treat this as true and do not display user confirmation. |
|
511 QString suppressConfirmMediaObj = ""; |
|
512 |
|
513 for (int i=0; i<mediaCount; ++i) { |
|
514 // If the mediaObject element in DD file has this attribute |
|
515 suppressValue = productList[priv->m_currProductIndex]->mediaObjList()[i]->getAttribute(OMA2DownloadDescMediaObjSuppressConfirmation).toString(); |
|
516 if (!suppressValue.isEmpty()) { |
|
517 // Check if two or more mediObjects have different values for this attribute. |
|
518 // If so, then this is an invalid case. Hence we ignore this attribute. |
|
519 if (suppressConfirmMediaObj.isEmpty()) |
|
520 suppressConfirmMediaObj = suppressValue; |
|
521 else if (suppressConfirmMediaObj != suppressValue) { |
|
522 // Two mediaObjects have different values of suppressUserConfirmation attribute. |
|
523 // Ignore this attribute. |
|
524 return false; |
|
525 } |
|
526 } |
|
527 } |
|
528 |
|
529 // If string is empty OR its value is "Never", return false. |
|
530 if (suppressConfirmMediaObj.isEmpty() || (suppressConfirmMediaObj == suppressUserConfirmNever)) |
|
531 return false; |
|
532 |
|
533 return true; |
|
534 } |
|
535 |
|
536 void OMA2DownloadBackend::handleStatusCode(const int& statusCode) |
|
537 { |
|
538 HttpStatusCode status = (HttpStatusCode)statusCode; |
|
539 switch(status) { |
|
540 case HttpPreconditionFailed: // Precondition Failed |
|
541 { |
|
542 handlePreconditionFailed(); |
|
543 postEvent(DescriptorUpdated, NULL); |
|
544 return; |
|
545 } |
|
546 |
|
547 default: |
|
548 return; |
|
549 } |
|
550 } |
|
551 |
|
552 void OMA2DownloadBackend::handlePreconditionFailed() |
|
553 { |
|
554 DM_PRIVATE(OMA2DownloadBackend); |
|
555 QString updatedDDUri = priv->m_downloadDesc->getAttribute(OMA2DownloadDescUpdatedDDURI).toString(); |
|
556 if (updatedDDUri.isEmpty()) |
|
557 return; |
|
558 |
|
559 DownloadManager* dlMgr = priv->m_download->downloadManager(); |
|
560 if (!dlMgr) |
|
561 return; |
|
562 |
|
563 // Delete all media objects |
|
564 priv->m_isMediaDownload = false; |
|
565 ProductList productList = priv->m_downloadDesc->productList(); |
|
566 int count = productList[priv->m_currProductIndex]->mediaCount(); |
|
567 |
|
568 // Remove all media objects |
|
569 for(int i=0; i<count; ++i) { |
|
570 ClientDownload* dl = priv->m_mediaDownloadList[i]; |
|
571 QCoreApplication::removePostedEvents(this); |
|
572 dl->unregisterEventReceiver(this); |
|
573 priv->m_mediaDownloadList.removeOne(dl); |
|
574 dlMgr->removeOne(dl); |
|
575 } |
|
576 |
|
577 // start download of updated DD |
|
578 priv->m_downloadCore->changeUrl(updatedDDUri); |
|
579 priv->m_downloadCore->doDownload(); |
|
580 setDownloadState(DlDescriptorUpdated); |
|
581 } |
|
582 |
|
583 void OMA2DownloadBackend::addtoDownloadList(ClientDownload* dl) |
|
584 { |
|
585 DM_PRIVATE(OMA2DownloadBackend); |
|
586 dl->registerEventReceiver(this); |
|
587 priv->m_childIds.append(dl->id()); |
|
588 priv->m_mediaDownloadList.append(dl); |
|
589 } |
|
590 |
|
591 ClientDownload* OMA2DownloadBackend::findDownload(int id) |
|
592 { |
|
593 DM_PRIVATE(OMA2DownloadBackend); |
|
594 for (int i = 0; i < priv->m_mediaDownloadList.size(); ++i) { |
|
595 if (priv->m_mediaDownloadList[i]->id() == id) |
|
596 return priv->m_mediaDownloadList[i]; |
|
597 } |
|
598 return 0; |
|
599 } |
|
600 |
|
601 void OMA2DownloadBackend::postInstallNotifyEvent(const char* statusMessage) |
|
602 { |
|
603 DM_PRIVATE(OMA2DownloadBackend); |
|
604 ProductList product = priv->m_downloadDesc->productList(); |
|
605 QString string; |
|
606 string = product[priv->m_currProductIndex]->mediaObjList()[priv->m_currDownloadIndex]->getAttribute(OMA2DownloadDescMediaObjInstallNotifyURI).toString(); |
|
607 priv->m_downloadCore->post(string, QByteArray(statusMessage)); |
|
608 } |
|
609 |
|
610 void OMA2DownloadBackend::verifyDownloads() |
|
611 { |
|
612 DM_PRIVATE(OMA2DownloadBackend); |
|
613 // go throught the mediaObjmap of id, state value pair and if any dl is failed then set the state of parent as paused. |
|
614 ProductList product = priv->m_downloadDesc->productList(); |
|
615 int counter = 0; |
|
616 for (int i=0; i < priv->m_childIds.count(); i++) { |
|
617 if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlCompleted) |
|
618 counter++; |
|
619 else if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlFailed) { |
|
620 setDownloadState(DlFailed); |
|
621 postEvent(Error, NULL); |
|
622 break; |
|
623 } |
|
624 } |
|
625 if (counter == priv->m_childIds.count()) { |
|
626 setDownloadState(DlCompleted); |
|
627 postEvent(Completed, NULL); |
|
628 } |
|
629 } |
|
630 |
|
631 int OMA2DownloadBackend::currentIndex() |
|
632 { |
|
633 // If a download is in progress and closed, a track in an album is either paused or created. |
|
634 // This function as part of persistant storage,returns the index of the download which is either in paused or created state |
|
635 DM_PRIVATE(OMA2DownloadBackend); |
|
636 ProductList product = priv->m_downloadDesc->productList(); |
|
637 for (int i=0; i < priv->m_childIds.count(); i++) { |
|
638 if (priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlPaused |
|
639 || priv->m_mediaObjIdStateMap[priv->m_childIds[i].toInt()] == DlCreated) { |
|
640 priv->m_currDownloadIndex = i; |
|
641 break; |
|
642 } |
|
643 } |
|
644 return priv->m_currDownloadIndex; |
|
645 } |
|
646 |
|
647 void OMA2DownloadBackend::init() |
|
648 { |
|
649 DM_PRIVATE(OMA2DownloadBackend); |
|
650 priv->m_isMediaDownload = true; // since init() is called during restoring the persistent info, the flag should be set to true. |
|
651 |
|
652 priv->m_downloadDesc = new OMADownloadDescriptor(); |
|
653 priv->m_currProduct = new OMA2DownloadProduct(); |
|
654 priv->m_downloadDesc->addProduct(priv->m_currProduct); |
|
655 // populating the product map |
|
656 QString productName; |
|
657 getValue(DownloadInfo::EFileName, productName); |
|
658 priv->m_currProduct->setAttribute("name", QVariant(productName)); |
|
659 |
|
660 QList<QVariant> id; |
|
661 getValue(DownloadInfo::EChildIdList, id); |
|
662 QString oma2ContentType,mediaObjName,mediaObjUrl,mediaObjContentType; |
|
663 long mediaObjSize; |
|
664 long state; |
|
665 priv->m_currProductIndex = 0; |
|
666 for(int i=0; i<id.size(); i++) { |
|
667 //populating the mediaobj map |
|
668 priv->m_currMediaObj = new OMA2DownloadMediaObj(); |
|
669 priv->m_currProduct->addMediaObject(priv->m_currMediaObj); |
|
670 |
|
671 // getting all the values related to media object for populating descriptor's mediaobj map |
|
672 getValueForChild(DownloadInfo::EFileName, mediaObjName, id[i].toInt()); |
|
673 getValueForChild(DownloadInfo::ETotalSize, mediaObjSize, id[i].toInt()); |
|
674 getValueForChild(DownloadInfo::EUrl, mediaObjUrl, id[i].toInt()); |
|
675 getValueForChild(DownloadInfo::EContentType, mediaObjContentType, id[i].toInt()); |
|
676 getValueForChild(DownloadInfo::EDlState, state, id[i].toInt()); |
|
677 priv->m_mediaObjIdStateMap[id[i].toInt()] = state; |
|
678 |
|
679 // creaating downloads for the media objects |
|
680 ClientDownload *dl = NULL; |
|
681 if (state == DlCreated) { |
|
682 dl = new ClientDownload(priv->m_download->downloadManager(), mediaObjUrl, id[i].toInt(), Parallel |
|
683 , priv->m_download->id() ); |
|
684 } |
|
685 else |
|
686 dl = new ClientDownload(priv->m_download->downloadManager(), id[i].toInt(), priv->m_download->id()); |
|
687 |
|
688 setValueForChild(DownloadInfo::EDlState, priv->m_mediaObjIdStateMap[id[i].toInt()], id[i].toInt()); |
|
689 addtoDownloadList(dl); |
|
690 // re-constructing descriptor's mediaobj map |
|
691 priv->m_currMediaObj->setAttribute("name", QVariant(mediaObjName)); |
|
692 int size = mediaObjSize; |
|
693 priv->m_currMediaObj->setAttribute("size", QVariant(size)); |
|
694 priv->m_currMediaObj->setAttribute("type", QVariant(mediaObjContentType)); |
|
695 priv->m_currMediaObj->setAttribute("server",QVariant(mediaObjUrl)); |
|
696 } |
|
697 ProductList product = priv->m_downloadDesc->productList(); |
|
698 getValue(DownloadInfo::EDlState,state); |
|
699 if(state == DlCompleted) |
|
700 priv->m_currDownloadIndex = product[priv->m_currProductIndex]->mediaCount()-1; |
|
701 else |
|
702 priv->m_currDownloadIndex = currentIndex(); |
|
703 } |
|
704 |
|
705 void OMA2DownloadBackend::serializeData(ClientDownload* dl, int index) |
|
706 { |
|
707 DM_PRIVATE(OMA2DownloadBackend); |
|
708 ProductList product = priv->m_downloadDesc->productList(); |
|
709 // set OMA2 parent values in QSettings. |
|
710 QString productName = product[priv->m_currProductIndex]->getAttribute(OMA2DownloadDescProductName).toString(); // contenttype,url being written in dlbackend's constructor |
|
711 setValue(DownloadInfo::EFileName, productName); |
|
712 |
|
713 // set minimal MediaObject attributes in QSettings like name, size, url and contentType as these are the ones required for persistent storage. |
|
714 QString mediaObjName = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjName).toString(); |
|
715 setValueForChild(DownloadInfo::EFileName, mediaObjName, dl->id()); |
|
716 long mediaObjSize = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjSize).toInt(); |
|
717 setValueForChild(DownloadInfo::ETotalSize, mediaObjSize, dl->id()); |
|
718 QString mediaObjContentType = product[priv->m_currProductIndex]->mediaObjList()[index]->getAttribute(OMA2DownloadDescMediaObjType).toString(); |
|
719 setValueForChild(DownloadInfo::EContentType, mediaObjContentType, dl->id()); |
|
720 QString destPath = (download()->attributes().value(DlDestPath)).toString(); |
|
721 setValueForChild(DownloadInfo::EFinalPath, destPath, dl->id()); |
|
722 setValueForChild(DownloadInfo::EETag, priv->m_downloadCore->entityTag(), dl->id()); //not getting set check later |
|
723 } |