2 * Copyright (c) 2011 - 2016 Samsung Electronics Co., Ltd. All rights reserved.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
30 #include "shortcut_private.h"
31 #include "shortcut_internal.h"
33 #define SHORTCUT_PKGNAME_LEN 512
35 #define PROVIDER_BUS_NAME "org.tizen.data_provider_service"
36 #define PROVIDER_OBJECT_PATH "/org/tizen/data_provider_service"
37 #define PROVIDER_SHORTCUT_INTERFACE_NAME "org.tizen.data_provider_shortcut_service"
39 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
40 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
41 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
43 static GDBusConnection *_gdbus_conn = NULL;
44 static int monitor_id = 0;
45 static int provider_monitor_id = 0;
47 typedef struct _shortcut_request_cb_info {
48 int (*request_cb)(const char *appid, const char *name, int type, const char *content, const char *icon, pid_t pid, double period, int allow_duplicate, void *data);
50 } shortcut_request_cb_info;
52 typedef struct _shortcut_remove_cb_info {
53 int (*remove_cb)(const char *package_name, const char *name, int sender_pid, void *user_data);
55 } shortcut_remove_cb_info;
57 static shortcut_request_cb_info _request_callback_info;
58 static shortcut_remove_cb_info _remove_callback_info;
61 static void _add_shortcut_notify(GVariant *parameters)
71 g_variant_get(parameters, "(i&s&si&s&si)", &sender_pid, &appid, &name, &type, &content, &icon, &allow_duplicate);
72 DbgPrint("_add_shortcut_notify sender_pid: %d ", sender_pid);
74 if (_request_callback_info.request_cb != NULL)
75 _request_callback_info.request_cb(appid, name, type, content, icon, sender_pid, -1.0f, allow_duplicate, _request_callback_info.data);
77 DbgPrint("request_cb is null.");
82 static void _add_shortcut_widget_notify(GVariant *parameters)
93 g_variant_get(parameters, "(i&s&si&s&sdi)", &sender_pid, &appid, &name, &type, &content, &icon, &period, &allow_duplicate);
95 if (_request_callback_info.request_cb != NULL)
96 _request_callback_info.request_cb(appid, name, type, content, icon, sender_pid, period, allow_duplicate, _request_callback_info.data);
98 DbgPrint("request_cb is null.");
102 static void _remove_shortcut_notify(GVariant *parameters)
108 g_variant_get(parameters, "(i&s&s)", &sender_pid, &appid, &name);
109 DbgPrint("_add_shortcut_notify sender_pid: %d ", sender_pid);
111 if (_remove_callback_info.remove_cb != NULL)
112 _remove_callback_info.remove_cb(appid, name, sender_pid, _remove_callback_info.data);
114 DbgPrint("remove_cb is null.");
117 /* LCOV_EXCL_START */
118 static void _handle_shortcut_notify(GDBusConnection *connection,
119 const gchar *sender_name,
120 const gchar *object_path,
121 const gchar *interface_name,
122 const gchar *signal_name,
123 GVariant *parameters,
126 DbgPrint("signal_name: %s", signal_name);
127 if (g_strcmp0(signal_name, "add_shortcut_notify") == 0)
128 _add_shortcut_notify(parameters);
129 else if (g_strcmp0(signal_name, "add_shortcut_widget_notify") == 0)
130 _add_shortcut_widget_notify(parameters);
131 else if (g_strcmp0(signal_name, "remove_shortcut_notify") == 0)
132 _remove_shortcut_notify(parameters);
138 GError *error = NULL;
140 if (_gdbus_conn == NULL) {
141 _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
143 if (_gdbus_conn == NULL) {
144 /* LCOV_EXCL_START */
147 ErrPrint("Failed to get dbus [%s]", error->message);
151 return SHORTCUT_ERROR_IO_ERROR;
154 shortcut_error_quark();
157 return SHORTCUT_ERROR_NONE;
160 int _dbus_signal_init()
162 int ret = SHORTCUT_ERROR_NONE;
165 if (monitor_id == 0) {
166 DbgPrint("get dbus connection success");
167 id = g_dbus_connection_signal_subscribe(
170 PROVIDER_SHORTCUT_INTERFACE_NAME, /* interface */
172 PROVIDER_OBJECT_PATH, /* path */
174 G_DBUS_SIGNAL_FLAGS_NONE,
175 _handle_shortcut_notify,
179 DbgPrint("subscribe id : %d", id);
181 /* LCOV_EXCL_START */
182 ret = SHORTCUT_ERROR_IO_ERROR;
183 ErrPrint("Failed to _register_noti_dbus_interface");
193 char *_shortcut_get_pkgname_by_pid(void)
195 char pkgname[SHORTCUT_PKGNAME_LEN + 1] = { 0, };
196 char buf[SHORTCUT_PKGNAME_LEN + 1] = { 0, };
203 ret = aul_app_get_pkgname_bypid(pid, pkgname, sizeof(pkgname));
205 /* LCOV_EXCL_START */
206 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
208 fd = open(buf, O_RDONLY);
212 ret = read(fd, pkgname, sizeof(pkgname) - 1);
222 * "ret" is not able to be larger than "sizeof(pkgname) - 1",
223 * if the system is not going wrong.
226 if (strlen(pkgname) <= 0)
230 dup_pkgname = strdup(pkgname);
232 ErrPrint("Heap: %d\n", errno); /* LCOV_EXCL_LINE */
238 * implement user request
240 int _send_sync_shortcut(GVariant *body, GDBusMessage **reply, char *cmd)
244 int ret = SHORTCUT_ERROR_NONE;
246 msg = g_dbus_message_new_method_call(
248 PROVIDER_OBJECT_PATH,
249 PROVIDER_SHORTCUT_INTERFACE_NAME,
252 /* LCOV_EXCL_START */
253 ErrPrint("Can't allocate new method call");
255 g_variant_unref(body);
256 return SHORTCUT_ERROR_OUT_OF_MEMORY;
261 g_dbus_message_set_body(msg, body);
263 *reply = g_dbus_connection_send_message_with_reply_sync(
266 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
275 /* LCOV_EXCL_START */
276 ret = SHORTCUT_ERROR_COMM;
278 ErrPrint("No reply. cmd = %s, error = %s", cmd, err->message);
279 if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
280 ret = SHORTCUT_ERROR_PERMISSION_DENIED;
287 if (g_dbus_message_to_gerror(*reply, &err)) {
288 /* LCOV_EXCL_START */
289 if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
290 ret = SHORTCUT_ERROR_PERMISSION_DENIED;
294 ErrPrint("_send_sync_shortcut error %s err code: %d", err->message, ret);
299 DbgPrint("_send_sync_shortcut done !!");
300 return SHORTCUT_ERROR_NONE;
303 int _send_service_register()
305 GDBusMessage *reply = NULL;
308 result = _send_sync_shortcut(g_variant_new("(i)", getuid()), &reply, "shortcut_service_register");
309 ErrPrint("_send_service_register done");
313 static void _send_message_with_reply_sync_cb(GDBusConnection *connection,
317 int result = SHORTCUT_ERROR_NONE;
319 GDBusMessage *reply = NULL;
320 struct result_cb_item *cb_item = (struct result_cb_item *)user_data;
322 if (cb_item == NULL) {
323 /* LCOV_EXCL_START */
324 ErrPrint("Failed to get a callback item");
329 reply = g_dbus_connection_send_message_with_reply_finish(
335 /* LCOV_EXCL_START */
337 ErrPrint("No reply. error = %s", err->message);
340 result = SHORTCUT_ERROR_COMM;
343 } else if (g_dbus_message_to_gerror(reply, &err)) {
344 /* LCOV_EXCL_START */
345 if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
346 result = SHORTCUT_ERROR_PERMISSION_DENIED;
350 ErrPrint("_send_message_with_reply_sync_cb error %s err code: %d", err->message, result);
355 if (cb_item->result_internal_cb)
356 result = cb_item->result_internal_cb(result, getpid(), cb_item->data); /* LCOV_EXCL_LINE */
357 else if (cb_item->result_cb)
358 result = cb_item->result_cb(result, cb_item->data);
361 g_object_unref(reply);
366 int _send_async_shortcut(GVariant *body, struct result_cb_item *cb_item, char *cmd)
369 msg = g_dbus_message_new_method_call(
371 PROVIDER_OBJECT_PATH,
372 PROVIDER_SHORTCUT_INTERFACE_NAME,
375 /* LCOV_EXCL_START */
376 ErrPrint("Can't allocate new method call");
377 return SHORTCUT_ERROR_OUT_OF_MEMORY;
382 g_dbus_message_set_body(msg, body);
384 g_dbus_connection_send_message_with_reply(
387 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
391 (GAsyncReadyCallback)_send_message_with_reply_sync_cb,
396 DbgPrint("_send_async_shortcut done !!");
397 return SHORTCUT_ERROR_NONE;
400 int _check_privilege(void)
402 GDBusMessage *reply = NULL;
403 int ret = SHORTCUT_ERROR_NONE;
405 ret = _send_sync_shortcut(NULL, &reply, "check_privilege");
408 g_object_unref(reply);
414 /* LCOV_EXCL_START */
415 static void _on_name_appeared(GDBusConnection *connection,
417 const gchar *name_owner,
420 DbgPrint("name appeared : %s", name);
421 _send_service_register();
425 /* LCOV_EXCL_START */
426 static void _on_name_vanished(GDBusConnection *connection,
430 DbgPrint("name vanished : %s", name);
434 void _set_request_cb(shortcut_request_cb request_cb, void *data)
436 _request_callback_info.request_cb = request_cb;
437 _request_callback_info.data = data;
440 int _dbus_set_watch_name()
442 if (provider_monitor_id == 0) {
443 provider_monitor_id = g_bus_watch_name_on_connection(
446 G_BUS_NAME_WATCHER_FLAGS_NONE,
452 if (provider_monitor_id == 0) {
453 /* LCOV_EXCL_START */
454 ErrPrint("watch on name fail");
455 return SHORTCUT_ERROR_IO_ERROR;
460 return SHORTCUT_ERROR_NONE;
463 EXPORT_API int shortcut_set_remove_cb(shortcut_remove_cb remove_cb, void *user_data)
467 if (remove_cb == NULL)
468 return SHORTCUT_ERROR_INVALID_PARAMETER;
471 if (ret != SHORTCUT_ERROR_NONE) {
472 /* LCOV_EXCL_START */
473 ErrPrint("Can't init dbus %d", ret);
478 ret = _dbus_signal_init();
479 if (ret != SHORTCUT_ERROR_NONE) {
480 /* LCOV_EXCL_START */
481 ErrPrint("Can't init dbus_signal %d", ret);
486 ret = _send_service_register();
487 if (ret != SHORTCUT_ERROR_NONE) {
488 /* LCOV_EXCL_START */
489 ErrPrint("Can't init ipc_monitor_register %d", ret);
494 ret = _dbus_set_watch_name();
495 if (ret != SHORTCUT_ERROR_NONE) {
496 /* LCOV_EXCL_START */
497 ErrPrint("Can't init _dbus_set_watch_name %d", ret);
502 _remove_callback_info.remove_cb = remove_cb;
503 _remove_callback_info.data = user_data;
505 return SHORTCUT_ERROR_NONE;
508 EXPORT_API int shortcut_remove_from_home(const char *name, result_cb_t result_cb, void *user_data)
510 struct result_cb_item *item;
516 ErrPrint("name is NULL.");
517 return SHORTCUT_ERROR_INVALID_PARAMETER;
521 if (ret != SHORTCUT_ERROR_NONE) {
522 /* LCOV_EXCL_START */
523 ErrPrint("Can't init dbus %d", ret);
528 ret = _check_privilege();
529 if (ret != SHORTCUT_ERROR_NONE)
532 appid = _shortcut_get_pkgname_by_pid();
533 item = malloc(sizeof(struct result_cb_item));
535 /* LCOV_EXCL_START */
539 ErrPrint("Heap: %d\n", errno);
540 return SHORTCUT_ERROR_OUT_OF_MEMORY;
544 item->result_cb = result_cb;
545 item->result_internal_cb = NULL;
546 item->data = user_data;
548 body = g_variant_new("(iss)", getpid(), appid, name);
550 ret = _send_async_shortcut(body, item, "remove_shortcut");
551 if (ret != SHORTCUT_ERROR_NONE) {
552 /* LCOV_EXCL_START */
561 g_variant_unref(body);