2 * Copyright (c) 2017 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
18 * @file privacy_privilege_manager.c
19 * @author Piotr Sawicki <p.sawicki2@partner.samsung.com>
20 * @brief The implementation of Privacy Privilege Manager CAPI.
25 #include <askuser-notification-client.h>
27 #include <privacy_privilege_manager.h>
29 #define UNUSED __attribute__((unused))
31 struct ppm_private_s {
32 askuser_client *client;
34 GIOCondition condition;
37 typedef struct ppm_private_s ppm_private;
39 struct ppm_callback_closure_s {
41 ppm_popup_response_cb callback;
43 typedef struct ppm_callback_closure_s ppm_callback_closure;
45 static ppm_private *ppm_handle = NULL;
47 static void ppm_private_init(ppm_private *handle)
49 handle->channel = NULL;
50 handle->condition = 0;
54 static ppm_error_e ask_user_to_ppm_error(int ask_error)
56 ppm_error_e ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
59 case ASKUSER_API_SUCCESS:
60 ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
62 case ASKUSER_API_UNKNOWN_ERROR:
63 ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN;
65 case ASKUSER_API_OUT_OF_MEMORY:
66 ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
68 case ASKUSER_API_INVALID_PARAM:
69 ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER;
71 case ASKUSER_API_CONNECTION_ERROR:
72 ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_IO_ERROR;
74 case ASKUSER_API_ALREADY_IN_PROGRESS:
75 ret = PRIVACY_PRIVILEGE_MANAGER_ERROR_ALREADY_IN_PROGRESS;
83 static ppm_check_result_e ask_user_check_result_to_ppm(askuser_check_result result)
86 case ASKUSER_CHECK_RESULT_ALLOW:
87 return PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ALLOW;
88 case ASKUSER_CHECK_RESULT_DENY:
89 return PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY;
90 case ASKUSER_CHECK_RESULT_ASK:
91 return PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_ASK;
94 return PRIVACY_PRIVILEGE_MANAGER_CHECK_RESULT_DENY;
97 static ppm_popup_result_e askuser_client_popup_result_to_ppm(askuser_popup_result result)
100 case ASKUSER_POPUP_RESULT_ALLOW_FOREVER:
101 return PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_ALLOW_FOREVER;
102 case ASKUSER_POPUP_RESULT_DENY_FOREVER:
103 return PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_FOREVER;
104 case ASKUSER_POPUP_RESULT_DENY_ONCE:
105 return PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_ONCE;
108 return PRIVACY_PRIVILEGE_MANAGER_POPUP_RESULT_DENY_ONCE;
111 static ppm_call_cause_e askuser_client_popup_cause_to_ppm(askuser_call_cause cause)
114 case ASKUSER_CALL_CAUSE_ANSWER:
115 return PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ANSWER;
116 case ASKUSER_CALL_CAUSE_ERROR:
117 case ASKUSER_CALL_CAUSE_FINALIZE:
118 return PRIVACY_PRIVILEGE_MANAGER_CALL_CAUSE_ERROR;
121 return ASKUSER_CALL_CAUSE_ERROR;
124 static int g_io_condition_to_askuser_events(GIOCondition cond)
126 return ((cond & G_IO_IN) ? ASKUSER_READ_EVENT : 0) |
127 ((cond & G_IO_OUT) ? ASKUSER_WRITE_EVENT : 0);
130 static GIOCondition askuser_events_to_g_io_condition(int events)
132 return ((events & ASKUSER_READ_EVENT) ? G_IO_IN : 0) |
133 ((events & ASKUSER_WRITE_EVENT) ? G_IO_OUT : 0);
136 static gboolean ppm_error_condition(GIOCondition cond)
138 return !!(cond & (G_IO_ERR | G_IO_HUP | G_IO_NVAL));
141 static gboolean ppm_is_connected(ppm_private *handle)
143 return handle->channel != NULL;
146 static gboolean ppm_gio_cb(GIOChannel *src, GIOCondition cond, gpointer data)
149 ppm_private *handle = (ppm_private *) data;
151 fd = g_io_channel_unix_get_fd(src);
152 events = g_io_condition_to_askuser_events(cond);
154 (void) askuser_client_process(handle->client, fd,
155 ppm_error_condition(cond) ? ASKUSER_EMPTY_EVENTS : events);
160 static void ask_status_callback(int fd, int events, void *p_user_data)
162 ppm_private *handle = (ppm_private *) p_user_data;
163 GIOCondition gio_condition = askuser_events_to_g_io_condition(events);
165 if (events == ASKUSER_EMPTY_EVENTS) {
166 if (ppm_is_connected(handle)) {
167 g_source_remove(handle->watch_id);
168 g_io_channel_unref(handle->channel);
169 ppm_private_init(handle);
174 if (!ppm_is_connected(handle)) {
175 handle->condition = gio_condition;
176 handle->channel = g_io_channel_unix_new(fd);
178 g_io_channel_set_encoding (handle->channel, NULL, NULL);
179 g_io_channel_set_close_on_unref(handle->channel, FALSE);
181 handle->watch_id = g_io_add_watch(handle->channel,
182 handle->condition | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
188 if (handle->condition != gio_condition) {
189 handle->condition = gio_condition;
190 g_source_remove(handle->watch_id);
191 handle->watch_id = g_io_add_watch(handle->channel,
192 handle->condition | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
198 static void ppm_popup_response_callback(UNUSED int request_id, askuser_call_cause cause,
199 askuser_popup_result result, const char *privilege,
202 ppm_callback_closure *callback_closure = (ppm_callback_closure *) p_user_data;
204 /* Don't invoke callback while the application is finishing. The user data
205 * may already have been destroyed.
207 if (cause == ASKUSER_CALL_CAUSE_FINALIZE) {
208 free(callback_closure);
212 ppm_call_cause_e ppm_cause = askuser_client_popup_cause_to_ppm(cause);
213 ppm_check_result_e ppm_result = askuser_client_popup_result_to_ppm(result);
215 callback_closure->callback(ppm_cause, ppm_result, privilege, callback_closure->user_data);
217 free(callback_closure);
220 static void ppm_free_client()
222 if (ppm_handle != NULL) {
223 askuser_client_finalize(ppm_handle->client);
229 static int ppm_init_client()
231 if (ppm_handle == NULL) {
232 ppm_handle = (ppm_private *) calloc(1, sizeof(ppm_private));
233 if (ppm_handle == NULL) {
234 return PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
237 ppm_private_init(ppm_handle);
239 int ret = askuser_client_initialize(&ppm_handle->client, ask_status_callback, ppm_handle);
240 if (ret != ASKUSER_API_SUCCESS) {
243 return ask_user_to_ppm_error(ret);
246 ret = atexit(ppm_free_client);
248 askuser_client_finalize(ppm_handle->client);
251 return PRIVACY_PRIVILEGE_MANAGER_ERROR_UNKNOWN;
255 return PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
259 int ppm_check_privilege(const char *privilege, ppm_check_result_e *result)
261 if (!privilege || !result) {
262 return PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER;
265 int ret = ppm_init_client();
266 if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
270 askuser_check_result check_result = ASKUSER_CHECK_RESULT_DENY;
271 ret = askuser_client_check_privilege(ppm_handle->client, privilege, &check_result);
272 if (ret != ASKUSER_API_SUCCESS) {
273 return ask_user_to_ppm_error(ret);
276 *result = ask_user_check_result_to_ppm(check_result);
278 return PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;
282 int ppm_popup_request(const char *privilege, ppm_popup_response_cb callback, void *user_data)
284 if (!privilege || !callback) {
285 return PRIVACY_PRIVILEGE_MANAGER_ERROR_INVALID_PARAMETER;
288 int ret = ppm_init_client();
289 if (ret != PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE) {
293 ppm_callback_closure *callback_closure = (ppm_callback_closure *) calloc(1, sizeof(ppm_callback_closure));
294 if (callback_closure == NULL) {
295 return PRIVACY_PRIVILEGE_MANAGER_ERROR_OUT_OF_MEMORY;
298 callback_closure->callback = callback;
299 callback_closure->user_data = user_data;
301 ret = askuser_client_popup_request(ppm_handle->client, privilege, ppm_popup_response_callback,
302 callback_closure, NULL);
303 if (ret != ASKUSER_API_SUCCESS) {
304 free(callback_closure);
305 return ask_user_to_ppm_error(ret);
308 return PRIVACY_PRIVILEGE_MANAGER_ERROR_NONE;