apply FSL(Flora Software License)
[profile/ivi/download-provider.git] / src / download-provider-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-provider-downloadItem.cpp
19  * @author      Jungki Kwak (jungki.kwak@samsung.com)
20  * @brief       download item class for interface of download agent
21  */
22
23 #include "download-provider-downloadItem.h"
24
25 #include "download-provider-common.h"
26 #include <Ecore.h>
27 #include <iostream>
28
29 /* Download Agent CallBacks */
30 static void __notify_cb(user_notify_info_t *notify_info, void *user_data);
31 static void __update_download_info_cb(user_download_info_t *download_info, void *user_data);
32 static void __get_dd_info_cb(user_dd_info_t *dd_info, void *user_data);
33
34 static Ecore_Pipe *ecore_pipe = NULL;
35 static void __ecore_cb_pipe_update(void *data, void *buffer, unsigned int nbyte);
36
37 namespace DA_CB {
38 enum TYPE {
39         NOTIFY = 1,
40         UPDATE,
41         DD_INFO
42 };
43 }
44
45 class CbData {
46 public:
47         CbData() {}
48         ~CbData() {}
49
50         void updateDownloadItem();
51
52         inline void setType(DA_CB::TYPE type) { m_type = type; }
53         inline void setUserData(void *userData) { m_userData = userData; }
54         inline void setDownloadId(int id) { m_da_req_id = id; }
55         inline void setReceivedFileSize(unsigned long int size) { m_receivedFileSize = size; }
56         inline void setFileSize(unsigned long int size) { m_fileSize = size; }
57         inline void setFilePath(const char *path) { if (path) m_filePath = path; }
58         inline void setRegisteredFilePath(const char *path) { if (path) m_registeredFilePath = path; }
59         inline void setMimeType(const char *mime) { m_mimeType = mime; }
60         inline void setState(da_state state) { m_da_state = state; }
61         inline void setErrorCode(int err) { m_da_error = err;   }
62         inline void setIsMidletInstalled(bool b) { m_isMidletInstalled = b; }
63         inline void setIsJad(bool b) { m_isJad = b;}
64         inline void setContentName(const char *name) { m_contentName = name; }
65         inline void setVendorName(const char *name) { m_vendorName = name; }
66
67 private:
68         DA_CB::TYPE m_type;
69         void *m_userData;
70         da_handle_t m_da_req_id;
71         da_state m_da_state;
72         int m_da_error;
73         unsigned long int m_receivedFileSize;
74         unsigned long int m_fileSize;
75         string m_filePath;
76         string m_registeredFilePath;
77         string m_mimeType;
78         bool m_isMidletInstalled;
79         bool m_isJad;
80         string m_contentName;
81         string m_vendorName;
82 };
83
84 struct pipe_data_t {
85         CbData *cbData;
86 };
87
88 DownloadEngine::DownloadEngine()
89 {
90 }
91
92 DownloadEngine::~DownloadEngine()
93 {
94         DP_LOG_FUNC();
95 }
96
97 void DownloadEngine::initEngine(void)
98 {
99         da_client_cb_t da_cb = {
100                 __notify_cb,    /* da_notify_cb */
101                 __get_dd_info_cb,       /* da_send_dd_info_cb */
102                 __update_download_info_cb,      /* da_update_download_info_cb */
103                 NULL    /* da_go_to_next_url_cb */
104         };
105
106         int da_ret = da_init(&da_cb, DA_DOWNLOAD_MANAGING_METHOD_AUTO);
107         if (DA_RESULT_OK == da_ret) {
108                 ecore_pipe = ecore_pipe_add(__ecore_cb_pipe_update, NULL);
109         }
110 }
111
112 void DownloadEngine::deinitEngine(void)
113 {
114         da_deinit();
115         if (ecore_pipe) {
116                 ecore_pipe_del(ecore_pipe);
117                 ecore_pipe = NULL;
118         }
119 }
120
121 void CbData::updateDownloadItem()
122 {
123 //      DP_LOGD_FUNC();
124
125         if (!m_userData) {
126                 DP_LOGE("download item is NULL");
127                 return;
128         }
129         
130
131         DownloadItem *downloadItem = static_cast<DownloadItem*>(m_userData);
132         if (downloadItem->state() == DL_ITEM::FAILED) {
133                 DP_LOGE("download item is already failed");
134                 return;
135         }
136
137         switch(m_type) {
138         case DA_CB::NOTIFY:
139         {
140                 DP_LOGD("DA_CB::NOTIFY");
141                 downloadItem->setDownloadId(m_da_req_id);
142                 DL_ITEM::STATE dl_state = downloadItem->_convert_da_state_to_download_state(m_da_state);
143                 DP_LOG("DL_ITEM::STATE [%d]", dl_state);
144                 //if (dl_state != DL_ITEM::IGNORE)
145                 if (dl_state == DL_ITEM::IGNORE)
146                         return;
147                 downloadItem->setState(dl_state);
148
149                 if (dl_state == DL_ITEM::FAILED)
150                         downloadItem->setErrorCode(downloadItem->_convert_da_error(m_da_error));
151         }
152                 break;
153
154         case DA_CB::UPDATE:
155                 DP_LOGD("DA_CB::UPDATE");
156                 DP_LOGD("DA_CB::UPDATE state[%d] receivedFileSize[%d]", downloadItem->state(), m_receivedFileSize);
157 //              downloadItem->setDownloadId(m_da_req_id);
158                 downloadItem->setState(DL_ITEM::UPDATING);
159                 downloadItem->setReceivedFileSize(m_receivedFileSize);
160                 downloadItem->setFileSize(m_fileSize);
161
162                 if (!m_mimeType.empty())
163                         downloadItem->setMimeType(m_mimeType);
164
165                 if (!m_filePath.empty())
166                         downloadItem->setFilePath(m_filePath);
167
168                 if (!m_registeredFilePath.empty()) {
169                         DP_LOGD("registeredFilePath[%s]", m_registeredFilePath.c_str());
170                         downloadItem->setRegisteredFilePath(m_registeredFilePath);
171                 }
172                 break;
173
174         case DA_CB::DD_INFO:
175                 DP_LOG("DA_CB::DD_INFO");
176                 downloadItem->setDownloadId(m_da_req_id);
177                 downloadItem->setFileSize(m_fileSize);
178                 downloadItem->setIsMidletInstalled(m_isMidletInstalled);
179                 if (m_isJad)
180                         downloadItem->setDownloadType(DL_TYPE::MIDP_DOWNLOAD);
181                 else
182                         downloadItem->setDownloadType(DL_TYPE::OMA_DOWNLOAD);
183                 downloadItem->setContentName(m_contentName);
184                 downloadItem->setVendorName(m_vendorName);
185                 downloadItem->setState(DL_ITEM::WAITING_CONFIRM);
186                 break;
187
188         default:
189                 break;
190         }
191
192         downloadItem->notify();
193 }
194
195 void __ecore_cb_pipe_update(void *data, void *buffer, unsigned int nbyte)
196 {
197 //      DP_LOGD_FUNC();
198
199         if (!buffer)
200                 return;
201         pipe_data_t *pipe_data = static_cast<pipe_data_t *>(buffer);
202         CbData *cbData = pipe_data->cbData;
203         if (!cbData)
204                 return;
205
206         cbData->updateDownloadItem();
207         delete cbData;
208 }
209
210 void __notify_cb(user_notify_info_t *notify_info, void* user_data)
211 {
212         DP_LOGD_FUNC();
213
214         if (!notify_info || !user_data)
215                 return;
216
217         DP_LOGD("__notify_cb: id[%d] state[%d] err[%d]", notify_info->da_dl_req_id, notify_info->state, notify_info->err);
218
219         CbData *cbData = new CbData();
220         cbData->setType(DA_CB::NOTIFY);
221         cbData->setDownloadId(notify_info->da_dl_req_id);
222         cbData->setUserData(user_data);
223         cbData->setState(notify_info->state);
224         cbData->setErrorCode(notify_info->err);
225
226         pipe_data_t pipe_data;
227         pipe_data.cbData = cbData;
228         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
229 }
230
231 void __update_download_info_cb(user_download_info_t *download_info, void *user_data)
232 {
233 //      DP_LOGD_FUNC();
234
235         if (!download_info || !user_data)
236                 return;
237
238         CbData *cbData = new CbData();
239         cbData->setType(DA_CB::UPDATE);
240         cbData->setDownloadId(download_info->da_dl_req_id);
241         cbData->setUserData(user_data);
242         cbData->setFileSize(download_info->file_size);
243         cbData->setReceivedFileSize(download_info->total_received_size);
244
245 //      DP_LOGD("tmp path [%s] path [%s] type [%s]", download_info->tmp_saved_path, download_info->saved_path, download_info->file_type);
246         DownloadItem *item = static_cast<DownloadItem*>(user_data);
247         if(download_info->file_type && item->mimeType().empty())
248                 cbData->setMimeType(download_info->file_type);
249
250         if(download_info->tmp_saved_path && item->filePath().empty())
251                 cbData->setFilePath(download_info->tmp_saved_path);
252
253         if(download_info->saved_path && item->registeredFilePath().empty())
254                 cbData->setRegisteredFilePath(download_info->saved_path);
255
256         pipe_data_t pipe_data;
257         pipe_data.cbData = cbData;
258         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
259 }
260
261 void __get_dd_info_cb(user_dd_info_t *dd_info, void *user_data)
262 {
263         DP_LOGD_FUNC();
264
265         if (!dd_info || !user_data)
266                 return;
267
268         CbData *cbData = new CbData();
269         cbData->setType(DA_CB::DD_INFO);
270         cbData->setDownloadId(dd_info->da_dl_req_id);
271         cbData->setUserData(user_data);
272         cbData->setIsMidletInstalled(dd_info->is_installed);
273         cbData->setIsJad(dd_info->is_jad);
274         cbData->setFileSize(dd_info->size);
275
276         if (dd_info->name)
277                 cbData->setContentName(dd_info->name);
278         if (dd_info->vendor)
279                 cbData->setVendorName(dd_info->vendor);
280         if (dd_info->type)
281                 cbData->setMimeType(dd_info->type);
282
283         pipe_data_t pipe_data;
284         pipe_data.cbData = cbData;
285         ecore_pipe_write(ecore_pipe, &pipe_data, sizeof(pipe_data_t));
286 }
287
288 DownloadItem::DownloadItem()
289         : m_da_req_id(DA_INVALID_ID)
290         , m_state(DL_ITEM::IGNORE)
291         , m_errorCode(ERROR::NONE)
292         , m_receivedFileSize(0)
293         , m_fileSize(0)
294         , m_downloadType(DL_TYPE::HTTP_DOWNLOAD)
295         , m_isMidletInstalled(false)
296 {
297 }
298
299 DownloadItem::DownloadItem(auto_ptr<DownloadRequest> request)
300         : m_aptr_request(request)
301         , m_da_req_id(DA_INVALID_ID)
302         , m_state(DL_ITEM::IGNORE)
303         , m_errorCode(ERROR::NONE)
304         , m_receivedFileSize(0)
305         , m_fileSize(0)
306         , m_downloadType(DL_TYPE::HTTP_DOWNLOAD)
307         , m_isMidletInstalled(false)
308 {
309 }
310
311 DownloadItem::~DownloadItem()
312 {
313         DP_LOGD_FUNC();
314 }
315
316 void DownloadItem::start(void)
317 {
318         int da_ret = 0;
319         DP_LOGD_FUNC();
320
321         if (m_aptr_request->getCookie().empty()) {
322                 da_ret = da_start_download_with_extension(
323                         m_aptr_request->getUrl().c_str(),
324                         &m_da_req_id,
325                         DA_FEATURE_USER_DATA,
326                         static_cast<void*>(this),
327                         NULL);
328         } else {
329                 char *requestHeader[1] = {NULL,};
330                 int reqHeaderCount = 1;
331                 string reqHeaderStr = string("Cookie:");
332                 reqHeaderStr.append(m_aptr_request->getCookie().c_str());
333                 requestHeader[0] = strdup(reqHeaderStr.c_str());
334                 da_ret = da_start_download_with_extension(
335                         m_aptr_request->getUrl().c_str(),
336                         &m_da_req_id,
337                         DA_FEATURE_REQUEST_HEADER,
338                         requestHeader,
339                         &reqHeaderCount,
340                         DA_FEATURE_USER_DATA,
341                         static_cast<void*>(this),
342                         NULL);
343                 if (requestHeader[0]) {
344                         free(requestHeader[0]);
345                         requestHeader[0] = NULL;
346                 }
347         }
348         if (da_ret != DA_RESULT_OK) {
349                 m_state = DL_ITEM::FAILED;
350                 m_errorCode = ERROR::ENGINE_FAIL;
351                 notify();
352         }
353 }
354
355 DL_ITEM::STATE DownloadItem::_convert_da_state_to_download_state(int da_state)
356 {
357         switch (da_state) {
358         case DA_STATE_DOWNLOAD_STARTED:
359                 return DL_ITEM::STARTED;
360 //      case DA_STATE_DOWNLOADING:
361 //              return DL_ITEM::UPDATING;
362         case DA_STATE_DOWNLOAD_COMPLETE:
363                 return DL_ITEM::COMPLETE_DOWNLOAD;
364         case DA_STATE_WAITING_USER_CONFIRM:
365                 return DL_ITEM::WAITING_CONFIRM;
366         case DA_STATE_START_INSTALL_NOTIFY:
367                 return DL_ITEM::INSTALL_NOTIFY;
368         case DA_STATE_DRM_JOIN_LEAVE_DOMAIN_START:
369                 return DL_ITEM::START_DRM_DOMAIN;
370         case DA_STATE_DRM_JOIN_LEAVE_DOMAIN_FINISH:
371                 return DL_ITEM::FINISH_DRM_DOMAIN;
372         case DA_STATE_WAITING_RO:
373                 return DL_ITEM::WAITING_RO;
374         case DA_STATE_SUSPENDED:
375                 return DL_ITEM::SUSPENDED;
376         case DA_STATE_RESUMED:
377                 return DL_ITEM::RESUMED;
378         case DA_STATE_CANCELED:
379                 return DL_ITEM::CANCELED;
380         case DA_STATE_FINISHED:
381                 return DL_ITEM::FINISHED;
382         case DA_STATE_FAILED:
383                 return DL_ITEM::FAILED;
384         case DA_STATE_DOWNLOADING:
385         case DA_STATE_DONE_INSTALL_NOTIFY:
386         case DA_STATE_DRM_ROAP_START:
387         case DA_STATE_DRM_ROAP_FINISH:
388         default:
389                 return DL_ITEM::IGNORE;
390         }
391 }
392
393 ERROR::CODE DownloadItem::_convert_da_error(int da_err)
394 {
395         DP_LOGD("download agent error[%d]", da_err);
396
397         switch (da_err) {
398         case DA_ERR_NETWORK_FAIL:
399         case DA_ERR_HTTP_TIMEOUT:
400         case DA_ERR_UNREACHABLE_SERVER :
401                 return ERROR::NETWORK_FAIL;
402
403         case DA_ERR_INVALID_URL:
404                 return ERROR::INVALID_URL;
405
406         case DA_ERR_DISK_FULL:
407                 return ERROR::NOT_ENOUGH_MEMORY;
408
409         case DA_ERR_FAIL_TO_INSTALL_FILE:
410         case DA_ERR_DLOPEN_FAIL:
411                 return ERROR::FAIL_TO_INSTALL;
412
413         case DA_ERR_USER_RESPONSE_WAITING_TIME_OUT:
414                 return ERROR::OMA_POPUP_TIME_OUT;
415
416         case DA_ERR_PARSE_FAIL:
417                 return ERROR::FAIL_TO_PARSE_DESCRIPTOR;
418
419         default :
420                 return ERROR::UNKNOWN;
421         }
422
423 }
424
425 void DownloadItem::cancel()
426 {
427         DP_LOGD("DownloadItem::cancel");
428         if (m_state == DL_ITEM::CANCELED) {
429                 DP_LOGD("It is already canceled");
430                 notify();
431                 return;
432         }
433         int da_ret = da_cancel_download(m_da_req_id);
434         if (da_ret != DA_RESULT_OK) {
435                 DP_LOGE("Fail to cancel download : reqId[%d]  reason[%d]",
436                         m_da_req_id, da_ret);
437                 m_state = DL_ITEM::FAILED;
438                 m_errorCode = ERROR::ENGINE_FAIL;
439                 notify();
440         }
441         return;
442 }
443
444 void DownloadItem::retry()
445 {
446         DP_LOGD_FUNC();
447         m_da_req_id = DA_INVALID_ID;
448         m_state = DL_ITEM::IGNORE;
449         m_errorCode = ERROR::NONE;
450         m_receivedFileSize = 0;
451         m_fileSize = 0;
452         m_downloadType = DL_TYPE::HTTP_DOWNLOAD;
453         m_isMidletInstalled = false;
454         start();
455 }
456
457 bool DownloadItem::sendUserResponse(bool res)
458 {
459         int da_ret = da_send_back_user_confirm(m_da_req_id, res);
460         if (da_ret != DA_RESULT_OK) {
461                 DP_LOGE("Fail to send back user confirm : reqId[%d]  reason[%d]",
462                         m_da_req_id, da_ret);
463                 m_state = DL_ITEM::FAILED;
464                 m_errorCode = ERROR::ENGINE_FAIL;
465                 notify();
466                 return false;
467         }
468         return true;
469 }
470
471 void DownloadItem::suspend()
472 {
473         int da_ret = DA_RESULT_OK;
474         da_ret = da_suspend_download(m_da_req_id);
475         if (da_ret != DA_RESULT_OK) {
476                 DP_LOGE("Fail to suspend download : reqId[%d] err[%d]", m_da_req_id, da_ret);
477                 m_state = DL_ITEM::FAILED;
478                 m_errorCode = ERROR::ENGINE_FAIL;
479                 notify();
480         }
481 }
482
483 void DownloadItem::resume()
484 {
485         int da_ret = DA_RESULT_OK;
486         da_ret = da_resume_download(m_da_req_id);
487         if (da_ret != DA_RESULT_OK) {
488                 DP_LOGE("Fail to resume download : reqId[%d] err[%d]", m_da_req_id, da_ret);
489                 m_state = DL_ITEM::FAILED;
490                 m_errorCode = ERROR::ENGINE_FAIL;
491                 notify();
492         }
493 }