Code Sync with Private GIT
[apps/web/download-manager.git] / src / download-manager-downloadItem.cpp
1 /*
2  * Copyright 2012  Samsung Electronics Co., Ltd
3  *
4  * Licensed under the Flora License, Version 1.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.tizenopensource.org/license
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file        download-manager-downloadItem.cpp
19  * @author      Jungki Kwak (jungki.kwak@samsung.com)
20  * @brief       download item class for interface of download agent
21  */
22
23 #include <Ecore.h>
24 #include <iostream>
25 #include "download-manager-downloadItem.h"
26 #include "download-manager-common.h"
27 #include "app_service.h"
28
29 static Ecore_Pipe *ecore_pipe = NULL;
30 static void __ecore_cb_pipe_update(void *data, void *buffer, unsigned int nbyte);
31
32 namespace DA_CB {
33 enum TYPE {
34         STARTED = 1,
35         PROGRESS,
36         PAUSED,
37         COMPLETED,
38         STOPPED
39 };
40 }
41
42 class CbData {
43 public:
44         CbData() {}
45         ~CbData() {}
46
47         void updateDownloadItem();
48
49         inline void setType(DA_CB::TYPE type) { m_type = type; }
50         inline void setUserData(void *userData) { m_userData = userData; }
51         inline void setDownloadHandle(url_download_h handle) { m_download_handle = handle; }
52         inline void setReceivedFileSize(unsigned long int size) { m_receivedFileSize = size; }
53         inline void setFileSize(unsigned long int size) { m_fileSize = size; }
54         inline void setContentName(const char *name) { if (name) m_contentName = name; }
55         inline void setRegisteredFilePath(const char *path) { if (path) m_registeredFilePath = path; }
56         inline void setMimeType(const char *mime) { m_mimeType = mime; }
57         inline void setErrorCode(int err) { m_error = err;      }
58
59 private:
60         DA_CB::TYPE m_type;
61         void *m_userData;
62         url_download_h m_download_handle;
63         int m_error;
64         unsigned long int m_receivedFileSize;
65         unsigned long int m_fileSize;
66         string m_contentName;
67         string m_registeredFilePath;
68         string m_mimeType;
69 };
70
71 struct pipe_data_t {
72         CbData *cbData;
73 };
74
75 DownloadEngine::DownloadEngine()
76 {
77 }
78
79 DownloadEngine::~DownloadEngine()
80 {
81         DP_LOG_FUNC();
82 }
83
84 void DownloadEngine::initEngine(void)
85 {
86         ecore_pipe = ecore_pipe_add(__ecore_cb_pipe_update, NULL);
87 }
88
89 void DownloadEngine::deinitEngine(void)
90 {
91         DP_LOG_FUNC();
92         if (ecore_pipe) {
93                 ecore_pipe_del(ecore_pipe);
94                 ecore_pipe = NULL;
95         }
96 }
97
98 void CbData::updateDownloadItem()
99 {
100 //      DP_LOGD_FUNC();
101
102         if (!m_userData) {
103                 DP_LOGE("download item is NULL");
104                 return;
105         }
106
107         DownloadItem *downloadItem = static_cast<DownloadItem*>(m_userData);
108         if (downloadItem->state() == DL_ITEM::FAILED) {
109                 DP_LOGE("download item is already failed");
110                 return;
111         }
112         downloadItem->setDownloadHandle(m_download_handle);
113
114         switch(m_type) {
115         case DA_CB::STARTED:
116                 downloadItem->setState(DL_ITEM::STARTED);
117                 //downloadItem->setFileSize(m_fileSize);
118                 if (!m_contentName.empty())
119                         downloadItem->setContentName(m_contentName);
120                 if (!m_mimeType.empty())
121                         downloadItem->setMimeType(m_mimeType);
122                 break;
123         case DA_CB::PROGRESS:
124                 downloadItem->setState(DL_ITEM::UPDATING);
125                 downloadItem->setFileSize(m_fileSize);
126                 downloadItem->setReceivedFileSize(m_receivedFileSize);
127                 break;
128         case DA_CB::PAUSED:
129                 downloadItem->setState(DL_ITEM::SUSPENDED);
130                 downloadItem->setFileSize(m_fileSize);
131                 downloadItem->setReceivedFileSize(m_receivedFileSize);
132                 break;
133         case DA_CB::COMPLETED:
134                 downloadItem->setState(DL_ITEM::FINISHED);
135                 if (!m_registeredFilePath.empty()) {
136                         DP_LOGD("registeredFilePath[%s]", m_registeredFilePath.c_str());
137                         downloadItem->setRegisteredFilePath(m_registeredFilePath);
138                 }
139                 downloadItem->destroyHandle();
140                 break;
141         case DA_CB::STOPPED:
142                 if (m_error != URL_DOWNLOAD_ERROR_NONE) {
143                         downloadItem->setState(DL_ITEM::FAILED);
144                         downloadItem->setErrorCode(downloadItem->_convert_error(m_error));
145                 } else {
146                         downloadItem->setState(DL_ITEM::CANCELED);
147                 }
148                 downloadItem->destroyHandle();
149                 break;
150         default:
151                 break;
152         }
153         downloadItem->notify();
154 }
155
156 void __ecore_cb_pipe_update(void *data, void *buffer, unsigned int nbyte)
157 {
158 //      DP_LOGD_FUNC();
159
160         if (!buffer)
161                 return;
162         pipe_data_t *pipe_data = static_cast<pipe_data_t *>(buffer);
163         CbData *cbData = pipe_data->cbData;
164         if (!cbData)
165                 return;
166
167         cbData->updateDownloadItem();
168         delete cbData;
169 }
170
171 DownloadItem::DownloadItem()
172         : m_download_handle(NULL)
173         , m_state(DL_ITEM::IGNORE)
174         , m_errorCode(ERROR::NONE)
175         , m_receivedFileSize(0)
176         , m_fileSize(0)
177         , m_downloadType(DL_TYPE::HTTP_DOWNLOAD)
178 {
179 }
180
181 DownloadItem::DownloadItem(auto_ptr<DownloadRequest> request)
182         : m_aptr_request(request)
183         , m_download_handle(NULL)
184         , m_state(DL_ITEM::IGNORE)
185         , m_errorCode(ERROR::NONE)
186         , m_receivedFileSize(0)
187         , m_fileSize(0)
188         , m_downloadType(DL_TYPE::HTTP_DOWNLOAD)
189 {
190 }
191
192 void DownloadItem::createHandle()
193 {
194         int ret = url_download_create(&m_download_handle);
195         if (ret != URL_DOWNLOAD_ERROR_NONE) {
196                 DP_LOGE("Fail to create download handle : [%d]", ret);
197                 return;
198         }
199         DP_LOGD("URL download handle : [%p]", m_download_handle);
200         ret = url_download_set_started_cb(m_download_handle, started_cb, static_cast<void*>(this));
201         if (ret != URL_DOWNLOAD_ERROR_NONE) {
202                 DP_LOGE("Fail to set started callback : [%d]", ret);
203                 return;
204         }
205
206         ret = url_download_set_completed_cb(m_download_handle, completed_cb, static_cast<void*>(this));
207         if (ret != URL_DOWNLOAD_ERROR_NONE) {
208                 DP_LOGE("Fail to set completed cb : [%d]", ret);
209                 return;
210         }
211
212         ret = url_download_set_paused_cb(m_download_handle, paused_cb, static_cast<void*>(this));
213         if (ret != URL_DOWNLOAD_ERROR_NONE) {
214                 DP_LOGE("Fail to set paused cb : [%d]", ret);
215                 return;
216         }
217
218         ret = url_download_set_stopped_cb(m_download_handle, stopped_cb, static_cast<void*>(this));
219         if (ret != URL_DOWNLOAD_ERROR_NONE) {
220                 DP_LOGE("Fail to set stopped cb : [%d]", ret);
221                 return;
222         }
223
224         ret = url_download_set_progress_cb(m_download_handle, progress_cb, static_cast<void*>(this));
225         if (ret != URL_DOWNLOAD_ERROR_NONE) {
226                 DP_LOGE("Fail to set progress cb : [%d]", ret);
227                 return;
228         }
229
230         service_h service_handle;
231         ret = service_create(&service_handle);
232         if (ret < 0) {
233                 DP_LOGE("Fail to create service handle");
234                 return;
235         }
236
237         ret = service_set_package(service_handle, PACKAGE_NAME);
238         if (ret < 0) {
239                 DP_LOGE("Fail to set package name");
240                 return;
241         }
242         ret = url_download_set_notification(m_download_handle, service_handle);
243         if (ret != URL_DOWNLOAD_ERROR_NONE) {
244                 DP_LOGE("Fail to set notification : [%d]", ret);
245                 return;
246         }
247         ret = service_destroy(service_handle);
248         if (ret < 0) {
249                 DP_LOGE("Fail to create service handle");
250                 return;
251         }
252 }
253
254 DownloadItem::~DownloadItem()
255 {
256         DP_LOGD_FUNC();
257         destroyHandle();
258 }
259
260 void DownloadItem::destroyHandle()
261 {
262         if (!m_download_handle)
263                 return;
264         DP_LOGD("download handle[%p]", m_download_handle);
265         url_download_unset_started_cb(m_download_handle);
266         url_download_unset_completed_cb(m_download_handle);
267         url_download_unset_paused_cb(m_download_handle);
268         url_download_unset_stopped_cb(m_download_handle);
269         url_download_unset_progress_cb(m_download_handle);
270         url_download_destroy(m_download_handle);
271         m_download_handle = NULL;
272 }
273
274 void DownloadItem::started_cb(url_download_h download, const char *name,
275         const char *mime, void *user_data)
276 {
277
278         CbData *cbData = new CbData();
279         cbData->setType(DA_CB::STARTED);
280         cbData->setDownloadHandle(download);
281         cbData->setUserData(user_data);
282         if (name)
283                 cbData->setContentName(name);
284         if (mime)
285                 cbData->setMimeType(mime);
286
287         pipe_data_t pipe_data;
288         pipe_data.cbData = cbData;
289         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
290 }
291
292 void DownloadItem::paused_cb(url_download_h download, void *user_data)
293 {
294         CbData *cbData = new CbData();
295         cbData->setType(DA_CB::PAUSED);
296         cbData->setDownloadHandle(download);
297         cbData->setUserData(user_data);
298
299         pipe_data_t pipe_data;
300         pipe_data.cbData = cbData;
301         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
302 }
303
304 void DownloadItem::completed_cb(url_download_h download, const char *path,
305         void *user_data)
306 {
307         CbData *cbData = new CbData();
308         cbData->setType(DA_CB::COMPLETED);
309         cbData->setDownloadHandle(download);
310         cbData->setUserData(user_data);
311         cbData->setRegisteredFilePath(path);
312
313         pipe_data_t pipe_data;
314         pipe_data.cbData = cbData;
315         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
316 }
317
318 void DownloadItem::stopped_cb(url_download_h download, url_download_error_e error,
319         void *user_data)
320 {
321         CbData *cbData = new CbData();
322         cbData->setType(DA_CB::STOPPED);
323         cbData->setDownloadHandle(download);
324         cbData->setUserData(user_data);
325         cbData->setErrorCode(error);
326
327         pipe_data_t pipe_data;
328         pipe_data.cbData = cbData;
329         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
330 }
331
332 void DownloadItem::progress_cb(url_download_h download, unsigned long long received,
333         unsigned long long total, void *user_data)
334 {
335         CbData *cbData = new CbData();
336         cbData->setType(DA_CB::PROGRESS);
337         cbData->setDownloadHandle(download);
338         cbData->setUserData(user_data);
339         cbData->setFileSize(total);
340         cbData->setReceivedFileSize(received);
341 // need to tmp path??
342
343         pipe_data_t pipe_data;
344         pipe_data.cbData = cbData;
345         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
346 }
347
348 void DownloadItem::start(bool isRetry)
349 {
350         int ret = 0;
351         DP_LOGD_FUNC();
352         if (m_download_handle) {
353                 destroyHandle();
354         }
355         createHandle();
356
357         ret = url_download_set_url(m_download_handle,
358                         m_aptr_request->getUrl().c_str());
359         if (ret != URL_DOWNLOAD_ERROR_NONE) {
360                 DP_LOGE("Fail to set url : [%d]", ret);
361                 m_state = DL_ITEM::FAILED;
362                 m_errorCode = ERROR::ENGINE_FAIL;
363                 notify();
364                 return;
365         }
366         if (!m_aptr_request->getCookie().empty()) {
367                 ret = url_download_add_http_header_field(m_download_handle,
368                                 "Cookie", m_aptr_request->getCookie().c_str());
369                 if (ret != URL_DOWNLOAD_ERROR_NONE) {
370                         DP_LOGE("Fail to set cookie : [%d]", ret);
371                         m_state = DL_ITEM::FAILED;
372                         m_errorCode = ERROR::ENGINE_FAIL;
373                         notify();
374                         return;
375                 }
376         }
377         ret = url_download_start(m_download_handle, &m_download_id);
378         DP_LOGD("URL download handle : handle[%p]id[%d]", m_download_handle, m_download_id);
379
380         if (ret != URL_DOWNLOAD_ERROR_NONE) {
381                 m_state = DL_ITEM::FAILED;
382                 m_errorCode = ERROR::ENGINE_FAIL;
383                 notify();
384         }
385 }
386
387 ERROR::CODE DownloadItem::_convert_error(int err)
388 {
389         DP_LOGD("download module error[%d]", err);
390
391         switch (err) {
392         /*
393         case URL_DOWNLOAD_ERROR_NONE:
394         case URL_DOWNLOAD_ERROR_INVALID_PARAMETER:
395         case URL_DOWNLOAD_ERROR_OUT_OF_MEMORY:
396         case URL_DOWNLOAD_ERROR_IO_ERROR:
397         case URL_DOWNLOAD_ERROR_FIELD_NOT_FOUND:
398         case URL_DOWNLOAD_ERROR_INVALID_STATE:
399         case URL_DOWNLOAD_ERROR_INVALID_DESTINATION:
400         case URL_DOWNLOAD_ERROR_TOO_MANY_DOWNLOADS:
401 */
402         case URL_DOWNLOAD_ERROR_NETWORK_UNREACHABLE:
403         case URL_DOWNLOAD_ERROR_CONNECTION_TIMED_OUT:
404         case URL_DOWNLOAD_ERROR_CONNECTION_FAILED:
405                 return ERROR::NETWORK_FAIL;
406
407         case URL_DOWNLOAD_ERROR_INVALID_URL:
408                 return ERROR::INVALID_URL;
409
410         case URL_DOWNLOAD_ERROR_NO_SPACE:
411                 return ERROR::NOT_ENOUGH_MEMORY;
412
413 //              return ERROR::FAIL_TO_INSTALL;
414         default :
415                 return ERROR::UNKNOWN;
416         }
417
418 }
419
420 void DownloadItem::cancel()
421 {
422         DP_LOGD("DownloadItem::cancel");
423         if (m_state == DL_ITEM::CANCELED) {
424                 DP_LOGD("It is already canceled");
425                 notify();
426                 return;
427         }
428         int ret = url_download_stop(m_download_handle);
429         if (ret != URL_DOWNLOAD_ERROR_NONE) {
430                 DP_LOGE("Fail to cancel download : handle[%p]  reason[%d]",
431                         m_download_handle, ret);
432                 m_state = DL_ITEM::FAILED;
433                 m_errorCode = ERROR::ENGINE_FAIL;
434                 notify();
435         }
436         return;
437 }
438
439 void DownloadItem::retry()
440 {
441         DP_LOGD_FUNC();
442 //      m_download_handle = NULL;
443         m_state = DL_ITEM::IGNORE;
444         m_errorCode = ERROR::NONE;
445         m_receivedFileSize = 0;
446         m_fileSize = 0;
447         m_downloadType = DL_TYPE::HTTP_DOWNLOAD;
448         start(true);
449 }
450
451 void DownloadItem::suspend()
452 {
453         int ret = url_download_pause(m_download_handle);
454         if (ret != URL_DOWNLOAD_ERROR_NONE) {
455                 DP_LOGE("Fail to suspend download : handle[%p] err[%d]",
456                         m_download_handle, ret);
457                 m_state = DL_ITEM::FAILED;
458                 m_errorCode = ERROR::ENGINE_FAIL;
459                 notify();
460         }
461 }
462
463 void DownloadItem::resume()
464 {
465         int ret = url_download_start(m_download_handle, &m_download_id);
466         if (ret != URL_DOWNLOAD_ERROR_NONE) {
467                 DP_LOGE("Fail to resume download : handle[%p] err[%d]",
468                         m_download_handle, ret);
469                 m_state = DL_ITEM::FAILED;
470                 m_errorCode = ERROR::ENGINE_FAIL;
471                 notify();
472         }
473 }