|
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 "omadownloadbackend.h" |
|
18 #include "omaddparser.h" |
|
19 #include "downloadmanager.h" |
|
20 #include "clientdownload.h" |
|
21 #include "downloadcore.h" |
|
22 #include "downloadevent.h" |
|
23 #include <QCoreApplication> |
|
24 #include <QFileInfo> |
|
25 |
|
26 #ifdef Q_OS_LINUX |
|
27 #include <sys/statvfs.h> |
|
28 #endif |
|
29 |
|
30 #ifdef Q_OS_LINUX |
|
31 static double freeSpace(const char *path) |
|
32 #else |
|
33 static double freeSpace(const char* /*path*/) |
|
34 #endif |
|
35 { |
|
36 #ifdef Q_OS_LINUX |
|
37 struct statvfs fiData; |
|
38 if ((statvfs(path,&fiData)) < 0 ) |
|
39 return 0; |
|
40 else { |
|
41 int blockSize = fiData.f_bsize/1024; |
|
42 double freeSize = (fiData.f_bavail)*blockSize; |
|
43 freeSize = freeSize/1024; |
|
44 return freeSize; |
|
45 } |
|
46 #endif |
|
47 return 0; |
|
48 } |
|
49 |
|
50 // private implementation |
|
51 class OMADownloadBackendPrivate { |
|
52 DM_DECLARE_PUBLIC(OMADownloadBackend); |
|
53 public: |
|
54 OMADownloadBackendPrivate(); |
|
55 ~OMADownloadBackendPrivate(); |
|
56 |
|
57 DownloadCore *m_downloadCore; |
|
58 ClientDownload *m_download; |
|
59 OMADownloadDescParser *m_parser; // for parsing oma descriptor |
|
60 OMADownloadDescriptor *m_downloadDesc; |
|
61 bool m_isMediaDownload; // flag to indicate if media download is happening |
|
62 ClientDownload *m_mediaDownload; // not owned |
|
63 bool m_isUserCancelled; |
|
64 }; |
|
65 |
|
66 OMADownloadBackendPrivate::OMADownloadBackendPrivate() |
|
67 { |
|
68 m_downloadCore = 0; |
|
69 m_download = 0; |
|
70 m_parser = 0; |
|
71 m_downloadDesc = 0; |
|
72 m_isMediaDownload = false; |
|
73 m_mediaDownload = 0; |
|
74 m_isUserCancelled = false; |
|
75 } |
|
76 |
|
77 OMADownloadBackendPrivate::~OMADownloadBackendPrivate() |
|
78 { |
|
79 if (m_parser) { |
|
80 delete m_parser; |
|
81 m_parser = 0; |
|
82 m_downloadDesc = 0; |
|
83 } |
|
84 if (m_mediaDownload) { |
|
85 delete m_mediaDownload; |
|
86 m_mediaDownload = NULL; |
|
87 } |
|
88 } |
|
89 |
|
90 OMADownloadBackend::OMADownloadBackend(DownloadCore *dlCore, ClientDownload *dl) |
|
91 :DownloadBackend(dlCore, dl) |
|
92 { |
|
93 DM_INITIALIZE(OMADownloadBackend); |
|
94 priv->m_downloadCore = dlCore; |
|
95 priv->m_download = dl; |
|
96 } |
|
97 |
|
98 OMADownloadBackend::~OMADownloadBackend() |
|
99 { |
|
100 DM_UNINITIALIZE(OMADownloadBackend); |
|
101 } |
|
102 |
|
103 int OMADownloadBackend::pause() |
|
104 { |
|
105 DM_PRIVATE(OMADownloadBackend); |
|
106 if (priv->m_isMediaDownload) { |
|
107 priv->m_mediaDownload->pause(); |
|
108 setDownloadState(DlPaused); |
|
109 } |
|
110 return 0; |
|
111 } |
|
112 |
|
113 int OMADownloadBackend::resume() |
|
114 { |
|
115 DM_PRIVATE(OMADownloadBackend); |
|
116 priv->m_isUserCancelled = false; |
|
117 if (priv->m_isMediaDownload) |
|
118 return (priv->m_mediaDownload->resume()); |
|
119 |
|
120 // Ready to download after the descriptor is parsed |
|
121 // capability check on the descriptor information |
|
122 if (checkDownloadDescriptor()) { |
|
123 // create download for media object |
|
124 priv->m_mediaDownload = new ClientDownload(priv->m_download->downloadManager(), |
|
125 priv->m_downloadDesc->getAttribute(OMADownloadDescObjectURI).toString(), priv->m_download->id()); |
|
126 |
|
127 if (!priv->m_mediaDownload) { |
|
128 deleteInfo(); |
|
129 return -1; |
|
130 } |
|
131 priv->m_mediaDownload->setAttribute(DlFileName, priv->m_downloadDesc->getAttribute(OMADownloadDescName)); |
|
132 priv->m_mediaDownload->registerEventReceiver(this); |
|
133 priv->m_mediaDownload->start(); |
|
134 priv->m_isMediaDownload = true; |
|
135 deleteInfo(); |
|
136 return 0; |
|
137 } |
|
138 return -1; |
|
139 } |
|
140 |
|
141 int OMADownloadBackend::cancel() |
|
142 { |
|
143 DM_PRIVATE(OMADownloadBackend); |
|
144 priv->m_isUserCancelled = true; |
|
145 if (priv->m_isMediaDownload) |
|
146 priv->m_mediaDownload->cancel(); |
|
147 else |
|
148 DownloadBackend::cancel(); |
|
149 return 0; |
|
150 } |
|
151 |
|
152 QVariant OMADownloadBackend::getAttribute(DownloadAttribute attr) |
|
153 { |
|
154 DM_PRIVATE(OMADownloadBackend); |
|
155 switch(attr) { |
|
156 case OMADownloadDescriptorName: |
|
157 return priv->m_downloadDesc->getAttribute(OMADownloadDescName); |
|
158 case OMADownloadDescriptorVersion: |
|
159 return priv->m_downloadDesc->getAttribute(OMADownloadDescVersion); |
|
160 case OMADownloadDescriptorType: |
|
161 return priv->m_downloadDesc->getAttribute(OMADownloadDescType); |
|
162 case OMADownloadDescriptorSize: |
|
163 return priv->m_downloadDesc->getAttribute(OMADownloadDescSize); |
|
164 case OMADownloadDescriptorVendor: |
|
165 return priv->m_downloadDesc->getAttribute(OMADownloadDescVendor); |
|
166 case OMADownloadDescriptorDescription: |
|
167 return priv->m_downloadDesc->getAttribute(OMADownloadDescDescription); |
|
168 |
|
169 case DlFileName: |
|
170 { |
|
171 if (!priv->m_isMediaDownload) { |
|
172 QString url = priv->m_downloadCore->url(); |
|
173 QFileInfo fileUrl(url); |
|
174 return QVariant(fileUrl.fileName()); |
|
175 } else |
|
176 return priv->m_downloadDesc->getAttribute(OMADownloadDescName); |
|
177 } |
|
178 case DlContentType: |
|
179 { |
|
180 if (!priv->m_isMediaDownload) |
|
181 return DownloadBackend::getAttribute(DlContentType); |
|
182 |
|
183 else |
|
184 return priv->m_mediaDownload->getAttribute(DlContentType); |
|
185 } |
|
186 default: |
|
187 return DownloadBackend::getAttribute(attr); |
|
188 } |
|
189 return QVariant(); |
|
190 } |
|
191 |
|
192 int OMADownloadBackend::setAttribute(DownloadAttribute attr, const QVariant& value) |
|
193 { |
|
194 return DownloadBackend::setAttribute(attr, value); |
|
195 } |
|
196 |
|
197 // stores the data in storage |
|
198 void OMADownloadBackend::store(QByteArray /*data*/, bool /*lastChunk=false*/) |
|
199 { |
|
200 return; |
|
201 } |
|
202 |
|
203 // deletes the storage |
|
204 void OMADownloadBackend::deleteStore() |
|
205 { |
|
206 return; |
|
207 } |
|
208 |
|
209 // returns the size of stored data |
|
210 qint64 OMADownloadBackend::storedDataSize() |
|
211 { |
|
212 return 0; |
|
213 } |
|
214 |
|
215 void OMADownloadBackend::bytesRecieved(qint64 /*bytesRecieved*/, qint64 /*bytesTotal*/) |
|
216 { |
|
217 //Do nothing. This is here to avoid this signal to reach to base class' slot. |
|
218 return; |
|
219 } |
|
220 |
|
221 void OMADownloadBackend::bytesUploaded(qint64 bytesUploaded, qint64 bytesTotal) |
|
222 { |
|
223 DM_PRIVATE(OMADownloadBackend); |
|
224 // once data is uploaded, cancel the transaction |
|
225 if (bytesUploaded == bytesTotal) |
|
226 priv->m_downloadCore->abort() ; |
|
227 } |
|
228 |
|
229 void OMADownloadBackend::handleFinished() |
|
230 { |
|
231 DM_PRIVATE(OMADownloadBackend); |
|
232 QString contentType = priv->m_downloadCore->contentType(); |
|
233 if (contentType == OMA_CONTENT_TYPE) { |
|
234 bool bSucceeded = parseDownloadDescriptor(); |
|
235 if (bSucceeded) { |
|
236 priv->m_downloadDesc = priv->m_parser->downloadDescriptor(); |
|
237 |
|
238 QString objectURI = priv->m_downloadDesc->getAttribute(OMADownloadDescObjectURI).toString(); |
|
239 if (objectURI.isEmpty()) { |
|
240 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("905 Attribute Mismatch")); |
|
241 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
242 priv->m_downloadCore->setLastErrorString(tr("No ObjectURI")); |
|
243 setDownloadState(DlFailed); |
|
244 postEvent(Error, NULL); |
|
245 return; |
|
246 } |
|
247 setDownloadState(DlPaused); |
|
248 postEvent(OMADownloadDescriptorReady, NULL); |
|
249 } else { |
|
250 priv->m_downloadDesc = priv->m_parser->downloadDescriptor(); |
|
251 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("906 Invalid descriptor")); |
|
252 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
253 priv->m_downloadCore->setLastErrorString(tr("Invalid Descriptor")); |
|
254 setDownloadState(DlFailed); |
|
255 postEvent(Error, NULL); |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 bool OMADownloadBackend::parseDownloadDescriptor() |
|
261 { |
|
262 DM_PRIVATE(OMADownloadBackend); |
|
263 priv->m_parser = new OMADownloadDescParser(); |
|
264 QXmlInputSource source(priv->m_downloadCore->reply()); |
|
265 QXmlSimpleReader reader; |
|
266 reader.setContentHandler(priv->m_parser); |
|
267 reader.setErrorHandler(priv->m_parser); |
|
268 return reader.parse(source); |
|
269 } |
|
270 |
|
271 // capability check on the descriptor |
|
272 bool OMADownloadBackend::checkDownloadDescriptor() |
|
273 { |
|
274 DM_PRIVATE(OMADownloadBackend); |
|
275 |
|
276 QString version = priv->m_downloadDesc->getAttribute(OMADownloadDescVersion).toString(); |
|
277 if (! version.isEmpty() && (version != OMA_VERSION_1)) { |
|
278 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("951 Invalid DDVersion")); |
|
279 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
280 priv->m_downloadCore->setLastErrorString(tr("951 Invalid DDVersion")); |
|
281 setDownloadState(DlFailed); |
|
282 postEvent(Error, NULL); |
|
283 return false; |
|
284 } |
|
285 |
|
286 #ifdef Q_OS_LINUX |
|
287 // "Size" check needs to be done |
|
288 double fileSize = priv->m_downloadDesc->getAttribute(OMADownloadDescSize).toDouble(); |
|
289 double mbFactor = 1024*1024; |
|
290 fileSize = fileSize/mbFactor; //fileSize in MB |
|
291 double spaceLeft = freeSpace(ROOT_PATH); //spaze left in MB |
|
292 |
|
293 if (fileSize > spaceLeft) { |
|
294 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("901 Insufficient memory")); |
|
295 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
296 priv->m_downloadCore->setLastErrorString(tr("901 Insufficient Memory")); |
|
297 setDownloadState(DlFailed); |
|
298 postEvent(Error, NULL); |
|
299 return false; |
|
300 } |
|
301 #endif |
|
302 return true; |
|
303 } |
|
304 |
|
305 bool OMADownloadBackend::event(QEvent *event) |
|
306 { |
|
307 DM_PRIVATE(OMADownloadBackend); |
|
308 DEventType type = (DEventType)event->type(); |
|
309 switch(type) { |
|
310 case Started: |
|
311 break; |
|
312 case HeaderReceived: |
|
313 { |
|
314 // handling the events from media object downloads |
|
315 // Check the mismatch in total size returned by server with the size given in the descriptor. |
|
316 //This piece of code is commented as-of-now. when needed in future , will be uncommented |
|
317 /*int totalSize = dl->getAttribute(DlTotalSize).toInt(); |
|
318 if (priv->m_downloadDesc->getAttribute(OMADownloadDescSize).toInt() != totalSize) |
|
319 { |
|
320 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("905 Attribute Mismatch")); |
|
321 |
|
322 if (dl) |
|
323 { |
|
324 dl->setError("905 Attribute Mismatch"); |
|
325 dl->cancel(); |
|
326 dl->setDownloadState(DlFailed); |
|
327 dl->postEvent(Error, NULL); |
|
328 } |
|
329 return true; |
|
330 }*/ |
|
331 // Check the mismatch in content type returned by server with the content type given in the descriptor. |
|
332 QString contentType = priv->m_mediaDownload->getAttribute(DlContentType).toString(); |
|
333 if (priv->m_downloadDesc->getAttribute(OMADownloadDescType).toString() != contentType) { |
|
334 // media object download cannot be proceeded |
|
335 if (priv->m_mediaDownload) { |
|
336 priv->m_mediaDownload->setError("905 Attribute Mismatch"); |
|
337 priv->m_mediaDownload->cancel(); |
|
338 priv->m_mediaDownload->setDownloadState(DlFailed); |
|
339 priv->m_mediaDownload->postEvent(Error, NULL); |
|
340 } |
|
341 break; |
|
342 } |
|
343 } |
|
344 case Progress: |
|
345 { |
|
346 QVariant tSize = priv->m_mediaDownload->getAttribute(DlTotalSize); |
|
347 setTotalSize(tSize.toInt()); |
|
348 QVariant curDlsize = priv->m_mediaDownload->getAttribute(DlDownloadedSize); |
|
349 setDownloadedDataSize(curDlsize.toInt()); |
|
350 setDownloadState(DlInprogress); |
|
351 postEvent(Progress, NULL); |
|
352 break; |
|
353 } |
|
354 case NetworkLoss: |
|
355 { |
|
356 postEvent(NetworkLoss, NULL); |
|
357 break; |
|
358 } |
|
359 case Cancelled: |
|
360 { |
|
361 if (priv->m_isUserCancelled) |
|
362 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("902 User Cancelled")); |
|
363 setDownloadState(DlCancelled); |
|
364 postEvent(Cancelled, NULL); |
|
365 break; |
|
366 } |
|
367 case Completed: |
|
368 { |
|
369 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("900 Success ")); |
|
370 setDownloadState(DlCompleted); |
|
371 postEvent(Completed, NULL); |
|
372 break; |
|
373 } |
|
374 case Error: |
|
375 { |
|
376 priv->m_downloadCore->post(priv->m_downloadDesc->getAttribute(OMADownloadDescInstallNotifyURI).toString(), QByteArray("905 Attribute Mismatch")); |
|
377 priv->m_downloadCore->setLastError(QNetworkReply::UnknownContentError); |
|
378 priv->m_downloadCore->setLastErrorString(tr("905 Attribute Mismatch")); |
|
379 setDownloadState(DlFailed); |
|
380 postEvent(Error, NULL); |
|
381 break; |
|
382 } |
|
383 default: |
|
384 break; |
|
385 } |
|
386 return true; |
|
387 } |
|
388 |
|
389 |