Add a new API for sending whether sticker DB is changed
[platform/core/uifw/capi-ui-sticker.git] / consumer / sticker_consumer.c
1 /*
2  * Copyright (c) 2019 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 <dlog.h>
18 #include <gio/gio.h>
19 #include <dbus/dbus.h>
20 #include <app_common.h>
21 #include <cynara-client.h>
22 #include <cynara-error.h>
23 #include <cynara-session.h>
24
25 #include "sticker_consumer.h"
26 #include "sticker_consumer_main.h"
27 #include "sticker_dbus.h"
28
29 #ifdef LOG_TAG
30 #undef LOG_TAG
31 #endif
32 #define LOG_TAG "STICKER_CONSUMER"
33
34 static cynara *p_cynara = NULL;
35
36 static void _free_sticker_data(sticker_data_h sticker_data)
37 {
38     if (sticker_data->app_id) {
39         free(sticker_data->app_id);
40         sticker_data->app_id = NULL;
41     }
42
43     if (sticker_data->uri) {
44         free(sticker_data->uri);
45         sticker_data->uri = NULL;
46     }
47
48     if (sticker_data->thumbnail) {
49         free(sticker_data->thumbnail);
50         sticker_data->thumbnail = NULL;
51     }
52
53     if (sticker_data->keyword) {
54         g_list_free_full(sticker_data->keyword, free);
55         sticker_data->keyword = NULL;
56     }
57
58     if (sticker_data->group) {
59         free(sticker_data->group);
60         sticker_data->group = NULL;
61     }
62
63     if (sticker_data->description) {
64         free(sticker_data->description);
65         sticker_data->description = NULL;
66     }
67
68     if (sticker_data->date) {
69         free(sticker_data->date);
70         sticker_data->date = NULL;
71     }
72
73     free(sticker_data);
74     sticker_data = NULL;
75 }
76
77 static int _cynara_initialize()
78 {
79     int ret = cynara_initialize(&p_cynara, NULL);
80     if (ret != CYNARA_API_SUCCESS)
81         LOGE("Failed to cynara initialize");
82
83     return ret;
84 }
85
86 static int _check_privilege(const char *uid, const char *privilege)
87 {
88     int ret;
89     FILE *fp = NULL;
90     char label_path[1024] = "/proc/self/attr/current";
91     char smack_label[1024] = {'\0',};
92
93     if (!p_cynara) {
94         return -1;
95     }
96
97     fp = fopen(label_path, "r");
98     if (fp != NULL) {
99         ret = fread(smack_label, 1, sizeof(smack_label), fp);
100         if (ret <= 0)
101             LOGE("Failed to fread");
102
103         fclose(fp);
104     }
105
106     pid_t pid = getpid();
107     char *session = cynara_session_from_pid(pid);
108     ret = cynara_check(p_cynara, smack_label, session, uid, privilege);
109     if (session)
110         free(session);
111
112     if (ret != CYNARA_API_ACCESS_ALLOWED) {
113         LOGE("Access denied. The result of cynara_check() : %d.", ret);
114         return -1;
115     }
116
117     return 0;
118 }
119
120 static void _cynara_deinitialize()
121 {
122     if (p_cynara)
123         cynara_finish(p_cynara);
124
125     p_cynara = NULL;
126 }
127
128 static int _sticker_check_privilege() {
129     char uid[16];
130     int ret = STICKER_ERROR_NONE;
131
132     if (_cynara_initialize() != CYNARA_API_SUCCESS)
133         return STICKER_ERROR_PERMISSION_DENIED;
134
135     snprintf(uid, 16, "%d", getuid());
136     if (_check_privilege(uid, STICKER_PRIVILEGE_MEDIASTORAGE) < 0) {
137         LOGE("Permission is denied");
138         ret = STICKER_ERROR_PERMISSION_DENIED;
139     }
140
141     _cynara_deinitialize();
142
143     return ret;
144 }
145
146 EXPORT_API int sticker_consumer_create(sticker_consumer_h *consumer_handle)
147 {
148     CHECK_STICKER_FEATURE();
149
150     int ret;
151     if (!consumer_handle)
152         return STICKER_ERROR_INVALID_PARAMETER;
153
154     if (_sticker_check_privilege() != STICKER_ERROR_NONE)
155         return STICKER_ERROR_PERMISSION_DENIED;
156
157     struct sticker_consumer_s *consumer_struct = (sticker_consumer_h)calloc(1, sizeof(struct sticker_consumer_s));
158
159     if (!consumer_struct)
160         return STICKER_ERROR_OUT_OF_MEMORY;
161
162     ret = app_get_id(&consumer_struct->app_id);
163     if (ret != APP_ERROR_NONE) {
164         LOGE("Failed to get app_id : %d", ret);
165         free(consumer_struct);
166         return STICKER_ERROR_OPERATION_FAILED;
167     }
168
169     ret = sticker_dbus_init(&consumer_struct->gdbus_connection, &consumer_struct->server_watcher_id,
170         &consumer_struct->monitor_id, &consumer_struct->server_monitor_id, STICKER_CLIENT_LIB_CONSUMER, (void *)consumer_struct);
171     if (ret != STICKER_ERROR_NONE) {
172         LOGE("Failed to initialize dbus : %d", ret);
173         free(consumer_struct);
174         return STICKER_ERROR_OPERATION_FAILED;
175     }
176
177     *consumer_handle = consumer_struct;
178
179     return STICKER_ERROR_NONE;
180 }
181
182 EXPORT_API int sticker_consumer_destroy(sticker_consumer_h consumer_handle)
183 {
184     CHECK_STICKER_FEATURE();
185
186     int ret;
187     if (!consumer_handle)
188         return STICKER_ERROR_INVALID_PARAMETER;
189
190     LOGD("consumer_handle : %p", consumer_handle);
191     ret = sticker_dbus_shutdown(consumer_handle->gdbus_connection, &consumer_handle->server_watcher_id,
192                                 &consumer_handle->server_monitor_id, &consumer_handle->monitor_id);
193     if (ret != STICKER_ERROR_NONE) {
194         LOGE("Failed to finalize dbus : %d", ret);
195         free(consumer_handle);
196         return STICKER_ERROR_OPERATION_FAILED;
197     }
198
199     if (consumer_handle->gdbus_connection)
200         g_object_unref(consumer_handle->gdbus_connection);
201
202     if (consumer_handle->app_id) {
203         free(consumer_handle->app_id);
204         consumer_handle->app_id = NULL;
205     }
206
207     free(consumer_handle);
208
209     return STICKER_ERROR_NONE;
210 }
211
212 EXPORT_API int sticker_consumer_data_foreach_all(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_consumer_data_foreach_cb callback, void *user_data)
213 {
214     CHECK_STICKER_FEATURE();
215
216     int ret;
217     int info_id;
218     int sticker_count = 0;
219     GVariantIter *id_iter = NULL;
220
221     if (!consumer_handle || (offset < 0) || (count <= 0) || !result || !callback)
222         return STICKER_ERROR_INVALID_PARAMETER;
223
224     ret = sticker_dbus_get_all_sticker_info(consumer_handle->gdbus_connection, consumer_handle->app_id, offset, count, &id_iter);
225     if (ret != STICKER_ERROR_NONE) {
226         LOGE("Failed to get all sticker information : %d", ret);
227         ret = STICKER_ERROR_OPERATION_FAILED;
228         goto cleanup;
229     }
230
231     if (id_iter) {
232         while (g_variant_iter_loop (id_iter, "(i)", &info_id)) {
233             sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s));
234             if (!sticker_data) {
235                 ret = STICKER_ERROR_OUT_OF_MEMORY;
236                 goto cleanup;
237             }
238
239             ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id);
240             if (ret == STICKER_ERROR_NONE) {
241                 sticker_count++;
242                 callback(sticker_data, user_data);
243                 _free_sticker_data(sticker_data);
244             } else {
245                 _free_sticker_data(sticker_data);
246                 goto cleanup;
247             }
248         }
249     }
250
251     *result = sticker_count;
252
253 cleanup:
254     if (id_iter)
255         g_variant_iter_free(id_iter);
256
257     return ret;
258 }
259
260 EXPORT_API int sticker_consumer_data_foreach_by_keyword(sticker_consumer_h consumer_handle, int offset, int count, int *result, const char *keyword, sticker_consumer_data_foreach_cb callback, void *user_data)
261 {
262     CHECK_STICKER_FEATURE();
263
264     int ret;
265     int info_id;
266     int sticker_count = 0;
267     GVariantIter *id_iter = NULL;
268
269     if (!consumer_handle || (offset < 0) || (count <= 0) || !result || !keyword || !callback)
270         return STICKER_ERROR_INVALID_PARAMETER;
271
272     ret = sticker_dbus_get_sticker_info_by_keyword(consumer_handle->gdbus_connection, consumer_handle->app_id, keyword, offset, count, &id_iter);
273     if (ret != STICKER_ERROR_NONE) {
274         LOGE("Failed to get sticker information by keyword : %d", ret);
275         ret = STICKER_ERROR_OPERATION_FAILED;
276         goto cleanup;
277     }
278
279     if (id_iter) {
280         while (g_variant_iter_loop (id_iter, "(i)", &info_id)) {
281             sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s));
282             if (!sticker_data) {
283                 ret = STICKER_ERROR_OUT_OF_MEMORY;
284                 goto cleanup;
285             }
286
287             ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id);
288             if (ret == STICKER_ERROR_NONE) {
289                 sticker_count++;
290                 callback(sticker_data, user_data);
291                 _free_sticker_data(sticker_data);
292             } else {
293                 _free_sticker_data(sticker_data);
294                 goto cleanup;
295             }
296         }
297     }
298
299     *result = sticker_count;
300
301 cleanup:
302     if (id_iter)
303         g_variant_iter_free(id_iter);
304
305     return ret;
306 }
307
308 EXPORT_API int sticker_consumer_data_foreach_by_group(sticker_consumer_h consumer_handle, int offset, int count, int *result, const char *group, sticker_consumer_data_foreach_cb callback, void *user_data)
309 {
310     CHECK_STICKER_FEATURE();
311
312         int ret;
313     int info_id;
314     int sticker_count = 0;
315     GVariantIter *id_iter = NULL;
316
317     if (!consumer_handle || (offset < 0) || (count <= 0) || !result || !group || !callback)
318         return STICKER_ERROR_INVALID_PARAMETER;
319
320     ret = sticker_dbus_get_sticker_info_by_group(consumer_handle->gdbus_connection, consumer_handle->app_id, group, offset, count, &id_iter);
321     if (ret != STICKER_ERROR_NONE) {
322         LOGE("Failed to get sticker information by group : %d", ret);
323         ret = STICKER_ERROR_OPERATION_FAILED;
324         goto cleanup;
325     }
326
327     if (id_iter) {
328         while (g_variant_iter_loop (id_iter, "(i)", &info_id)) {
329             sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s));
330             if (!sticker_data) {
331                 ret = STICKER_ERROR_OUT_OF_MEMORY;
332                 goto cleanup;
333             }
334
335             ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id);
336             if (ret == STICKER_ERROR_NONE) {
337                 sticker_count++;
338                 callback(sticker_data, user_data);
339                 _free_sticker_data(sticker_data);
340             } else {
341                 _free_sticker_data(sticker_data);
342                 goto cleanup;
343             }
344         }
345     }
346
347     *result = sticker_count;
348
349 cleanup:
350     if (id_iter)
351         g_variant_iter_free(id_iter);
352
353     return ret;
354 }
355
356 EXPORT_API int sticker_consumer_data_foreach_by_type(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_data_uri_type_e type, sticker_consumer_data_foreach_cb callback, void *user_data)
357 {
358     CHECK_STICKER_FEATURE();
359
360     int ret;
361     int info_id;
362     int sticker_count = 0;
363     GVariantIter *id_iter = NULL;
364
365     if (!consumer_handle || (offset < 0) || (count <= 0) || !result || (type < 1) || !callback)
366         return STICKER_ERROR_INVALID_PARAMETER;
367
368     ret = sticker_dbus_get_sticker_info_by_type(consumer_handle->gdbus_connection, consumer_handle->app_id, type, offset, count, &id_iter);
369     if (ret != STICKER_ERROR_NONE) {
370         LOGE("Failed to get sticker information by uri type : %d", ret);
371         ret = STICKER_ERROR_OPERATION_FAILED;
372         goto cleanup;
373     }
374
375     if (id_iter) {
376         while (g_variant_iter_loop (id_iter, "(i)", &info_id)) {
377             sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s));
378             if (!sticker_data) {
379                 ret = STICKER_ERROR_OUT_OF_MEMORY;
380                 goto cleanup;
381             }
382
383             ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id);
384             if (ret == STICKER_ERROR_NONE) {
385                 sticker_count++;
386                 callback(sticker_data, user_data);
387                 _free_sticker_data(sticker_data);
388             } else {
389                 _free_sticker_data(sticker_data);
390                 goto cleanup;
391             }
392         }
393     }
394
395     *result = sticker_count;
396
397 cleanup:
398     if (id_iter)
399         g_variant_iter_free(id_iter);
400
401     return ret;
402 }
403
404 EXPORT_API int sticker_consumer_group_list_foreach_all(sticker_consumer_h consumer_handle, sticker_consumer_group_list_foreach_cb callback, void *user_data)
405 {
406     CHECK_STICKER_FEATURE();
407
408     int ret;
409     GList *list = NULL;
410
411     if (!consumer_handle || !callback)
412         return STICKER_ERROR_INVALID_PARAMETER;
413
414     ret = sticker_dbus_get_group_list(consumer_handle->gdbus_connection, consumer_handle->app_id, &list);
415     if (ret != STICKER_ERROR_NONE) {
416         LOGE("Failed to get group list : %d", ret);
417         ret = STICKER_ERROR_OPERATION_FAILED;
418         goto cleanup;
419     }
420
421     for(GList *tmp = g_list_first(list); tmp != NULL; tmp=tmp->next) {
422         callback((const char *)tmp->data, user_data);
423     }
424
425 cleanup:
426     if (list)
427         g_list_free_full(list, free);
428
429     return ret;
430 }
431
432 EXPORT_API int sticker_consumer_keyword_list_foreach_all(sticker_consumer_h consumer_handle, sticker_consumer_keyword_list_foreach_cb callback, void *user_data)
433 {
434     CHECK_STICKER_FEATURE();
435
436     int ret;
437     GList *list = NULL;
438
439     if (!consumer_handle || !callback)
440         return STICKER_ERROR_INVALID_PARAMETER;
441
442     ret = sticker_dbus_get_keyword_list(consumer_handle->gdbus_connection, consumer_handle->app_id, &list);
443     if (ret != STICKER_ERROR_NONE) {
444         LOGE("Failed to get keyword list : %d", ret);
445         ret = STICKER_ERROR_OPERATION_FAILED;
446         goto cleanup;
447     }
448
449     for(GList *tmp = g_list_first(list); tmp != NULL; tmp=tmp->next) {
450         callback((const char *)tmp->data, user_data);
451     }
452
453 cleanup:
454     if (list)
455         g_list_free_full(list, free);
456
457     return ret;
458 }
459
460 EXPORT_API int sticker_consumer_data_foreach_by_display_type(sticker_consumer_h consumer_handle, int offset, int count, int *result, sticker_data_display_type_e type, sticker_consumer_data_foreach_cb callback, void *user_data)
461 {
462     CHECK_STICKER_FEATURE();
463
464     int ret;
465     int info_id;
466     int sticker_count = 0;
467     GVariantIter *id_iter = NULL;
468
469     if (!consumer_handle || (offset < 0) || (count <= 0) || !result || (type < 1) || !callback)
470         return STICKER_ERROR_INVALID_PARAMETER;
471
472     ret = sticker_dbus_get_sticker_info_by_display_type(consumer_handle->gdbus_connection, consumer_handle->app_id, type, offset, count, &id_iter);
473     if (ret != STICKER_ERROR_NONE) {
474         LOGE("Failed to get sticker information by display type : %d", ret);
475         ret = STICKER_ERROR_OPERATION_FAILED;
476         goto cleanup;
477     }
478
479     if (id_iter) {
480         while (g_variant_iter_loop (id_iter, "(i)", &info_id)) {
481             sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s));
482             if (!sticker_data) {
483                 ret = STICKER_ERROR_OUT_OF_MEMORY;
484                 goto cleanup;
485             }
486
487             ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id);
488             if (ret == STICKER_ERROR_NONE) {
489                 sticker_count++;
490                 callback(sticker_data, user_data);
491                 _free_sticker_data(sticker_data);
492             } else {
493                 _free_sticker_data(sticker_data);
494                 goto cleanup;
495             }
496         }
497     }
498
499     *result = sticker_count;
500
501 cleanup:
502     if (id_iter)
503         g_variant_iter_free(id_iter);
504
505     return ret;
506 }
507
508 EXPORT_API int sticker_consumer_group_list_foreach_by_display_type(sticker_consumer_h consumer_handle, sticker_data_display_type_e type, sticker_consumer_group_list_foreach_cb callback, void *user_data)
509 {
510     CHECK_STICKER_FEATURE();
511
512     int ret;
513     GList *list = NULL;
514
515     if (!consumer_handle || (type < 1) || !callback)
516         return STICKER_ERROR_INVALID_PARAMETER;
517
518     ret = sticker_dbus_get_group_list_by_display_type(consumer_handle->gdbus_connection, consumer_handle->app_id, type, &list);
519     if (ret != STICKER_ERROR_NONE) {
520         LOGE("Failed to get group list : %d", ret);
521         ret = STICKER_ERROR_OPERATION_FAILED;
522         goto cleanup;
523     }
524
525     for(GList *tmp = g_list_first(list); tmp != NULL; tmp=tmp->next) {
526         callback((const char *)tmp->data, user_data);
527     }
528
529 cleanup:
530     if (list)
531         g_list_free_full(list, free);
532
533     return ret;
534 }
535
536 EXPORT_API int sticker_consumer_add_recent_data(sticker_consumer_h consumer_handle, sticker_data_h data_handle)
537 {
538     CHECK_STICKER_FEATURE();
539
540     int ret;
541
542     if (!consumer_handle || !data_handle || (data_handle->sticker_info_id > 0) || !data_handle->uri)
543         return STICKER_ERROR_INVALID_PARAMETER;
544
545     ret = sticker_dbus_insert_recent_sticker_info(consumer_handle->gdbus_connection, data_handle->sticker_info_id);
546     if (ret != STICKER_ERROR_NONE) {
547         LOGE("Failed to add recent sticker information : %d", ret);
548         return STICKER_ERROR_OPERATION_FAILED;
549     }
550
551     return STICKER_ERROR_NONE;
552 }
553
554 EXPORT_API int sticker_consumer_get_recent_data_list(sticker_consumer_h consumer_handle, int count, int *result, sticker_consumer_data_foreach_cb callback, void *user_data)
555 {
556     CHECK_STICKER_FEATURE();
557
558     int ret;
559     int info_id;
560     int sticker_count = 0;
561     GVariantIter *id_iter = NULL;
562
563     if (!consumer_handle || (count <= 0) || !result || !callback)
564         return STICKER_ERROR_INVALID_PARAMETER;
565
566     ret = sticker_dbus_get_recent_sticker_list(consumer_handle->gdbus_connection, count, &id_iter);
567     if (ret != STICKER_ERROR_NONE) {
568         LOGE("Failed to get recent sticker information : %d", ret);
569         ret = STICKER_ERROR_OPERATION_FAILED;
570         goto cleanup;
571     }
572
573     if (id_iter) {
574         while (g_variant_iter_loop (id_iter, "(i)", &info_id)) {
575             sticker_data_h sticker_data = (sticker_data_h)calloc(1, sizeof(struct sticker_data_s));
576             if (!sticker_data) {
577                 ret = STICKER_ERROR_OUT_OF_MEMORY;
578                 goto cleanup;
579             }
580
581             ret = sticker_dbus_get_sticker_info_by_record_id(consumer_handle->gdbus_connection, sticker_data, info_id);
582             if (ret == STICKER_ERROR_NONE) {
583                 sticker_count++;
584                 callback(sticker_data, user_data);
585                 _free_sticker_data(sticker_data);
586             } else {
587                 _free_sticker_data(sticker_data);
588                 goto cleanup;
589             }
590         }
591     }
592
593     *result = sticker_count;
594
595 cleanup:
596     if (id_iter)
597         g_variant_iter_free(id_iter);
598
599     return ret;
600 }
601
602 EXPORT_API int sticker_consumer_set_event_callback(sticker_consumer_h consumer_handle, sticker_consumer_event_cb callback, void *user_data)
603 {
604     CHECK_STICKER_FEATURE();
605
606     if (!consumer_handle || !callback)
607         return STICKER_ERROR_INVALID_PARAMETER;
608
609     consumer_handle->event_cb = callback;
610     consumer_handle->event_cb_user_data = user_data;
611
612     return STICKER_ERROR_NONE;
613 }
614
615 EXPORT_API int sticker_consumer_unset_event_callback(sticker_consumer_h consumer_handle)
616 {
617     CHECK_STICKER_FEATURE();
618
619     if (!consumer_handle)
620         return STICKER_ERROR_INVALID_PARAMETER;
621
622     consumer_handle->event_cb = NULL;
623     consumer_handle->event_cb_user_data = NULL;
624
625     return STICKER_ERROR_NONE;
626 }