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;
60 static void _shortcut_send_return(int ret_val, const char *request_id)
63 GDBusMessage *reply = NULL;
66 if (ret != SHORTCUT_ERROR_NONE) {
67 SHORTCUT_ERR("Can't init dbus %d", ret);
71 _send_sync_shortcut(g_variant_new("(is)", ret_val, request_id),
75 g_object_unref(reply);
79 static void _add_shortcut_notify(GVariant *parameters)
81 int ret = SHORTCUT_ERROR_NOT_SUPPORTED;
89 const char *request_id;
91 g_variant_get(parameters, "(&si&s&si&s&si)", &request_id, &sender_pid, &appid, &name, &type, &content, &icon, &allow_duplicate);
92 SHORTCUT_DBG("_add_shortcut_notify sender pid : [%d] appid : [%s]", sender_pid, appid);
94 if (_request_callback_info.request_cb != NULL)
95 ret = _request_callback_info.request_cb(appid, name, type, content, icon, sender_pid, -1.0f, allow_duplicate, _request_callback_info.data);
97 SHORTCUT_DBG("request_cb is null.");
98 _shortcut_send_return(ret, request_id);
103 /* LCOV_EXCL_START */
104 static void _add_shortcut_widget_notify(GVariant *parameters)
106 int ret = SHORTCUT_ERROR_NOT_SUPPORTED;
115 const char *request_id;
117 g_variant_get(parameters, "(&si&s&si&s&sdi)", &request_id, &sender_pid, &appid, &name, &type, &content, &icon, &period, &allow_duplicate);
118 SHORTCUT_DBG("_add_shortcut_widget_notify sender pid : [%d] appid : [%s]", sender_pid, appid);
120 if (_request_callback_info.request_cb != NULL)
121 ret = _request_callback_info.request_cb(appid, name, type, content, icon, sender_pid, period, allow_duplicate, _request_callback_info.data);
123 SHORTCUT_DBG("request_cb is null.");
124 _shortcut_send_return(ret, request_id);
128 static void _remove_shortcut_notify(GVariant *parameters)
130 int ret = SHORTCUT_ERROR_NOT_SUPPORTED;
134 const char *request_id;
136 g_variant_get(parameters, "(&si&s&s)", &request_id, &sender_pid, &appid, &name);
137 SHORTCUT_DBG("_remove_shortcut_notify sender pid : [%d] appid : [%s]", sender_pid, appid);
139 if (_remove_callback_info.remove_cb != NULL)
140 ret = _remove_callback_info.remove_cb(appid, name, sender_pid, _remove_callback_info.data);
142 SHORTCUT_DBG("remove_cb is null.");
143 _shortcut_send_return(ret, request_id);
146 /* LCOV_EXCL_START */
147 static void _handle_shortcut_notify(GDBusConnection *connection,
148 const gchar *sender_name,
149 const gchar *object_path,
150 const gchar *interface_name,
151 const gchar *signal_name,
152 GVariant *parameters,
155 SHORTCUT_DBG("signal_name : [%s]", signal_name);
156 if (g_strcmp0(signal_name, "add_shortcut_notify") == 0)
157 _add_shortcut_notify(parameters);
158 else if (g_strcmp0(signal_name, "add_shortcut_widget_notify") == 0)
159 _add_shortcut_widget_notify(parameters);
160 else if (g_strcmp0(signal_name, "remove_shortcut_notify") == 0)
161 _remove_shortcut_notify(parameters);
167 GError *error = NULL;
169 if (_gdbus_conn == NULL) {
170 _gdbus_conn = g_bus_get_sync(G_BUS_TYPE_SYSTEM, NULL, &error);
172 if (_gdbus_conn == NULL) {
173 /* LCOV_EXCL_START */
176 SHORTCUT_ERR("Failed to get dbus [%s]", error->message);
180 return SHORTCUT_ERROR_IO_ERROR;
183 shortcut_error_quark();
186 return SHORTCUT_ERROR_NONE;
189 int _dbus_signal_init()
191 int ret = SHORTCUT_ERROR_NONE;
194 if (monitor_id == 0) {
195 id = g_dbus_connection_signal_subscribe(
198 PROVIDER_SHORTCUT_INTERFACE_NAME, /* interface */
200 PROVIDER_OBJECT_PATH, /* path */
202 G_DBUS_SIGNAL_FLAGS_NONE,
203 _handle_shortcut_notify,
206 SHORTCUT_DBG("subscribe id : %d", id);
208 /* LCOV_EXCL_START */
209 ret = SHORTCUT_ERROR_IO_ERROR;
210 SHORTCUT_ERR("Failed to _register_noti_dbus_interface");
213 SHORTCUT_INFO("get dbus connection success");
221 char *_shortcut_get_pkgname_by_pid(void)
223 char pkgname[SHORTCUT_PKGNAME_LEN + 1] = { 0, };
224 char buf[SHORTCUT_PKGNAME_LEN + 1] = { 0, };
231 ret = aul_app_get_pkgname_bypid(pid, pkgname, sizeof(pkgname));
233 /* LCOV_EXCL_START */
234 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
236 fd = open(buf, O_RDONLY);
240 ret = read(fd, pkgname, sizeof(pkgname) - 1);
250 * "ret" is not able to be larger than "sizeof(pkgname) - 1",
251 * if the system is not going wrong.
254 if (strlen(pkgname) <= 0)
258 dup_pkgname = strdup(pkgname);
260 SHORTCUT_ERR("Heap: %d\n", errno); /* LCOV_EXCL_LINE */
266 * implement user request
268 int _send_sync_shortcut(GVariant *body, GDBusMessage **reply, char *cmd)
272 int ret = SHORTCUT_ERROR_NONE;
274 msg = g_dbus_message_new_method_call(
276 PROVIDER_OBJECT_PATH,
277 PROVIDER_SHORTCUT_INTERFACE_NAME,
280 /* LCOV_EXCL_START */
281 SHORTCUT_ERR("Can't allocate new method call");
283 g_variant_unref(body);
284 return SHORTCUT_ERROR_OUT_OF_MEMORY;
289 g_dbus_message_set_body(msg, body);
291 *reply = g_dbus_connection_send_message_with_reply_sync(
294 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
303 /* LCOV_EXCL_START */
304 ret = SHORTCUT_ERROR_COMM;
306 SHORTCUT_ERR("No reply. cmd = %s, error = %s", cmd, err->message);
307 if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
308 ret = SHORTCUT_ERROR_PERMISSION_DENIED;
315 if (g_dbus_message_to_gerror(*reply, &err)) {
316 /* LCOV_EXCL_START */
317 if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
318 ret = SHORTCUT_ERROR_PERMISSION_DENIED;
322 SHORTCUT_ERR("_send_sync_shortcut error %s err code: %d", err->message, ret);
328 SHORTCUT_DBG("_send_sync_shortcut done !!");
329 return SHORTCUT_ERROR_NONE;
332 int _send_service_register()
334 GDBusMessage *reply = NULL;
337 result = _send_sync_shortcut(g_variant_new("(i)", getuid()), &reply, "shortcut_service_register");
338 SHORTCUT_ERR("_send_service_register done");
342 static void _send_message_with_reply_sync_cb(GDBusConnection *connection,
348 GDBusMessage *reply = NULL;
350 struct result_cb_item *cb_item = (struct result_cb_item *)user_data;
352 if (cb_item == NULL) {
353 /* LCOV_EXCL_START */
354 SHORTCUT_ERR("Failed to get a callback item");
359 reply = g_dbus_connection_send_message_with_reply_finish(
365 /* LCOV_EXCL_START */
367 SHORTCUT_ERR("No reply. error = %s", err->message);
370 result = SHORTCUT_ERROR_COMM;
374 if (g_dbus_message_to_gerror(reply, &err)) {
375 /* LCOV_EXCL_START */
376 if (err->code == G_DBUS_ERROR_ACCESS_DENIED)
377 result = SHORTCUT_ERROR_PERMISSION_DENIED;
381 SHORTCUT_ERR("_send_message_with_reply_sync_cb error %s err code: %d", err->message, result);
385 body = g_dbus_message_get_body(reply);
386 g_variant_get(body, "(i)", &result);
389 if (cb_item->result_internal_cb)
390 cb_item->result_internal_cb(result, getpid(), cb_item->data); /* LCOV_EXCL_LINE */
391 else if (cb_item->result_cb)
392 cb_item->result_cb(result, cb_item->data);
395 g_object_unref(reply);
400 int _send_async_shortcut(GVariant *body, struct result_cb_item *cb_item, char *cmd)
403 msg = g_dbus_message_new_method_call(
405 PROVIDER_OBJECT_PATH,
406 PROVIDER_SHORTCUT_INTERFACE_NAME,
409 /* LCOV_EXCL_START */
410 SHORTCUT_ERR("Can't allocate new method call");
411 return SHORTCUT_ERROR_OUT_OF_MEMORY;
415 if (g_variant_is_floating(body))
419 g_dbus_message_set_body(msg, body);
421 g_dbus_connection_send_message_with_reply(
424 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
428 (GAsyncReadyCallback)_send_message_with_reply_sync_cb,
434 SHORTCUT_DBG("_send_async_shortcut done !!");
435 return SHORTCUT_ERROR_NONE;
438 int _check_privilege(void)
440 GDBusMessage *reply = NULL;
441 int ret = SHORTCUT_ERROR_NONE;
443 ret = _send_sync_shortcut(NULL, &reply, "check_privilege");
446 g_object_unref(reply);
452 /* LCOV_EXCL_START */
453 static void _on_name_appeared(GDBusConnection *connection,
455 const gchar *name_owner,
458 SHORTCUT_DBG("name appeared : %s", name);
459 _send_service_register();
463 /* LCOV_EXCL_START */
464 static void _on_name_vanished(GDBusConnection *connection,
468 SHORTCUT_DBG("name vanished : %s", name);
472 void _ipc_monitor_fini(void)
474 if (provider_monitor_id) {
475 g_bus_unwatch_name(provider_monitor_id);
476 provider_monitor_id = 0;
480 g_dbus_connection_signal_unsubscribe(_gdbus_conn, monitor_id);
485 g_object_unref(_gdbus_conn);
491 void _set_request_cb(shortcut_request_cb request_cb, void *data)
493 _request_callback_info.request_cb = request_cb;
494 _request_callback_info.data = data;
497 void _unset_request_cb(void)
499 if (_remove_callback_info.remove_cb == NULL &&
500 _remove_callback_info.data == NULL)
503 _request_callback_info.request_cb = NULL;
504 _request_callback_info.data = NULL;
507 void _set_remove_cb(shortcut_remove_cb remove_cb, void *data)
509 _remove_callback_info.remove_cb = remove_cb;
510 _remove_callback_info.data = data;
513 void _unset_remove_cb(void)
515 if (_request_callback_info.request_cb == NULL &&
516 _request_callback_info.data == NULL)
519 _remove_callback_info.remove_cb = NULL;
520 _remove_callback_info.data = NULL;
523 int _dbus_set_watch_name()
525 if (provider_monitor_id == 0) {
526 provider_monitor_id = g_bus_watch_name_on_connection(
529 G_BUS_NAME_WATCHER_FLAGS_NONE,
535 if (provider_monitor_id == 0) {
536 /* LCOV_EXCL_START */
537 SHORTCUT_ERR("watch on name fail");
538 return SHORTCUT_ERROR_IO_ERROR;
543 return SHORTCUT_ERROR_NONE;