Fix wrong behavior about return value of shortcut request
[platform/core/appfw/shortcut.git] / lib / src / shortcut_manager.c
1 /*
2  * Copyright (c) 2011 - 2016 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 <gio/gio.h>
18 #include <stdlib.h>
19 #include <errno.h>
20 #include <unistd.h>
21 #include <fcntl.h>
22 #include <string.h>
23 #include <time.h>
24
25 #include <aul.h>
26 #include <dlog.h>
27 #include <glib.h>
28 #include <db-util.h>
29
30 #include "shortcut.h"
31 #include "shortcut_private.h"
32 #include "shortcut_db.h"
33 #include "shortcut_manager.h"
34 #include "shortcut_internal.h"
35
36 #define SHORTCUT_IS_WIDGET_SIZE(size)           (!!((size) & WIDGET_SIZE_DEFAULT))
37 #define REQUEST_ID_LEN  40
38
39 EAPI int shortcut_set_request_cb(shortcut_request_cb request_cb, void *data)
40 {
41         int ret;
42
43         if (request_cb == NULL)
44                 return SHORTCUT_ERROR_INVALID_PARAMETER; /* LCOV_EXCL_LINE */
45
46         ret = _dbus_init();
47         if (ret != SHORTCUT_ERROR_NONE) {
48                 /* LCOV_EXCL_START */
49                 SHORTCUT_ERR("Can't init dbus %d", ret);
50                 return ret;
51                 /* LCOV_EXCL_STOP */
52         }
53
54         ret = _dbus_signal_init();
55         if (ret != SHORTCUT_ERROR_NONE) {
56                 /* LCOV_EXCL_START */
57                 SHORTCUT_ERR("Can't init dbus_signal %d", ret);
58                 return ret;
59                 /* LCOV_EXCL_STOP */
60         }
61
62         ret = _send_service_register();
63         if (ret != SHORTCUT_ERROR_NONE) {
64                 /* LCOV_EXCL_START */
65                 SHORTCUT_ERR("Can't init ipc_monitor_register %d", ret);
66                 return ret;
67                 /* LCOV_EXCL_STOP */
68         }
69
70         ret = _dbus_set_watch_name();
71         if (ret != SHORTCUT_ERROR_NONE) {
72                 /* LCOV_EXCL_START */
73                 SHORTCUT_ERR("Can't init _dbus_set_watch_name %d", ret);
74                 return ret;
75                 /* LCOV_EXCL_STOP */
76         }
77
78         _set_request_cb(request_cb, data);
79
80         return SHORTCUT_ERROR_NONE;
81 }
82
83 EAPI void shortcut_unset_request_cb(void)
84 {
85         _unset_request_cb();
86 }
87
88 EAPI int shortcut_set_remove_cb(shortcut_remove_cb remove_cb, void *data)
89 {
90         int ret;
91
92         if (remove_cb == NULL)
93                 return SHORTCUT_ERROR_INVALID_PARAMETER;
94
95         ret = _dbus_init();
96         if (ret != SHORTCUT_ERROR_NONE) {
97                 /* LCOV_EXCL_START */
98                 SHORTCUT_ERR("Can't init dbus %d", ret);
99                 return ret;
100                 /* LCOV_EXCL_STOP */
101         }
102
103         ret = _dbus_signal_init();
104         if (ret != SHORTCUT_ERROR_NONE) {
105                 /* LCOV_EXCL_START */
106                 SHORTCUT_ERR("Can't init dbus_signal %d", ret);
107                 return ret;
108                 /* LCOV_EXCL_STOP */
109         }
110
111         ret = _send_service_register();
112         if (ret != SHORTCUT_ERROR_NONE) {
113                 /* LCOV_EXCL_START */
114                 SHORTCUT_ERR("Can't init ipc_monitor_register %d", ret);
115                 return ret;
116                 /* LCOV_EXCL_STOP */
117         }
118
119         ret = _dbus_set_watch_name();
120         if (ret != SHORTCUT_ERROR_NONE) {
121                 /* LCOV_EXCL_START */
122                 SHORTCUT_ERR("Can't init _dbus_set_watch_name %d", ret);
123                 return ret;
124                 /* LCOV_EXCL_STOP */
125         }
126
127         _set_remove_cb(remove_cb, data);
128
129         return SHORTCUT_ERROR_NONE;
130 }
131
132 EAPI void shortcut_unset_remove_cb(void)
133 {
134         _unset_remove_cb();
135 }
136
137 static char *_make_request_id()
138 {
139         static int id = 0;
140         char request_id[REQUEST_ID_LEN] = { 0, };
141
142         g_atomic_int_inc(&id);
143         snprintf(request_id, sizeof(request_id), "%d@%d", getpid(), id);
144
145         SHORTCUT_DBG("The request_id of shortcut is [%s]", request_id);
146
147         return strdup(request_id);
148 }
149
150 EAPI int shortcut_add_to_home(const char *name, shortcut_type type, const char *uri,
151                 const char *icon, int allow_duplicate, result_cb_t result_cb, void *data)
152 {
153         struct result_cb_item *item;
154         char *appid;
155         int ret;
156         GVariant *body;
157         char *request_id = NULL;
158
159         if (ADD_TO_HOME_IS_DYNAMICBOX(type)) {
160                 /* LCOV_EXCL_START */
161                 SHORTCUT_ERR("Invalid type used for adding a shortcut\n");
162                 return SHORTCUT_ERROR_INVALID_PARAMETER;
163                 /* LCOV_EXCL_STOP */
164         }
165
166         ret = _dbus_init();
167         if (ret != SHORTCUT_ERROR_NONE) {
168                 /* LCOV_EXCL_START */
169                 SHORTCUT_ERR("Can't init dbus %d", ret);
170                 return ret;
171                 /* LCOV_EXCL_STOP */
172         }
173
174         ret = _check_privilege();
175         if (ret != SHORTCUT_ERROR_NONE)
176                 return ret;
177
178         appid = _shortcut_get_pkgname_by_pid();
179         if (appid == NULL) {
180                 /* LCOV_EXCL_START */
181                 SHORTCUT_ERR("Can't get appid");
182                 return SHORTCUT_ERROR_IO_ERROR;
183                 /* LCOV_EXCL_STOP */
184         }
185
186         item = malloc(sizeof(struct result_cb_item));
187         if (!item) {
188                 /* LCOV_EXCL_START */
189                 if (appid)
190                         free(appid);
191
192                 SHORTCUT_ERR("Heap: %d\n", errno);
193                 return SHORTCUT_ERROR_OUT_OF_MEMORY;
194                 /* LCOV_EXCL_STOP */
195         }
196
197         item->result_cb = result_cb;
198         item->result_internal_cb = NULL;
199         item->data = data;
200
201         if (!name)
202                 name = "";
203
204         if (!uri)
205                 uri = "";
206
207         if (!icon)
208                 icon = "";
209
210         request_id = _make_request_id();
211         body = g_variant_new("(sississi)", request_id, getpid(), appid, name, type, uri, icon, allow_duplicate);
212
213         ret = _send_async_shortcut(body, item, "add_shortcut");
214         if (ret != SHORTCUT_ERROR_NONE) {
215                 /* LCOV_EXCL_START */
216                 free(item);
217                 item = NULL;
218                 /* LCOV_EXCL_STOP */
219         }
220
221         if (appid)
222                 free(appid);
223         if (body)
224                 g_variant_unref(body);
225         if (request_id)
226                 free(request_id);
227
228         return ret;
229 }
230
231 EAPI int shortcut_add_to_home_widget(const char *name, shortcut_widget_size_e size, const char *widget_id,
232                 const char *icon, double period, int allow_duplicate, result_cb_t result_cb, void *data)
233 {
234         struct result_cb_item *item;
235         char *appid;
236         int ret;
237         GVariant *body;
238         char *request_id = NULL;
239
240         if (name == NULL) {
241                 SHORTCUT_ERR("AppID is null\n");
242                 return SHORTCUT_ERROR_INVALID_PARAMETER;
243         }
244
245         if (!SHORTCUT_IS_WIDGET_SIZE(size)) {
246                 /* LCOV_EXCL_START */
247                 SHORTCUT_ERR("Invalid type used for adding a widget\n");
248                 return SHORTCUT_ERROR_INVALID_PARAMETER;
249                 /* LCOV_EXCL_STOP */
250         }
251
252         ret = _dbus_init();
253         if (ret != SHORTCUT_ERROR_NONE) {
254                 /* LCOV_EXCL_START */
255                 SHORTCUT_ERR("Can't init dbus %d", ret);
256                 return ret;
257                 /* LCOV_EXCL_STOP */
258         }
259
260         ret = _check_privilege();
261         if (ret != SHORTCUT_ERROR_NONE)
262                 return ret;
263
264         appid = _shortcut_get_pkgname_by_pid();
265         if (appid == NULL) {
266                 /* LCOV_EXCL_START */
267                 SHORTCUT_ERR("Can't get appid");
268                 return SHORTCUT_ERROR_IO_ERROR;
269                 /* LCOV_EXCL_STOP */
270         }
271
272         item = malloc(sizeof(struct result_cb_item));
273         if (!item) {
274                 /* LCOV_EXCL_START */
275                 if (appid)
276                         free(appid);
277
278                 SHORTCUT_ERR("Heap: %d\n", errno);
279                 return SHORTCUT_ERROR_OUT_OF_MEMORY;
280                 /* LCOV_EXCL_STOP */
281         }
282
283         item->result_cb = result_cb;
284         item->result_internal_cb = NULL;
285         item->data = data;
286
287         request_id = _make_request_id();
288         body = g_variant_new("(sississdi)", request_id, getpid(), widget_id, name, size, NULL, icon, period, allow_duplicate);
289         ret = _send_async_shortcut(body, item, "add_shortcut_widget");
290
291         if (ret != SHORTCUT_ERROR_NONE) {
292                 /* LCOV_EXCL_START */
293                 free(item);
294                 item = NULL;
295                 /* LCOV_EXCL_STOP */
296         }
297
298         if (appid)
299                 free(appid);
300         if (body)
301                 g_variant_unref(body);
302         if (request_id)
303                 free(request_id);
304
305         return ret;
306 }
307
308 EAPI int shortcut_remove_from_home(const char *name, result_cb_t result_cb, void *user_data)
309 {
310         struct result_cb_item *item;
311         char *appid;
312         int ret;
313         GVariant *body;
314         char *request_id = NULL;
315
316         if (name == NULL) {
317                 SHORTCUT_ERR("name is NULL.");
318                 return SHORTCUT_ERROR_INVALID_PARAMETER;
319         }
320
321         ret = _dbus_init();
322         if (ret != SHORTCUT_ERROR_NONE) {
323                 /* LCOV_EXCL_START */
324                 SHORTCUT_ERR("Can't init dbus %d", ret);
325                 return ret;
326                 /* LCOV_EXCL_STOP */
327         }
328
329         ret = _check_privilege();
330         if (ret != SHORTCUT_ERROR_NONE)
331                 return ret;
332
333         appid = _shortcut_get_pkgname_by_pid();
334         if (appid == NULL) {
335                 /* LCOV_EXCL_START */
336                 SHORTCUT_ERR("Can't get appid");
337                 return SHORTCUT_ERROR_IO_ERROR;
338                 /* LCOV_EXCL_STOP */
339         }
340
341         item = malloc(sizeof(struct result_cb_item));
342         if (!item) {
343                 /* LCOV_EXCL_START */
344                 if (appid)
345                         free(appid);
346
347                 SHORTCUT_ERR("Heap: %d\n", errno);
348                 return SHORTCUT_ERROR_OUT_OF_MEMORY;
349                 /* LCOV_EXCL_STOP */
350         }
351
352         item->result_cb = result_cb;
353         item->result_internal_cb = NULL;
354         item->data = user_data;
355
356         request_id = _make_request_id();
357         body = g_variant_new("(siss)", request_id, getpid(), appid, name);
358
359         ret = _send_async_shortcut(body, item, "remove_shortcut");
360         if (ret != SHORTCUT_ERROR_NONE) {
361                 /* LCOV_EXCL_START */
362                 free(item);
363                 item = NULL;
364                 /* LCOV_EXCL_STOP */
365         }
366
367         if (appid)
368                 free(appid);
369         if (body)
370                 g_variant_unref(body);
371         if (request_id)
372                 free(request_id);
373
374         return ret;
375 }
376
377 EAPI int shortcut_get_list(const char *package_name, shortcut_list_cb list_cb, void *data)
378 {
379         GDBusMessage *reply = NULL;
380         int result;
381         int ret = 0;
382         GVariant *body;
383         GVariant *reply_body;
384         GVariant *iter_body;
385         GVariantIter *iter;
386         GVariantBuilder *b;
387         shortcut_info_s shortcut;
388
389         if (list_cb == NULL)
390                 return SHORTCUT_ERROR_INVALID_PARAMETER;
391
392         result = _dbus_init();
393         if (result != SHORTCUT_ERROR_NONE) {
394                 /* LCOV_EXCL_START */
395                 SHORTCUT_ERR("Can't init dbus %d", result);
396                 return result;
397                 /* LCOV_EXCL_STOP */
398         }
399
400         b = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
401         if (package_name)
402                 g_variant_builder_add(b, "{sv}", "package_name", g_variant_new_string(package_name));
403         body = g_variant_builder_end(b);
404         result = _send_sync_shortcut(g_variant_new("(v)", body), &reply, "get_list");
405
406         if (result == SHORTCUT_ERROR_NONE) {
407                 reply_body = g_dbus_message_get_body(reply);
408                 g_variant_get(reply_body, "(ia(v))", &ret, &iter);
409                 SHORTCUT_DBG("shortcut count : %d", ret);
410                 while (g_variant_iter_loop(iter, "(v)", &iter_body)) {
411                         g_variant_get(iter_body, "(&s&s&s&s&s)",
412                                 &shortcut.package_name, &shortcut.icon, &shortcut.name, &shortcut.extra_key, &shortcut.extra_data);
413                         SHORTCUT_DBG("call calback : %s", shortcut.package_name);
414                         list_cb(shortcut.package_name, shortcut.icon, shortcut.name, shortcut.extra_key, shortcut.extra_data, data);
415                 }
416                 g_variant_iter_free(iter);
417         } else {
418                 ret = result; /* LCOV_EXCL_LINE */
419         }
420
421         if (reply)
422                 g_object_unref(reply);
423
424         return ret;
425 }
426
427 /* LCOV_EXCL_START */
428 EAPI int add_to_home_shortcut(const char *appid, const char *name, int type, const char *content,
429                 const char *icon, int allow_duplicate, result_internal_cb_t result_cb, void *data)
430 {
431         /*Deprecated API */
432         return SHORTCUT_ERROR_NONE;
433 }
434 /* LCOV_EXCL_STOP */
435
436 /* LCOV_EXCL_START */
437 EAPI int add_to_home_dynamicbox(const char *appid, const char *name, int type, const char *content, const char *icon, double period, int allow_duplicate, result_internal_cb_t result_cb, void *data)
438 {
439         /*Deprecated API */
440         return SHORTCUT_ERROR_NONE;
441 }
442 /* LCOV_EXCL_STOP */
443
444 /* End of a file */