merge with master
[platform/framework/web/download-provider.git] / provider / download-provider-notification.c
1 /*
2  * Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
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 #include <time.h>
18 #include <sys/time.h>
19 #include <stdlib.h>
20
21 #include "bundle.h"
22 #include "notification.h"
23 #include "appsvc.h"
24
25 #include "download-provider-notification.h"
26 #include "download-provider-request.h"
27 #include "download-provider-db.h"
28 #include "download-provider-log.h"
29
30 #include <libintl.h>
31 #define S_(s) dgettext("sys_string", s)
32
33 #define DP_NOTIFICATION_ICON_PATH IMAGE_DIR"/Q02_Notification_Download_failed.png"
34
35 static const char *__noti_error_str(
36                 notification_error_e err)
37 {
38         switch (err) {
39         case NOTIFICATION_ERROR_INVALID_DATA:
40                 return "NOTIFICATION_ERROR_INVALID_DATA";
41         case NOTIFICATION_ERROR_NO_MEMORY:
42                 return "NOTIFICATION_ERROR_NO_MEMORY";
43         case NOTIFICATION_ERROR_FROM_DB:
44                 return "NOTIFICATION_ERROR_FROM_DB";
45         case NOTIFICATION_ERROR_ALREADY_EXIST_ID:
46                 return "NOTIFICATION_ERROR_ALREADY_EXIST_ID";
47         case NOTIFICATION_ERROR_FROM_DBUS:
48                 return "NOTIFICATION_ERROR_FROM_DBUS";
49         case NOTIFICATION_ERROR_NOT_EXIST_ID:
50                 return "NOTIFICATION_ERROR_NOT_EXIST_ID";
51         default:
52                 break;
53         }
54         return "Unknown error";
55 }
56
57 static char *__get_string_status(dp_state_type state)
58 {
59         char *message = NULL;
60         switch (state) {
61         case DP_STATE_COMPLETED:
62                 //message = S_("IDS_COM_POP_SUCCESS");
63                 message = "Completed";
64                 break;
65         case DP_STATE_CANCELED:
66                 //message = S_("IDS_COM_POP_CANCELLED");
67                 message = "Canceled";
68                 break;
69         case DP_STATE_FAILED:
70                 //message = S_("IDS_COM_POP_FAILED");
71                 message = "Failed";
72                 break;
73         default:
74                 break;
75         }
76         return message;
77 }
78 static void __free_char_pointer_array(char **array, int count)
79 {
80         int i = 0;
81         if (count < 0)
82                 count = 0;
83         for (i = 0; i < count; i++) {
84                 if (array[i])
85                         free(array[i]);
86         }
87         free(array);
88 }
89
90 static int __set_extra_data(bundle *b, int id)
91 {
92         db_conds_list_fmt conds_p;
93         int conds_count = 0;
94         int count = 0;
95         // get count of key list.
96         conds_count = 1;
97         memset(&conds_p, 0x00, sizeof(db_conds_list_fmt));
98         conds_p.column = DP_DB_COL_ID;
99         conds_p.type = DP_DB_COL_TYPE_INT;
100         conds_p.value = &id;
101         count = dp_db_get_conds_rows_count(DP_DB_TABLE_NOTIFICATION,
102                         DP_DB_COL_DISTINCT_EXTRA_KEY, "AND", 1, &conds_p);
103         if (count > 0) {
104                 char **keys_array = NULL;
105                 int i = 0;
106                 keys_array = (char **)calloc(count, sizeof(char *));
107                 if (keys_array == NULL) {
108                         TRACE_ERROR("[FAIL] calloc failed");
109                         return -1;
110                 }
111                 // get key list
112                 int keys_count =
113                         dp_db_get_conds_list(DP_DB_TABLE_NOTIFICATION,
114                                         DP_DB_COL_DISTINCT_EXTRA_KEY , DP_DB_COL_TYPE_TEXT,
115                                         (void **)keys_array, count, -1, NULL, NULL,
116                                         "AND", 1, &conds_p);
117                 if (keys_count <= 0) {
118                         TRACE_ERROR("[FAIL] Wrong db data");
119                         __free_char_pointer_array(keys_array, 0);
120                         return -1;
121                 }
122                 for (i = 0; i < keys_count; i++) {
123                         db_conds_list_fmt conds_p2[2];
124                         int conds_count2 = 2;
125                         char **values_array = NULL;
126                         int check_rows = 0;
127                         int values_count = 0;
128
129                         memset(conds_p2, 0x00, conds_count2 * sizeof(db_conds_list_fmt));
130                         conds_p2[0].column = DP_DB_COL_ID;
131                         conds_p2[0].type = DP_DB_COL_TYPE_INT;
132                         conds_p2[0].value = &id;
133                         conds_p2[1].column = DP_DB_COL_EXTRA_KEY;
134                         conds_p2[1].type = DP_DB_COL_TYPE_TEXT;
135                         conds_p2[1].value = (void *)(keys_array[i]);
136                         // get value list
137                         check_rows = dp_db_get_conds_rows_count(
138                                         DP_DB_TABLE_NOTIFICATION, DP_DB_COL_EXTRA_VALUE, "AND",
139                                         conds_count2, conds_p2);
140                         if (check_rows <= 0) {
141                                 TRACE_ERROR("[FAIL] No values about key");
142                                 __free_char_pointer_array(keys_array, keys_count);
143                                 return -1;
144                         }
145                         values_array = (char **)calloc(check_rows, sizeof(char *));
146                         if (values_array == NULL) {
147                                 TRACE_ERROR("[FAIL] calloc failed");
148                                 __free_char_pointer_array(keys_array, keys_count);
149                                 return -1;
150                         }
151                         values_count =
152                                 dp_db_get_conds_list(DP_DB_TABLE_NOTIFICATION,
153                                         DP_DB_COL_EXTRA_VALUE, DP_DB_COL_TYPE_TEXT,
154                                         (void **)values_array, check_rows, -1, NULL, NULL,
155                                         "AND", conds_count2, conds_p2);
156                         if (values_count <= 0) {
157                                 TRACE_ERROR("[FAIL] No values about key");
158                                 __free_char_pointer_array(keys_array, keys_count);
159                                 __free_char_pointer_array(values_array, 0);
160                                 return -1;
161                         }
162                         if (values_count == 1) {
163                                 char *key = keys_array[i];
164                                 char *value = values_array[values_count-1];
165                                 if (appsvc_add_data(b, key, value) !=
166                                         APPSVC_RET_OK) {
167                                         TRACE_ERROR("[FAIL] set add data");
168                                         __free_char_pointer_array(keys_array, keys_count);
169                                         __free_char_pointer_array(values_array, values_count);
170                                         return -1;
171                                 }
172                         } else {
173                                 char *key = keys_array[i];
174                                 if (appsvc_add_data_array(b, key, (const char **)values_array,
175                                                 values_count) !=        APPSVC_RET_OK) {
176                                         TRACE_ERROR("[FAIL] set add data");
177                                         __free_char_pointer_array(keys_array, keys_count);
178                                         __free_char_pointer_array(values_array, values_count);
179                                         return -1;
180                                 }
181                         }
182                         __free_char_pointer_array(values_array, values_count);
183                 }
184                 __free_char_pointer_array(keys_array, keys_count);
185         }
186         return 0;
187 }
188
189 int dp_set_downloadinginfo_notification(int id, char *packagename)
190 {
191         notification_h noti_handle = NULL;
192         notification_error_e err = NOTIFICATION_ERROR_NONE;
193         int privId = 0;
194         bundle *b = NULL;
195
196 #ifdef NOTI_NEW_VERSION_API
197         noti_handle = notification_create(NOTIFICATION_TYPE_ONGOING);
198 #else
199         noti_handle = notification_new(NOTIFICATION_TYPE_ONGOING,
200                 NOTIFICATION_GROUP_ID_NONE, NOTIFICATION_PRIV_ID_NONE);
201 #endif
202
203         if (!noti_handle) {
204                 TRACE_ERROR("[FAIL] create notification handle");
205                 return -1;
206         }
207
208         char *content_name =
209                 dp_db_get_text_column
210                         (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME);
211
212         if (content_name == NULL)
213                 content_name = strdup("No Name");
214
215         err = notification_set_text(noti_handle,
216                         NOTIFICATION_TEXT_TYPE_TITLE, content_name, NULL,
217                         NOTIFICATION_VARIABLE_TYPE_NONE);
218         if (content_name)
219                 free(content_name);
220
221         if (err != NOTIFICATION_ERROR_NONE) {
222                 TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err));
223                 notification_free(noti_handle);
224                 return -1;
225         }
226
227         err = notification_set_image(noti_handle,
228                         NOTIFICATION_IMAGE_TYPE_ICON, DP_NOTIFICATION_ICON_PATH);
229         if (err != NOTIFICATION_ERROR_NONE) {
230                 TRACE_ERROR("[FAIL] set icon [%s]", __noti_error_str(err));
231                 notification_free(noti_handle);
232                 return -1;
233         }
234
235         b = bundle_create();
236         if (!b) {
237                 TRACE_ERROR("[FAIL] create bundle");
238                 notification_free(noti_handle);
239                 return -1;
240         }
241
242         if (packagename &&
243                 appsvc_set_pkgname(b, packagename) != APPSVC_RET_OK) {
244                 TRACE_ERROR("[FAIL] set pkg name");
245                 bundle_free(b);
246                 notification_free(noti_handle);
247                 return -1;
248         }
249
250         if (__set_extra_data(b, id) < 0) {
251                 bundle_free(b);
252                 notification_free(noti_handle);
253                 return -1;
254         }
255
256         err = notification_set_execute_option(noti_handle,
257                         NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b);
258
259         if (err != NOTIFICATION_ERROR_NONE) {
260                 TRACE_ERROR("[FAIL] set execute option [%s]", __noti_error_str(err));
261                 bundle_free(b);
262                 notification_free(noti_handle);
263                 return -1;
264         }
265         bundle_free(b);
266
267         err = notification_set_property(noti_handle,
268                         NOTIFICATION_PROP_DISABLE_TICKERNOTI);
269         if (err != NOTIFICATION_ERROR_NONE) {
270                 TRACE_ERROR("[FAIL] set property [%s]", __noti_error_str(err));
271                 notification_free(noti_handle);
272                 return -1;
273         }
274
275         err = notification_insert(noti_handle, &privId);
276         if (err != NOTIFICATION_ERROR_NONE) {
277                 TRACE_ERROR("[FAIL] set insert [%s]", __noti_error_str(err));
278                 notification_free(noti_handle);
279                 return -1;
280         }
281
282         TRACE_INFO("m_noti_id [%d]", privId);
283         notification_free(noti_handle);
284         return privId;
285 }
286
287 int dp_set_downloadedinfo_notification(int priv_id, int id, char *packagename, dp_state_type state)
288 {
289         notification_h noti_handle = NULL;
290         notification_error_e err = NOTIFICATION_ERROR_NONE;
291         int privId = 0;
292         bundle *b = NULL;
293
294         if (priv_id >= 0) {
295                 err = notification_delete_by_priv_id(NULL, NOTIFICATION_TYPE_ONGOING,
296                                 priv_id);
297                 if (err != NOTIFICATION_ERROR_NONE) {
298                         TRACE_ERROR("[FAIL] delete notification handle [%s]",
299                                         __noti_error_str(err));
300                 }
301         }
302
303 #ifdef NOTI_NEW_VERSION_API
304         noti_handle = notification_create(NOTIFICATION_TYPE_NOTI);
305 #else
306         noti_handle = notification_new(NOTIFICATION_TYPE_NOTI,
307                 NOTIFICATION_GROUP_ID_NONE, NOTIFICATION_PRIV_ID_NONE);
308 #endif
309
310         if (!noti_handle) {
311                 TRACE_ERROR("[FAIL] create notification handle");
312                 return -1;
313         }
314
315         char *content_name =
316                 dp_db_get_text_column
317                         (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_CONTENT_NAME);
318
319         if (content_name == NULL)
320                 content_name = strdup("No Name");
321
322         err = notification_set_text(noti_handle,
323                         NOTIFICATION_TEXT_TYPE_TITLE, content_name,
324                         NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
325         if (content_name)
326                 free(content_name);
327
328         if (err != NOTIFICATION_ERROR_NONE) {
329                 TRACE_ERROR("[FAIL] set title [%s]", __noti_error_str(err));
330                 notification_free(noti_handle);
331                 return -1;
332         }
333
334         err = notification_set_text(noti_handle,
335                         NOTIFICATION_TEXT_TYPE_CONTENT,
336                         __get_string_status(state), NULL,
337                         NOTIFICATION_VARIABLE_TYPE_NONE);
338         if (err != NOTIFICATION_ERROR_NONE) {
339                 TRACE_ERROR("[FAIL] set text [%s]", __noti_error_str(err));
340                 notification_free(noti_handle);
341                 return -1;
342         }
343         time_t tt = time(NULL);
344
345         err = notification_set_time(noti_handle, tt);
346         if (err != NOTIFICATION_ERROR_NONE) {
347                 TRACE_ERROR("[FAIL] set time [%s]", __noti_error_str(err));
348                 notification_free(noti_handle);
349                 return -1;
350         }
351
352         b = bundle_create();
353         if (!b) {
354                 TRACE_ERROR("[FAIL] create bundle");
355                 notification_free(noti_handle);
356                 return -1;
357         }
358
359         if (state == DP_STATE_COMPLETED) {
360                 if (appsvc_set_operation(b, APPSVC_OPERATION_VIEW) != APPSVC_RET_OK) {
361                         TRACE_ERROR("[FAIL] appsvc set operation");
362                         bundle_free(b);
363                         notification_free(noti_handle);
364                         return -1;
365                 }
366                 
367                 char *savedpath =
368                         dp_db_get_text_column
369                                 (id, DP_DB_TABLE_DOWNLOAD_INFO, DP_DB_COL_SAVED_PATH);
370                 if (savedpath && appsvc_set_uri(b, savedpath) !=
371                                 APPSVC_RET_OK) {
372                         TRACE_ERROR("[FAIL] appsvc set uri");
373                         free(savedpath);
374                         bundle_free(b);
375                         notification_free(noti_handle);
376                         return -1;
377                 }
378                 if (savedpath)
379                         free(savedpath);
380                 err = notification_set_execute_option(noti_handle,
381                                 NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b);
382                 if (err != NOTIFICATION_ERROR_NONE) {
383                         TRACE_ERROR("[FAIL] set execute option[%s]", __noti_error_str(err));
384                         bundle_free(b);
385                         notification_free(noti_handle);
386                         return -1;
387                 }
388
389         } else if (state == DP_STATE_CANCELED || state == DP_STATE_FAILED) {
390                 if (__set_extra_data(b, id) < 0) {
391                         bundle_free(b);
392                         notification_free(noti_handle);
393                         return -1;
394                 }
395
396                 if (packagename &&
397                         appsvc_set_pkgname(b, packagename) !=
398                         APPSVC_RET_OK) {
399                         TRACE_ERROR("[FAIL] set pkg name");
400                         bundle_free(b);
401                         notification_free(noti_handle);
402                         return -1;
403                 }
404                 err = notification_set_execute_option(noti_handle,
405                                 NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, "View", NULL, b);
406                 if (err != NOTIFICATION_ERROR_NONE) {
407                         TRACE_ERROR("[FAIL] set execute option[%s]", __noti_error_str(err));
408                         bundle_free(b);
409                         notification_free(noti_handle);
410                         return -1;
411                 }
412         } else {
413                 TRACE_ERROR("[CRITICAL] invalid state");
414                 bundle_free(b);
415                 notification_free(noti_handle);
416                 return -1;
417         }
418
419         if (err != NOTIFICATION_ERROR_NONE) {
420                 TRACE_ERROR("[FAIL] set time [%s]", __noti_error_str(err));
421                 notification_free(noti_handle);
422                 bundle_free(b);
423                 return -1;
424         }
425
426         bundle_free(b);
427
428         err = notification_set_image(noti_handle, NOTIFICATION_IMAGE_TYPE_ICON,
429                         DP_NOTIFICATION_ICON_PATH);
430         if (err != NOTIFICATION_ERROR_NONE) {
431                 TRACE_ERROR("[FAIL] set icon [%s]", __noti_error_str(err));
432                 notification_free(noti_handle);
433                 return -1;
434         }
435
436         err = notification_set_property(noti_handle,
437                         NOTIFICATION_PROP_DISABLE_TICKERNOTI);
438         if (err != NOTIFICATION_ERROR_NONE) {
439                 TRACE_ERROR("[FAIL] set property [%s]", __noti_error_str(err));
440                 notification_free(noti_handle);
441                 return -1;
442         }
443
444         err = notification_insert(noti_handle, &privId);
445         if (err != NOTIFICATION_ERROR_NONE) {
446                 TRACE_ERROR("[FAIL] set insert [%s]", __noti_error_str(err));
447                 notification_free(noti_handle);
448                 return -1;
449         }
450
451         TRACE_INFO("m_noti_id [%d]", privId);
452         notification_free(noti_handle);
453         return privId;
454 }
455
456 void dp_update_downloadinginfo_notification(int priv_id, double received_size, double file_size)
457 {
458         notification_error_e err = NOTIFICATION_ERROR_NONE;
459         if (priv_id < 0) {
460                 TRACE_ERROR("[FAIL] Invalid priv_id[%d]", priv_id);
461                 return;
462         }
463
464         if (file_size > 0) {
465                 double progress;
466                 progress = received_size / file_size;
467                 err = notification_update_progress(NULL, priv_id, progress);
468                 if (err != NOTIFICATION_ERROR_NONE)
469                         TRACE_ERROR("[FAIL] update noti progress[%s]",
470                                         __noti_error_str(err));
471         } else {
472                 err = notification_update_size(NULL, priv_id, received_size);
473                 if (err != NOTIFICATION_ERROR_NONE)
474                         TRACE_ERROR("[FAIL]  update noti progress[%s]",
475                                         __noti_error_str(err));
476         }
477 }
478
479 void dp_clear_downloadinginfo_notification()
480 {
481         notification_error_e err = NOTIFICATION_ERROR_NONE;
482         err = notification_delete_all_by_type(NULL, NOTIFICATION_TYPE_ONGOING);
483         if (err != NOTIFICATION_ERROR_NONE) {
484                 TRACE_ERROR("[FAIL] clear noti [%s]", __noti_error_str(err));
485         }
486         return;
487 }