e_input_backend: make e_input_backend_intern header file
[platform/upstream/enlightenment.git] / src / bin / server / e_keyrouter_wl.c
1 #include "e_keyrouter_intern.h"
2 #include "e_input_intern.h"
3 #include "e_input_backend_intern.h"
4 #include "e_comp_wl_input_intern.h"
5 #include "e_comp_wl_intern.h"
6 #include "e_client_intern.h"
7 #include "e_config_intern.h"
8 #include "e_comp_input_intern.h"
9 #include "e_input_thread_client_intern.h"
10 #include "e_security.h"
11
12 #include <tizen-extension-server-protocol.h>
13
14 void
15 e_keyrouter_wl_event_surface_send(struct wl_resource *surface, int key, int mode)
16 {
17    Eina_List *l;
18    struct wl_resource *res_data;
19    struct wl_client *wc;
20
21    EINA_SAFETY_ON_NULL_RETURN(krt);
22    EINA_SAFETY_ON_NULL_RETURN(surface);
23
24    wc = wl_resource_get_client(surface);
25    EINA_SAFETY_ON_NULL_RETURN(wc);
26
27    EINA_LIST_FOREACH(krt->resources, l, res_data)
28      {
29         if (wl_resource_get_client(res_data) != wc) continue;
30         if (wl_resource_get_version(res_data) < 2) continue;
31
32         if (e_config->key_input_ttrace_enable)
33           {
34              TRACE_INPUT_BEGIN(tizen_keyrouter_send_event_surface);
35              ELOGF("INPUT", "tizen_keyrouter_send_event_surface|B|", NULL);
36           }
37
38         tizen_keyrouter_send_event_surface(res_data, surface, key, mode);
39
40         if (e_config->key_input_ttrace_enable)
41           {
42              TRACE_INPUT_END();
43              ELOGF("INPUT", "tizen_keyrouter_send_event_surface|E|", NULL);
44           }
45      }
46 }
47
48 static void
49 _e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, enum wl_keyboard_key_state state, Eina_List *key_list, Eina_Bool focused, struct wl_client *client, struct wl_resource *surface)
50 {
51    struct wl_resource *res;
52    Eina_List *l;
53    uint32_t serial, keycode;
54    struct wl_client *wc;
55    E_Comp_Config *comp_conf = NULL;
56
57    keycode = (ev->keycode - 8);
58
59    serial = wl_display_next_serial(e_comp_wl->wl.disp);
60
61    comp_conf = e_comp_config_get();
62
63    if (surface && !focused)
64      {
65         e_comp_wl_connection_lock();
66         e_keyrouter_wl_event_surface_send(surface, ev->keycode, TIZEN_KEYROUTER_MODE_NONE);
67         e_comp_wl_connection_unlock();
68      }
69
70    if (e_config->key_input_ttrace_enable)
71      {
72         TRACE_INPUT_BEGIN(wl_keyboard_send_key:%s:%s, (state ? "PRESS" : "RELEASE"), ev->keyname);
73         ELOGF("INPUT", "wl_keyboard_send_key:%s:%s|B|", NULL, (state ? "PRESS" : "RELEASE"), ev->keyname);
74      }
75
76    EINA_LIST_FOREACH(key_list, l, res)
77      {
78         wc = wl_resource_get_client(res);
79         if (!focused && wc != client) continue;
80         TRACE_INPUT_BEGIN(_e_comp_wl_key_send);
81         if (!e_input_thread_mode_get())
82           {
83              e_comp_wl_send_event_device(client, ev->timestamp, ev->dev, serial);
84           }
85         else
86           {
87              if (dev)
88                e_comp_wl_send_event_e_device(client, ev->timestamp, dev, serial);
89           }
90
91         if (comp_conf && comp_conf->input_log_enable)
92           INF("[Server] Routed Key %s (time: %d)\n", (state ? "Down" : "Up"), ev->timestamp);
93
94         wl_keyboard_send_key(res, serial, ev->timestamp,
95                              keycode, state);
96         TRACE_INPUT_END();
97      }
98
99    if (e_config->key_input_ttrace_enable)
100      {
101         TRACE_INPUT_END();
102         ELOGF("INPUT", "wl_keyboard_send_key|E|", NULL);
103      }
104 }
105
106 Eina_Bool
107 e_keyrouter_wl_key_send(Ecore_Event_Key *ev, E_Device *dev, Eina_Bool pressed, struct wl_client *client, struct wl_resource *surface, Eina_Bool focused)
108 {
109    E_Client *ec = NULL;
110    struct wl_client *wc = NULL;
111    uint32_t keycode;
112    enum wl_keyboard_key_state state;
113
114    if (ev->window != e_comp->ee_win)
115      {
116         return EINA_FALSE;
117      }
118
119    keycode = (ev->keycode - 8);
120    if (!(e_comp_wl = e_comp->wl_comp_data))
121      {
122         return EINA_FALSE;
123      }
124
125 #ifndef E_RELEASE_BUILD
126    if ((ev->modifiers & ECORE_EVENT_MODIFIER_CTRL) &&
127        ((ev->modifiers & ECORE_EVENT_MODIFIER_ALT) ||
128        (ev->modifiers & ECORE_EVENT_MODIFIER_ALTGR)) &&
129        eina_streq(ev->key, "BackSpace"))
130      {
131         exit(0);
132      }
133 #endif
134
135    if (pressed) state = WL_KEYBOARD_KEY_STATE_PRESSED;
136    else state = WL_KEYBOARD_KEY_STATE_RELEASED;
137
138    if (!focused)
139      {
140         _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.resources, EINA_FALSE, client, surface);
141         return EINA_FALSE;
142      }
143
144    if ((!e_client_action_get()) && (!e_comp->input_key_grabs))
145      {
146         ec = e_client_focused_get();
147
148         if (ec && ec->comp_data)
149           {
150              struct wl_resource *surface = e_comp_wl_client_surface_get(ec);
151              if (surface)
152                {
153                   if (e_comp_input_key->kbd.focused)
154                     {
155                        wc = wl_resource_get_client(surface);
156                        _e_keyrouter_wl_key_send(ev, dev, state, e_comp_input_key->kbd.focused, EINA_TRUE, wc, surface);
157                     }
158                }
159
160              /* update modifier state */
161              e_comp_wl_input_keyboard_state_update(keycode, pressed);
162           }
163      }
164    return !!ec;
165 }
166
167 void
168 e_keyrouter_keycancel_send(struct wl_client *client, struct wl_resource *surface, unsigned int key)
169 {
170    Eina_List *l;
171    struct wl_resource *resource = NULL;
172    struct wl_client *wc = NULL;
173    E_Keyrouter_Key_List_NodePtr data;
174    Eina_List *press_ptr_list = NULL;
175
176    if (surface) wc = wl_resource_get_client(surface);
177    else wc = client;
178
179    EINA_SAFETY_ON_NULL_RETURN(wc);
180
181    press_ptr_list = krt->HardKeys[key].press_ptr;
182    EINA_LIST_FOREACH(press_ptr_list, l, data)
183      {
184         if (surface)
185           {
186              if (surface == data->surface)
187                {
188                   EINA_LIST_FOREACH(krt->resources, l, resource)
189                     {
190                        if (wl_resource_get_client(resource) != wc) continue;
191
192                        tizen_keyrouter_send_key_cancel(resource, key-8);
193                     }
194                }
195           }
196         else if (client == data->wc)
197           {
198              EINA_LIST_FOREACH(krt->resources, l, resource)
199                {
200                   if (wl_resource_get_client(resource) != wc) continue;
201
202                   tizen_keyrouter_send_key_cancel(resource, key-8);
203                }
204           }
205      }
206 }
207
208 static int
209 _e_keyrouter_wl_array_length(const struct wl_array *array)
210 {
211    int *data = NULL;
212    int count = 0;
213
214    wl_array_for_each(data, array)
215      {
216         count++;
217      }
218
219    return count;
220 }
221
222 static void
223 _e_keyrouter_input_thread_keygrab_set(void *data)
224 {
225    int res = 0;
226    E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
227    EINA_SAFETY_ON_NULL_RETURN(keygrab_data);
228
229    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
230
231    res = e_keyrouter_keygrab_set(keygrab_data->client, keygrab_data->surface, keygrab_data->key, keygrab_data->mode);
232
233    TRACE_INPUT_END();
234
235    if (res == TIZEN_KEYROUTER_ERROR_NONE)
236      {
237         KLINF("Success to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d)", keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
238               keygrab_data->client, keygrab_data->surface, e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
239      }
240    else
241      KLINF("Failed to %d key %s grab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", keygrab_data->key, e_keyrouter_mode_to_string(keygrab_data->mode),
242         keygrab_data->client, keygrab_data->surface, e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface), res);
243
244    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource, keygrab_data->surface, keygrab_data->key, keygrab_data->mode, res);
245 }
246
247 /* tizen_keyrouter_set_keygrab request handler */
248 static void
249 _e_keyrouter_cb_keygrab_set(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key, uint32_t mode)
250 {
251    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set);
252
253    E_Input_Thread_Request_Keygrab_Data keygrab_data;
254
255    keygrab_data.resource = resource;
256    keygrab_data.surface = surface;
257    keygrab_data.client = client;
258    keygrab_data.key = key;
259    keygrab_data.mode = mode;
260
261    INF("client: %p, surface: %p, key: %d, mode: %d\n", keygrab_data.client, keygrab_data.surface, keygrab_data.key, keygrab_data.mode);
262    e_input_backend_thread_safe_call(_e_keyrouter_input_thread_keygrab_set, &keygrab_data, sizeof(E_Input_Thread_Request_Keygrab_Data));
263 }
264
265 static void
266 _e_keyrouter_input_thread_keygrab_unset(void *data)
267 {
268    int res = 0;
269    E_Input_Thread_Request_Keygrab_Data *keygrab_data = data;
270    EINA_SAFETY_ON_NULL_RETURN(keygrab_data);
271
272    res = e_keyrouter_keygrab_unset(keygrab_data->client, keygrab_data->surface, keygrab_data->key);
273
274    TRACE_INPUT_END();
275
276    if (res == TIZEN_KEYROUTER_ERROR_NONE)
277      KLDBG("Success to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d)", keygrab_data->key, keygrab_data->client, keygrab_data->surface,
278            e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface));
279    else
280      KLINF("Failed to %d key ungrab request (wl_client: %p, wl_surface: %p, pid: %d): res: %d", keygrab_data->key, keygrab_data->client, keygrab_data->surface,
281            e_keyrouter_util_get_pid(keygrab_data->client, keygrab_data->surface), res);
282
283    tizen_keyrouter_send_keygrab_notify(keygrab_data->resource, keygrab_data->surface, keygrab_data->key, TIZEN_KEYROUTER_MODE_NONE, res);
284 }
285
286 /* tizen_keyrouter unset_keygrab request handler */
287 static void
288 _e_keyrouter_cb_keygrab_unset(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
289 {
290    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset);
291
292    E_Input_Thread_Request_Keygrab_Data keygrab_data;
293
294    keygrab_data.resource = resource;
295    keygrab_data.surface = surface;
296    keygrab_data.client = client;
297    keygrab_data.key = key;
298    keygrab_data.mode = TIZEN_KEYROUTER_MODE_NONE; /* UNUSED */
299
300    INF("client: %p, surface: %p, key: %d\n", keygrab_data.client, keygrab_data.surface, keygrab_data.key);
301    e_input_backend_thread_safe_call(_e_keyrouter_input_thread_keygrab_unset, &keygrab_data, sizeof(E_Input_Thread_Request_Keygrab_Data));
302 }
303
304 /* tizen_keyrouter get_keygrab_status request handler */
305 static void
306 _e_keyrouter_cb_get_keygrab_status(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
307 {
308    (void) client;
309    (void) resource;
310    (void) surface;
311    (void) key;
312    int mode = TIZEN_KEYROUTER_MODE_NONE;
313
314    TRACE_INPUT_BEGIN(_e_keyrouter_cb_get_keygrab_status);
315    mode = e_keyrouter_find_key_in_list(surface, client, key);
316
317    TRACE_INPUT_END();
318    tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, TIZEN_KEYROUTER_ERROR_NONE);
319 }
320
321 static void
322 _e_keyrouter_cb_keygrab_set_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
323 {
324    E_Keyrouter_Grab_Request *grab_request = NULL;
325    int res = TIZEN_KEYROUTER_ERROR_NONE;
326    int array_len = 0;
327
328    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_set_list);
329
330    array_len = _e_keyrouter_wl_array_length(grab_list);
331
332    if (0 != (array_len % 3))
333      {
334         /* FIX ME: Which way is effectively to notify invalid pair to client */
335         KLWRN("Invalid keycode and grab mode pair. Check arguments in a list");
336         TRACE_INPUT_END();
337         tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
338         return;
339      }
340
341    wl_array_for_each(grab_request, grab_list)
342      {
343         res = e_keyrouter_keygrab_set(client, surface, grab_request->key, grab_request->mode);
344         grab_request->err = res;
345         if (res == TIZEN_KEYROUTER_ERROR_NONE)
346           KLDBG("Success to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d)",
347                 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
348                 client, surface, e_keyrouter_util_get_pid(client, surface));
349         else
350           KLINF("Failed to %d key %s grab using list(wl_client: %p, wl_surface: %p, pid: %d): res: %d",
351                 grab_request->key, e_keyrouter_mode_to_string(grab_request->mode),
352                 client, surface, e_keyrouter_util_get_pid(client, surface), grab_request->err);
353      }
354
355    TRACE_INPUT_END();
356    tizen_keyrouter_send_keygrab_notify_list(resource, surface, grab_list);
357 }
358
359 static void
360 _e_keyrouter_cb_keygrab_unset_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, struct wl_array *ungrab_list)
361 {
362    E_Keyrouter_Ungrab_Request *ungrab_request = NULL;
363    int res = TIZEN_KEYROUTER_ERROR_NONE;
364    int array_len = 0;
365
366    TRACE_INPUT_BEGIN(_e_keyrouter_cb_keygrab_unset_list);
367
368    array_len = _e_keyrouter_wl_array_length(ungrab_list);
369
370    if (0 != (array_len % 2))
371      {
372         /* FIX ME: Which way is effectively to notify invalid pair to client */
373         KLWRN("Invalid keycode and error pair. Check arguments in a list");
374         TRACE_INPUT_END();
375         tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
376         return;
377      }
378
379    wl_array_for_each(ungrab_request, ungrab_list)
380      {
381         res = e_keyrouter_keygrab_unset(client, surface, ungrab_request->key);
382         ungrab_request->err = res;
383         if (res == TIZEN_KEYROUTER_ERROR_NONE)
384           KLDBG("Success to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d)",
385                 ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface));
386         else
387           KLINF("Failed to ungrab using list: %d key (wl_client: %p, wl_surface: %p, pid: %d): res: %d",
388                 ungrab_request->key, client, surface, e_keyrouter_util_get_pid(client, surface), ungrab_request->err);
389      }
390
391    TRACE_INPUT_END();
392    tizen_keyrouter_send_keygrab_notify_list(resource, surface, ungrab_list);
393 }
394
395 static void
396 _e_keyrouter_cb_keygrab_get_list(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface)
397 {
398    (void) client;
399
400    tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
401 }
402
403 static void
404 _e_keyrouter_cb_set_register_none_key(struct wl_client *client, struct wl_resource *resource, struct wl_resource *surface, uint32_t data)
405 {
406    (void) client;
407    (void) data;
408
409    tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
410 }
411
412 static void
413 _e_keyrouter_cb_get_keyregister_status(struct wl_client *client, struct wl_resource *resource, uint32_t key)
414 {
415    (void) client;
416    (void) key;
417
418    tizen_keyrouter_send_keyregister_notify(resource, (int)EINA_FALSE);
419 }
420
421 static void
422 _e_keyrouter_cb_set_input_config(struct wl_client *client EINA_UNUSED, struct wl_resource *resource, struct wl_resource *surface EINA_UNUSED, uint32_t config_mode EINA_UNUSED, uint32_t value EINA_UNUSED)
423 {
424    tizen_keyrouter_send_set_input_config_notify(resource, 0);
425 }
426
427 static void
428 _e_keyrouter_cb_destroy(struct wl_client *client, struct wl_resource *resource)
429 {
430    wl_resource_destroy(resource);
431 }
432
433 static const struct tizen_keyrouter_interface _e_keyrouter_implementation = {
434    _e_keyrouter_cb_keygrab_set,
435    _e_keyrouter_cb_keygrab_unset,
436    _e_keyrouter_cb_get_keygrab_status,
437    _e_keyrouter_cb_keygrab_set_list,
438    _e_keyrouter_cb_keygrab_unset_list,
439    _e_keyrouter_cb_keygrab_get_list,
440    _e_keyrouter_cb_set_register_none_key,
441    _e_keyrouter_cb_get_keyregister_status,
442    _e_keyrouter_cb_set_input_config,
443    _e_keyrouter_cb_destroy,
444 };
445
446 static void
447 _e_keyrouter_cb_unbind(struct wl_resource *resource)
448 {
449    krt->resources = eina_list_remove(krt->resources, resource);
450 }
451
452 /* tizen_keyrouter global object bind function */
453 static void
454 _e_keyrouter_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
455 {
456    E_KeyrouterPtr krt_instance = data;
457    struct wl_resource *resource;
458
459    resource = wl_resource_create(client, &tizen_keyrouter_interface, version, id);
460
461    KLDBG("wl_resource_create(...,&tizen_keyrouter_interface,...)");
462
463    if (!resource)
464      {
465         KLERR("Failed to create resource ! (version :%d, id:%d)", version, id);
466         wl_client_post_no_memory(client);
467          return;
468      }
469
470    krt->resources = eina_list_append(krt->resources, resource);
471
472    wl_resource_set_implementation(resource, &_e_keyrouter_implementation, krt_instance, _e_keyrouter_cb_unbind);
473 }
474
475 static void
476 _e_keyrouter_wl_client_cb_destroy(struct wl_listener *l, void *data)
477 {
478    struct wl_client *client = data;
479
480    KLDBG("Listener(%p) called: wl_client: %p is died", l, client);
481    e_keyrouter_remove_client_from_list(NULL, client);
482
483    wl_list_remove(&l->link);
484    E_FREE(l);
485
486    krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
487 }
488
489 static void
490 _e_keyrouter_wl_surface_cb_destroy(struct wl_listener *l, void *data)
491 {
492    struct wl_resource *surface = (struct wl_resource *)data;
493
494    KLDBG("Listener(%p) called: surface: %p is died", l, surface);
495    e_keyrouter_remove_client_from_list(surface, NULL);
496
497    wl_list_remove(&l->link);
498    E_FREE(l);
499
500    krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, surface);
501 }
502
503 int
504 e_keyrouter_wl_add_client_destroy_listener(struct wl_client *client)
505 {
506    struct wl_listener *destroy_listener = NULL;
507    Eina_List *l;
508    struct wl_client *wc_data;
509
510    if (!client) return TIZEN_KEYROUTER_ERROR_NONE;
511
512    EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
513      {
514         if (wc_data)
515           {
516              if (wc_data == client)
517                {
518                   return TIZEN_KEYROUTER_ERROR_NONE;
519                }
520           }
521      }
522
523    destroy_listener = E_NEW(struct wl_listener, 1);
524
525    if (!destroy_listener)
526      {
527         KLERR("Failed to allocate memory for wl_client destroy listener !");
528         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
529      }
530
531    destroy_listener->notify = _e_keyrouter_wl_client_cb_destroy;
532    wl_client_add_destroy_listener(client, destroy_listener);
533    krt->grab_client_list = eina_list_append(krt->grab_client_list, client);
534
535    return TIZEN_KEYROUTER_ERROR_NONE;
536 }
537
538 /* Function for registering wl_surface destroy listener */
539 int
540 e_keyrouter_wl_add_surface_destroy_listener(struct wl_resource *surface)
541 {
542    struct wl_listener *destroy_listener = NULL;
543    Eina_List *l;
544    struct wl_resource *surface_data;
545
546    if (!surface) return TIZEN_KEYROUTER_ERROR_NONE;
547
548    EINA_LIST_FOREACH(krt->grab_surface_list, l, surface_data)
549      {
550         if (surface_data)
551           {
552              if (surface_data == surface)
553                {
554                   return TIZEN_KEYROUTER_ERROR_NONE;
555                }
556           }
557      }
558
559    destroy_listener = E_NEW(struct wl_listener, 1);
560
561    if (!destroy_listener)
562      {
563         KLERR("Failed to allocate memory for wl_surface destroy listener !");
564         return TIZEN_KEYROUTER_ERROR_NO_SYSTEM_RESOURCES;
565      }
566
567    destroy_listener->notify = _e_keyrouter_wl_surface_cb_destroy;
568    wl_resource_add_destroy_listener(surface, destroy_listener);
569    krt->grab_surface_list = eina_list_append(krt->grab_surface_list, surface);
570
571    return TIZEN_KEYROUTER_ERROR_NONE;
572 }
573
574 #ifdef HAVE_CYNARA
575 static void
576 _e_keyrouter_wl_util_cynara_log(const char *func_name, int err)
577 {
578 #define CYNARA_BUFSIZE 128
579    char buf[CYNARA_BUFSIZE] = "\0";
580    int ret;
581
582    ret = cynara_strerror(err, buf, CYNARA_BUFSIZE);
583    if (ret != CYNARA_API_SUCCESS)
584      {
585         KLWRN("Failed to cynara_strerror: %d (error log about %s: %d)", ret, func_name, err);
586         return;
587      }
588    KLWRN("%s is failed: %s", func_name, buf);
589 }
590
591 Eina_Bool
592 e_keyrouter_wl_util_do_privilege_check(struct wl_client *client, uint32_t mode, uint32_t keycode)
593 {
594    int ret, retry_cnt=0;
595    Eina_Bool res = EINA_FALSE;
596    Eina_List *l;
597    struct wl_client *wc_data;
598    static Eina_Bool retried = EINA_FALSE;
599    pid_t pid = 0;
600    uid_t uid = 0;
601    gid_t gid = 0;
602
603    /* Top position grab is always allowed. This mode do not need privilege.*/
604    if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
605      return EINA_TRUE;
606
607    if (krt->HardKeys[keycode].no_privcheck == EINA_TRUE &&
608        mode == TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE)
609      return EINA_TRUE;
610
611    if (!client) return EINA_FALSE;
612
613    /* If initialize cynara is failed, allow keygrabs regardless of the privilege permission. */
614    if (krt->p_cynara == NULL)
615      {
616         if (retried == EINA_FALSE)
617           {
618              retried = EINA_TRUE;
619              for(retry_cnt = 0; retry_cnt < 5; retry_cnt++)
620                {
621                   KLDBG("Retry cynara initialize: %d", retry_cnt+1);
622                   ret = cynara_initialize(&krt->p_cynara, NULL);
623                   if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
624                     {
625                       _e_keyrouter_wl_util_cynara_log("cynara_initialize", ret);
626                        krt->p_cynara = NULL;
627                     }
628                   else
629                     {
630                        KLDBG("Success cynara initialize to try %d times", retry_cnt+1);
631                        break;
632                     }
633                }
634           }
635         return EINA_TRUE;
636      }
637
638    EINA_LIST_FOREACH(krt->grab_client_list, l, wc_data)
639      {
640         if (wc_data == client)
641           {
642              res = EINA_TRUE;
643              goto finish;
644           }
645      }
646
647    wl_client_get_credentials(client, &pid, &uid, &gid);
648
649    res = e_security_privilege_check(pid, uid, "http://tizen.org/privilege/keygrab");
650    if (!res)
651      {
652         KLINF("Fail to check cynara,  (pid : %d)", pid);
653      }
654
655 finish:
656    return res;
657 }
658 #endif
659
660 Eina_Bool
661 e_keyrouter_wl_init(void)
662 {
663    int ret;
664
665    EINA_SAFETY_ON_NULL_RETURN_VAL(krt, EINA_FALSE);
666    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
667
668    krt->global = wl_global_create(e_comp_wl->wl.disp, &tizen_keyrouter_interface, 2, krt, _e_keyrouter_cb_bind);
669    EINA_SAFETY_ON_NULL_RETURN_VAL(krt->global, EINA_FALSE);
670
671 #ifdef HAVE_CYNARA
672    ret = cynara_initialize(&krt->p_cynara, NULL);
673    if (EINA_UNLIKELY(CYNARA_API_SUCCESS != ret))
674      {
675         _e_keyrouter_wl_util_cynara_log("cynara_initialize", ret);
676         krt->p_cynara = NULL;
677      }
678 #endif
679
680    return EINA_TRUE;
681 }
682
683 void
684 e_keyrouter_wl_shutdown(void)
685 {
686    Eina_List *l, *l_next;
687    struct wl_resource *resource;
688    struct wl_client *client;
689    struct wl_listener *destroy_listener;
690
691    EINA_SAFETY_ON_NULL_RETURN(krt);
692
693    EINA_LIST_FOREACH_SAFE(krt->grab_client_list, l, l_next, client)
694      {
695         destroy_listener = wl_client_get_destroy_listener(client, _e_keyrouter_wl_client_cb_destroy);
696         if (destroy_listener)
697           {
698              wl_list_remove(&destroy_listener->link);
699              E_FREE(destroy_listener);
700           }
701         krt->grab_client_list = eina_list_remove(krt->grab_client_list, client);
702      }
703    EINA_LIST_FOREACH_SAFE(krt->grab_surface_list, l, l_next, resource)
704      {
705         destroy_listener = wl_resource_get_destroy_listener(resource, _e_keyrouter_wl_surface_cb_destroy);
706         if (destroy_listener)
707           {
708              wl_list_remove(&destroy_listener->link);
709              E_FREE(destroy_listener);
710           }
711         krt->grab_surface_list = eina_list_remove(krt->grab_surface_list, client);
712      }
713
714    EINA_LIST_FREE(krt->resources, resource)
715      wl_resource_destroy(resource);
716
717    if (krt->global) wl_global_destroy(krt->global);
718
719 #ifdef HAVE_CYNARA
720    if (krt->p_cynara) cynara_finish(krt->p_cynara);
721 #endif
722 }