Add a pid in logs
[platform/core/uifw/e-mod-tizen-keyrouter.git] / src / e_mod_main_wl.c
1 #define E_COMP_WL
2 #include "e_mod_main_wl.h"
3 #include <string.h>
4
5 E_KeyrouterPtr krt = NULL;
6 E_API E_Module_Api e_modapi = { E_MODULE_API_VERSION, "Keyrouter Module of Window Manager" };
7
8 static E_Keyrouter_Config_Data *_e_keyrouter_init(E_Module *m);
9 static void _e_keyrouter_init_handlers(void);
10 static void _e_keyrouter_deinit_handlers(void);
11
12 static Eina_Bool _e_keyrouter_query_tizen_key_table(void);
13 static int _e_keyrouter_wl_array_length(const struct wl_array *array);
14
15 static Eina_Bool _e_keyrouter_client_cb_stack(void *data, int type, void *event);
16 static Eina_Bool _e_keyrouter_client_cb_remove(void *data, int type, void *event);
17 static void _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data);
18 static void _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data);
19
20 static int _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode);
21 static int _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key);
22
23 #ifdef ENABLE_CYNARA
24 static void _e_keyrouter_util_cynara_log(const char *func_name, int err);
25 static Eina_Bool _e_keyrouter_util_do_privilege_check(struct wl_client *client, int socket_fd, uint32_t mode, uint32_t keycode);
26
27 #define E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO(func_name, ret, label) \
28   do \
29     { \
30        if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret)) \
31           { \
32              _e_keyrouter_util_cynara_log(func_name, ret); \
33              goto label; \
34           } \
35     } \
36   while (0)
37 #endif
38
39 static int
40 _e_keyrouter_keygrab_set(struct wl_client *client, struct wl_resource *surface, uint32_t key, uint32_t mode)
41 {
42    int res=0;
43
44 #ifdef ENABLE_CYNARA
45    if (EINA_FALSE == _e_keyrouter_util_do_privilege_check(client,
46                        wl_client_get_fd(client), mode, key))
47      {
48         return TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
49      }
50 #endif
51
52    if (!surface)
53      {
54         /* Regarding topmost mode, a client must request to grab a key with a valid surface. */
55         if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
56           {
57              KLWRN("Invalid surface for TOPMOST grab mode ! (key=%d, mode=%d)\n", key, mode);
58
59              return TIZEN_KEYROUTER_ERROR_INVALID_SURFACE;
60           }
61      }
62
63    /* Check the given key range */
64    if (krt->max_tizen_hwkeys < key)
65      {
66         KLWRN("Invalid range of key ! (keycode:%d)\n", key);
67         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
68      }
69
70    /* Check whether the key can be grabbed or not !
71     * Only key listed in Tizen key layout file can be grabbed. */
72    if (0 == krt->HardKeys[key].keycode)
73      {
74         KLWRN("Invalid key ! Disabled to grab ! (keycode:%d)\n", key);
75         return TIZEN_KEYROUTER_ERROR_INVALID_KEY;
76      }
77
78    /* Check whether the mode is valid or not */
79    if (TIZEN_KEYROUTER_MODE_REGISTERED < mode)
80      {
81         KLWRN("Invalid range of mode ! (mode:%d)\n", mode);
82         return  TIZEN_KEYROUTER_ERROR_INVALID_MODE;
83      }
84
85    /* Check whether the request key can be grabbed or not */
86    res = e_keyrouter_set_keygrab_in_list(surface, client, key, mode);
87
88    return res;
89 }
90
91 static int
92 _e_keyrouter_keygrab_unset(struct wl_client *client, struct wl_resource *surface, uint32_t key)
93 {
94    /* Ungrab top position grabs first. This grab mode do not need privilege */
95    if (!surface)
96      e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
97    else
98      e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_TOPMOST);
99
100 #ifdef ENABLE_CYNARA
101    if (EINA_FALSE == _e_keyrouter_util_do_privilege_check(client,
102                        wl_client_get_fd(client), TIZEN_KEYROUTER_MODE_NONE, key))
103      {
104         return TIZEN_KEYROUTER_ERROR_NONE;
105      }
106 #endif
107
108    if (!surface)
109      {
110         /* EXCLUSIVE grab */
111         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
112
113         /* OVERRIDABLE_EXCLUSIVE grab */
114         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
115
116         /* SHARED grab */
117         e_keyrouter_find_and_remove_client_from_list(NULL, client, key, TIZEN_KEYROUTER_MODE_SHARED);
118
119         return TIZEN_KEYROUTER_ERROR_NONE;
120      }
121
122    /* EXCLUSIVE grab */
123    e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_EXCLUSIVE);
124
125    /* OVERRIDABLE_EXCLUSIVE grab */
126    e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE);
127
128    /* SHARED grab */
129    e_keyrouter_find_and_remove_client_from_list(surface, client, key, TIZEN_KEYROUTER_MODE_SHARED);
130
131    /* REGISTERED grab */
132    e_keyrouter_unset_keyregister(surface, client, key);
133
134    return TIZEN_KEYROUTER_ERROR_NONE;
135 }
136
137 /* tizen_keyrouter_set_keygrab request handler */
138 static void
139 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
140 {
141    int res = 0;
142
143    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
144    KLINF("Key grab request (client: %p, surface: %p, pid: %d, key:%d, mode:%d)\n", client, surface, e_keyrouter_util_get_pid(client, surface), key, mode);
145
146    res = _e_keyrouter_keygrab_set(client, surface, key, mode);
147
148    TRACE_INPUT_END();
149    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res);
150 }
151
152 /* tizen_keyrouter unset_keygrab request handler */
153 static void
154 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
155 {
156    int res = 0;
157
158    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
159    KLINF("Key ungrab request (client: %p, surface: %p, pid: %d, key:%d)\n", client, surface, e_keyrouter_util_get_pid(client, surface), key);
160
161    res = _e_keyrouter_keygrab_unset(client, surface, key);
162
163    TRACE_INPUT_END();
164    tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res);
165 }
166
167 /* tizen_keyrouter get_keygrab_status request handler */
168 static void
169 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
170 {
171    (void) client;
172    (void) resource;
173    (void) surface;
174    (void) key;
175    int mode = TIZEN_KEYROUTER_MODE_NONE;
176
177    TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
178    mode = e_keyrouter_find_key_in_list(surface, client, key);
179
180    TRACE_INPUT_END();
181    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
182 }
183
184 static void
185 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
186 {
187    struct wl_array grab_result_list = {0,};
188    E_Keyrouter_Grab_Result *grab_result = NULL;
189    E_Keyrouter_Grab_Request *grab_request = NULL;
190    int res = TIZEN_KEYROUTER_ERROR_NONE;
191
192    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
193
194    wl_array_init(&grab_result_list);
195
196    if (0 != (_e_keyrouter_wl_array_length(grab_list) % 2))
197      {
198         /* FIX ME: Which way is effectively to notify invalid pair to client */
199         KLWRN("Invalid keycode and grab mode pair. Check arguments in a list\n");
200         grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
201         grab_result->request_data.key = 0;
202         grab_result->request_data.mode = 0;
203         grab_result->err = TIZEN_KEYROUTER_ERROR_INVALID_ARRAY;
204         goto send_notify;
205      }
206
207    wl_array_for_each(grab_request, grab_list)
208      {
209         KLINF("Grab request using list  (client: %p, surface: %p, pid: %d, key: %d, mode: %d]\n", client, surface, e_keyrouter_util_get_pid(client, surface), grab_request->key, grab_request->mode);
210         res = _e_keyrouter_keygrab_set(client, surface, grab_request->key, grab_request->mode);
211         grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
212         if (grab_result)
213           {
214              grab_result->request_data.key = grab_request->key;
215              grab_result->request_data.mode = grab_request->mode;
216              grab_result->err = res;
217           }
218      }
219
220 send_notify:
221    TRACE_INPUT_END();
222    tizen_keyrouter_send_keygrab_notify_list(resource, surface, &grab_result_list);
223    wl_array_release(&grab_result_list);
224 }
225
226 static void
227 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
228 {
229    struct wl_array grab_result_list = {0,};
230    E_Keyrouter_Grab_Result *grab_result = NULL;
231    int *ungrab_request = NULL;
232    int res = TIZEN_KEYROUTER_ERROR_NONE;
233
234    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
235
236    wl_array_init(&grab_result_list);
237
238    wl_array_for_each(ungrab_request, ungrab_list)
239      {
240         KLINF("Ungrab request using list  (client: %p, surface: %p, pid: %d, key: %d, res: %d]\n", client, surface, e_keyrouter_util_get_pid(client, surface), *ungrab_request, res);
241         res = _e_keyrouter_keygrab_unset(client, surface, *ungrab_request);
242         grab_result = wl_array_add(&grab_result_list, sizeof(E_Keyrouter_Grab_Result));
243         if (grab_result)
244           {
245              grab_result->request_data.key = *ungrab_request;
246              grab_result->request_data.mode = TIZEN_KEYROUTER_MODE_NONE;
247              grab_result->err = res;
248           }
249      }
250
251    TRACE_INPUT_END();
252    tizen_keyrouter_send_keygrab_notify_list(resource, surface, &grab_result_list);
253    wl_array_release(&grab_result_list);
254 }
255
256
257 /* Function for registering wl_client destroy listener */
258 int
259 e_keyrouter_add_client_destroy_listener(struct wl_client *client)
260 {
261    struct wl_listener *destroy_listener = NULL;
262    Eina_List *l;
263    struct wl_client *wc_data;
264
265    EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
266      {
267         if (wc_data)
268           {
269              if (wc_data == client)
270                {
271                   return TIZEN_KEYROUTER_ERROR_NONE;
272                }
273           }
274      }
275
276    destroy_listener = E_NEW(struct wl_listener, 1);
277
278    if (!destroy_listener)
279      {
280         KLERR("Failed to allocate memory for wl_client destroy listener !\n");
281         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
282      }
283
284    destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
285    wl_client_add_destroy_listener(client, destroy_listener);
286    krt->grab_client_list = eina_list_append(krt->grab_client_list, client);
287
288    return TIZEN_KEYROUTER_ERROR_NONE;
289 }
290
291 /* Function for registering wl_surface destroy listener */
292 int
293 e_keyrouter_add_surface_destroy_listener(struct wl_resource *surface)
294 {
295    struct wl_listener *destroy_listener = NULL;
296    Eina_List *l;
297    struct wl_resource *surface_data;
298
299    EINA_LIST_FOREACH(krt->grab_surface_list, l, surface_data)
300      {
301         if (surface_data)
302           {
303              if (surface_data == surface)
304                {
305                   return TIZEN_KEYROUTER_ERROR_NONE;
306                }
307           }
308      }
309
310    destroy_listener = E_NEW(struct wl_listener, 1);
311
312    if (!destroy_listener)
313      {
314         KLERR("Failed to allocate memory for wl_surface destroy listener !\n");
315         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
316      }
317
318    destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
319    wl_resource_add_destroy_listener(surface, destroy_listener);
320    krt->grab_surface_list = eina_list_append(krt->grab_surface_list, surface);
321
322    return TIZEN_KEYROUTER_ERROR_NONE;
323 }
324
325
326 static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
327    _e_keyrouter_cb_keygrab_set,
328    _e_keyrouter_cb_keygrab_unset,
329    _e_keyrouter_cb_get_keygrab_status,
330    _e_keyrouter_cb_keygrab_set_list,
331    _e_keyrouter_cb_keygrab_unset_list
332 };
333
334 /* tizen_keyrouter global object destroy function */
335 static void
336 _e_keyrouter_cb_destory(struct wl_resource *resource)
337 {
338    /* TODO : destroy resources if exist */
339 }
340
341 /* tizen_keyrouter global object bind function */
342 static void
343 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
344 {
345    E_KeyrouterPtr krt_instance = data;
346    struct wl_resource *resource;
347
348    resource = wl_resource_create(client, &tizen_keyrouter_interface, MIN(version, 1), id);
349
350    KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)\n");
351
352    if (!resource)
353      {
354         KLERR("Failed to create resource ! (version :%d, id:%d)\n", version, id);
355         wl_client_post_no_memory(client);
356          return;
357      }
358
359    wl_resource_set_implementation(resource, &_e_keyrouter_implementation, krt_instance, _e_keyrouter_cb_destory);
360 }
361
362 static Eina_Bool
363 _event_filter(void *data, void *loop_data EINA_UNUSED, int type, void *event)
364 {
365    (void) data;
366    (void) type;
367    (void) event;
368
369    /* Filter only for key down/up event */
370    if (ECORE_EVENT_KEY_DOWN == type || ECORE_EVENT_KEY_UP == type)
371      {
372         return e_keyrouter_process_key_event(event, type);
373      }
374
375    return EINA_TRUE;
376 }
377
378 static E_Keyrouter_Config_Data *
379 _e_keyrouter_init(E_Module *m)
380 {
381    E_Keyrouter_Config_Data *kconfig = NULL;
382    krt = E_NEW(E_Keyrouter, 1);
383    Eina_Bool res = EINA_FALSE;
384    int ret;
385
386    TRACE_INPUT_BEGIN(_e_keyrouter_init);
387
388    if (!krt)
389      {
390         KLERR("Failed to allocate memory for krt !\n");
391         TRACE_INPUT_END();
392         return NULL;
393      }
394
395    if (!e_comp)
396      {
397         KLERR("Failed to initialize keyrouter module ! (e_comp == NULL)\n");
398         goto err;
399      }
400
401    kconfig = E_NEW(E_Keyrouter_Config_Data, 1);
402    EINA_SAFETY_ON_NULL_GOTO(kconfig, err);
403
404    kconfig->module = m;
405
406    e_keyrouter_conf_init(kconfig);
407    EINA_SAFETY_ON_NULL_GOTO(kconfig->conf, err);
408    krt->conf = kconfig;
409
410    /* Get keyname and keycode pair from Tizen Key Layout file */
411    res = _e_keyrouter_query_tizen_key_table();
412    EINA_SAFETY_ON_FALSE_GOTO(res, err);
413
414    /* Add filtering mechanism */
415    krt->ef_handler = ecore_event_filter_add(NULL, _event_filter, NULL, NULL);
416    _e_keyrouter_init_handlers();
417
418    krt->global = wl_global_create(e_comp_wl->wl.disp, &tizen_keyrouter_interface, 1, krt, _e_keyrouter_cb_bind);
419    if (!krt->global)
420      {
421         KLERR("Failed to create global !\n");
422         goto err;
423      }
424
425 #ifdef ENABLE_CYNARA
426    ret = cynara_initialize(&krt->p_cynara, NULL);
427    if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
428      {
429         _e_keyrouter_util_cynara_log("cynara_initialize", ret);
430         krt->p_cynara = NULL;
431      }
432 #endif
433
434    TRACE_INPUT_END();
435    return kconfig;
436
437 err:
438    if (kconfig)
439      {
440         e_keyrouter_conf_deinit(kconfig);
441         E_FREE(kconfig);
442      }
443    _e_keyrouter_deinit_handlers();
444    if (krt && krt->ef_handler) ecore_event_filter_del(krt->ef_handler);
445    if (krt) E_FREE(krt);
446
447    TRACE_INPUT_END();
448    return NULL;
449 }
450
451 E_API void *
452 e_modapi_init(E_Module *m)
453 {
454    return _e_keyrouter_init(m);
455 }
456
457 E_API int
458 e_modapi_shutdown(E_Module *m)
459 {
460    E_Keyrouter_Config_Data *kconfig = m->data;
461    e_keyrouter_conf_deinit(kconfig);
462    _e_keyrouter_deinit_handlers();
463
464 #ifdef ENABLE_CYNARA
465    if (krt->p_cynara) cynara_finish(krt->p_cynara);
466 #endif
467    /* TODO: free allocated memory */
468
469    return 1;
470 }
471
472 E_API int
473 e_modapi_save(E_Module *m)
474 {
475    /* Save something to be kept */
476    E_Keyrouter_Config_Data *kconfig = m->data;
477    e_config_domain_save("module.keyrouter",
478                         kconfig->conf_edd,
479                         kconfig->conf);
480
481    return 1;
482 }
483
484 /* Function for getting keyname/keycode information from a key layout file */
485 static Eina_Bool
486 _e_keyrouter_query_tizen_key_table(void)
487 {
488    E_Keyrouter_Conf_Edd *kconf = krt->conf->conf;
489    Eina_List *l;
490    E_Keyrouter_Tizen_HWKey *data;
491
492    /* TODO: Make struct in HardKeys to pointer.
493                   If a key is defined, allocate memory to pointer,
494                   that makes to save unnecessary memory */
495    krt->HardKeys = E_NEW(E_Keyrouter_Grabbed_Key, kconf->max_keycode + 1);
496    EINA_SAFETY_ON_NULL_RETURN_VAL(krt->HardKeys, EINA_FALSE);
497
498    krt->numTizenHWKeys = kconf->num_keycode;
499    krt->max_tizen_hwkeys = kconf->max_keycode;
500
501    EINA_LIST_FOREACH(kconf->KeyList, l, data)
502      {
503         if (!data) continue;
504
505         if (0 > data->keycode || krt->max_tizen_hwkeys < data->keycode)
506           {
507              KLWRN("Given keycode(%d) is invalid. It must be bigger than zero, smaller than the maximum value(%d) or equal to it.\n", data->keycode, kconf->max_keycode);
508              continue;
509           }
510
511         krt->HardKeys[data->keycode].keycode = data->keycode;
512         krt->HardKeys[data->keycode].keyname = (char *)eina_stringshare_add(data->name);
513         krt->HardKeys[data->keycode].no_privcheck = data->no_privcheck ? EINA_TRUE : EINA_FALSE;
514      }
515
516    return EINA_TRUE;
517 }
518
519 static int
520 _e_keyrouter_wl_array_length(const struct wl_array *array)
521 {
522    int *data = NULL;
523    int count = 0;
524
525    wl_array_for_each(data, array)
526      {
527         count++;
528      }
529
530    return count;
531 }
532
533 static void
534 _e_keyrouter_deinit_handlers(void)
535 {
536    Ecore_Event_Handler *h = NULL;
537
538    if (!krt ||  !krt->handlers) return;
539
540    EINA_LIST_FREE(krt->handlers, h)
541      ecore_event_handler_del(h);
542 }
543
544 static void
545 _e_keyrouter_init_handlers(void)
546 {
547    E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_STACK, _e_keyrouter_client_cb_stack, NULL);
548    E_LIST_HANDLER_APPEND(krt->handlers, E_EVENT_CLIENT_REMOVE, _e_keyrouter_client_cb_remove, NULL);
549 }
550
551 static Eina_Bool
552 _e_keyrouter_client_cb_stack(void *data, int type, void *event)
553 {
554    E_Event_Client *ev = event;
555    E_Client *ec = ev->ec;
556
557    (void) data;
558    (void) type;
559    (void) event;
560    (void) ev;
561    (void) ec;
562
563    //KLDBG("ec: %p, visibile: %d, focused: %d, take_focus: %d, want_focus: %d, bordername: %s, input_only: %d\n",
564    //        ec, ec->visible, ec->focused, ec->take_focus, ec->want_focus, ec->bordername, ec->input_only);
565
566    krt->isWindowStackChanged = EINA_TRUE;
567    e_keyrouter_clear_registered_window();
568
569    return ECORE_CALLBACK_PASS_ON;
570 }
571
572 static Eina_Bool
573 _e_keyrouter_client_cb_remove(void *data, int type, void *event)
574 {
575    E_Event_Client *ev = event;
576    E_Client *ec = ev->ec;
577
578    (void) data;
579    (void) type;
580    (void) ev;
581    (void) ec;
582
583    /* FIXME: Remove this callback or do something others.
584     *             It was moved to _e_keyrouter_wl_surface_cb_destroy() where it had here.
585     */
586
587    return ECORE_CALLBACK_PASS_ON;
588 }
589
590 static void
591 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
592 {
593    struct wl_client *client = data;
594
595    KLDBG("Listener(%p) called: wl_client: %p is died\n", l, client);
596    e_keyrouter_remove_client_from_list(NULL, client);
597
598    E_FREE(l);
599    l = NULL;
600
601    krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
602 }
603
604 static void
605 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
606 {
607    struct wl_resource *surface = data;
608
609    KLDBG("Listener(%p) called: surface: %p is died\n", l, surface);
610    e_keyrouter_remove_client_from_list(surface, NULL);
611
612    E_FREE(l);
613    l = NULL;
614
615    krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
616 }
617
618 #ifdef ENABLE_CYNARA
619 static void
620 _e_keyrouter_util_cynara_log(const char *func_name, int err)
621 {
622 #define CYNARA_BUFSIZE 128
623    char buf[CYNARA_BUFSIZE] = "\0";
624    int ret;
625
626    ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
627    if (ret != CYNARA_API_SUCCESS)
628      {
629         KLWRN("Failed to cynara_strerror: %d (error log about %s: %d)\n", ret, func_name, err);
630         return;
631      }
632    KLWRN("%s is failed: %s\n", func_name, buf);
633 }
634
635 static Eina_Bool
636 _e_keyrouter_util_do_privilege_check(struct wl_client *client, int socket_fd, uint32_t mode, uint32_t keycode)
637 {
638    int ret, pid, retry_cnt=0;
639    char *clientSmack=NULL, *uid=NULL, *client_session=NULL;
640    Eina_Bool res = EINA_FALSE;
641    Eina_List *l;
642    struct wl_client *wc_data;
643    static Eina_Bool retried = EINA_FALSE;
644
645    /* Top position grab is always allowed. This mode do not need privilege.*/
646    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
647      return EINA_TRUE;
648
649    if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE)
650      return EINA_TRUE;
651
652    /* If initialize cynara is failed, allow keygrabs regardless of the previlege permition. */
653    if (krt->p_cynara == NULL)
654      {
655         if (retried == EINA_FALSE)
656           {
657              retried = EINA_TRUE;
658              for(retry_cnt = 0; retry_cnt < 5; retry_cnt++)
659                {
660                   KLDBG("Retry cynara initialize: %d\n", retry_cnt+1);
661                   ret = cynara_initialize(&krt->p_cynara, NULL);
662                   if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
663                     {
664                       _e_keyrouter_util_cynara_log("cynara_initialize", ret);
665                        krt->p_cynara = NULL;
666                     }
667                   else
668                     {
669                        KLDBG("Success cynara initialize to try %d times\n", retry_cnt+1);
670                        break;
671                     }
672                }
673           }
674         return EINA_TRUE;
675      }
676
677    EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
678      {
679         if (wc_data == client)
680           {
681              res = EINA_TRUE;
682              goto finish;
683           }
684      }
685
686    ret = cynara_creds_socket_get_client(socket_fd, CLIENT_METHOD_SMACK, &clientSmack);
687    E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_client", ret, finish);
688
689    ret = cynara_creds_socket_get_user(socket_fd, USER_METHOD_UID, &uid);
690    E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_user", ret, finish);
691
692    ret = cynara_creds_socket_get_pid(socket_fd, &pid);
693    E_KEYROUTER_CYNARA_ERROR_CHECK_GOTO("cynara_creds_socket_get_pid", ret, finish);
694
695    client_session = cynara_session_from_pid(pid);
696
697    ret = cynara_check(krt->p_cynara, clientSmack, client_session, uid, "http://tizen.org/privilege/keygrab");
698    if (CYNARA_API_ACCESS_ALLOWED == ret)
699      {
700         res = EINA_TRUE;
701         e_keyrouter_add_client_destroy_listener(client);
702      }
703
704 finish:
705    E_FREE(client_session);
706    E_FREE(clientSmack);
707    E_FREE(uid);
708
709    return res;
710 }
711 #endif