keyrouter: Add missing assignment
[platform/core/uifw/libds-tizen.git] / src / keyrouter / keyrouter.c
1 #include <unistd.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <errno.h>
5 #include <assert.h>
6 #include <stdint.h>
7 #include <stdbool.h>
8
9 #include <libds/log.h>
10 #include "libds-tizen/keyrouter.h"
11
12 #include "util.h"
13 #include "keyrouter.h"
14
15 static void
16 keyrouter_bind(struct wl_client *client, void *data, uint32_t version,
17         uint32_t id);
18 static bool
19 keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client,
20         struct wl_client *client, uint32_t mode, uint32_t keycode);
21 static void
22 keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter);
23
24 static void
25 keyrouter_handle_display_destroy(struct wl_listener *listener, void *data)
26 {
27     struct ds_tizen_keyrouter *keyrouter;
28
29     keyrouter = wl_container_of(listener, keyrouter, display_destroy);
30
31     ds_inf("Global destroy: ds_tizen_keyrouter(%p)", keyrouter);
32
33     wl_signal_emit(&keyrouter->events.destroy, keyrouter);
34
35     if (keyrouter->security_initialized)
36         tizen_security_finish();
37
38     free(keyrouter->opts);
39
40     wl_list_remove(&keyrouter->display_destroy.link);
41
42     wl_global_destroy(keyrouter->global);
43
44     keyrouter_grab_destroy(keyrouter->keyrouter_grab);
45
46     free(keyrouter);
47 }
48
49 WL_EXPORT struct ds_tizen_keyrouter *
50 ds_tizen_keyrouter_create(struct wl_display *display)
51 {
52     struct ds_tizen_keyrouter *keyrouter;
53
54     keyrouter = calloc(1, sizeof *keyrouter);
55     if (!keyrouter) {
56         return NULL;
57     }
58
59     keyrouter->keyrouter_grab = keyrouter_grab_create();
60     if (keyrouter->keyrouter_grab == NULL) {
61         ds_err("Failed to create keyrouter.");
62         free(keyrouter);
63         return NULL;
64     }
65
66     keyrouter->global = wl_global_create(display, &tizen_keyrouter_interface,
67             2, keyrouter, keyrouter_bind);
68     if (!keyrouter->global) {
69         keyrouter_grab_destroy(keyrouter->keyrouter_grab);
70         free(keyrouter);
71         return NULL;
72     }
73
74     wl_list_init(&keyrouter->clients);
75
76     wl_signal_init(&keyrouter->events.destroy);
77
78     keyrouter->display_destroy.notify = keyrouter_handle_display_destroy;
79     wl_display_add_destroy_listener(display, &keyrouter->display_destroy);
80
81     keyrouter_options_set(keyrouter);
82
83     keyrouter->security_initialized = tizen_security_init();
84     if (!keyrouter->security_initialized) {
85         ds_inf("tizen_security_init() is not sucessful. "
86                 "keyrouter works without security.");
87     }
88
89     ds_inf("Global created: ds_tizen_keyrouter(%p)", keyrouter);
90
91     return keyrouter;
92 }
93
94 WL_EXPORT void
95 ds_tizen_keyrouter_add_destroy_listener(struct ds_tizen_keyrouter *keyrouter,
96         struct wl_listener *listener)
97 {
98     wl_signal_add(&keyrouter->events.destroy, listener);
99 }
100
101 static void
102 keyrouter_handle_keygrab_set(struct wl_client *client,
103         struct wl_resource *resource, struct wl_resource *surface,
104         uint32_t key, uint32_t mode)
105 {
106     struct ds_tizen_keyrouter_client *keyrouter_client;
107     struct ds_tizen_keyrouter *keyrouter;
108     int res = TIZEN_KEYROUTER_ERROR_NONE;
109     bool ret;
110
111     keyrouter_client = wl_resource_get_user_data(resource);
112     keyrouter = keyrouter_client->keyrouter;
113
114     ret = keyrouter_check_privilege(keyrouter_client, client, mode, key);
115     if (ret == false) {
116         tizen_keyrouter_send_keygrab_notify(resource, surface,
117             key, mode, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
118         return;
119     }
120
121     res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab,
122         mode, key, (void *)client);
123     if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true)
124         keyrouter_client->grabbed = true;
125
126     tizen_keyrouter_send_keygrab_notify(resource, surface, key, mode, res);
127 }
128
129 static void
130 keyrouter_handle_keygrab_unset(struct wl_client *client,
131         struct wl_resource *resource, struct wl_resource *surface,  uint32_t key)
132 {
133     struct ds_tizen_keyrouter_client *keyrouter_client;
134     struct ds_tizen_keyrouter *keyrouter;
135     int res = TIZEN_KEYROUTER_ERROR_NONE;
136     bool ret;
137
138     keyrouter_client = wl_resource_get_user_data(resource);
139     keyrouter = keyrouter_client->keyrouter;
140
141     /* ungrab TOP POSITION grab first, this grab mode is not check privilege */
142     keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
143         TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client);
144
145     ret = keyrouter_check_privilege(keyrouter_client,
146         client, TIZEN_KEYROUTER_MODE_NONE, key);
147     if (ret == false) {
148         tizen_keyrouter_send_keygrab_notify(resource, surface, key,
149             TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
150         return;
151     }
152
153     keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
154         TIZEN_KEYROUTER_MODE_EXCLUSIVE, key, (void *)client);
155     keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
156         TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, key, (void *)client);
157     keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
158         TIZEN_KEYROUTER_MODE_TOPMOST, key, (void *)client);
159     keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
160         TIZEN_KEYROUTER_MODE_SHARED, key, (void *)client);
161
162     tizen_keyrouter_send_keygrab_notify(resource, surface, key, TIZEN_KEYROUTER_MODE_NONE, res);
163 }
164
165 static void
166 keyrouter_handle_get_keygrab_status(struct wl_client *client,
167         struct wl_resource *resource, struct wl_resource *surface, uint32_t key)
168 {
169     tizen_keyrouter_send_keygrab_notify(resource, surface, key,
170             TIZEN_KEYROUTER_MODE_NONE, TIZEN_KEYROUTER_ERROR_NO_PERMISSION);
171 }
172
173 static int
174 keyrouter_get_array_length(const struct wl_array *array)
175 {
176     int *data = NULL;
177     int count = 0;
178
179     wl_array_for_each(data, array) {
180         count++;
181     }
182
183     return count;
184 }
185
186 static void
187 keyrouter_handle_keygrab_set_list(struct wl_client *client,
188         struct wl_resource *resource, struct wl_resource *surface, struct wl_array *grab_list)
189 {
190     struct ds_tizen_keyrouter_client *keyrouter_client;
191     struct ds_tizen_keyrouter *keyrouter;
192     struct wl_array *return_list;
193     struct ds_tizen_grab_data *grab_data = NULL;
194     int res = TIZEN_KEYROUTER_ERROR_NONE;
195     bool ret;
196
197     keyrouter_client = wl_resource_get_user_data(resource);
198     keyrouter = keyrouter_client->keyrouter;
199
200     if ((keyrouter_get_array_length(grab_list) % 3) != 0) {
201         ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
202         tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
203         return;
204     }
205
206     wl_array_for_each(grab_data, grab_list) {
207         ret = keyrouter_check_privilege(keyrouter_client, client, grab_data->mode, grab_data->key);
208         if (ret == false) {
209             grab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
210         } else {
211             res = keyrouter_grab_grab_key(keyrouter->keyrouter_grab,
212                 grab_data->mode, grab_data->key, (void *)client);
213             if (res == TIZEN_KEYROUTER_ERROR_NONE && keyrouter_client->grabbed != true)
214                 keyrouter_client->grabbed = true;
215
216             grab_data->err = res;
217         }
218     }
219
220     return_list = grab_list;
221
222     tizen_keyrouter_send_keygrab_notify_list(resource, surface, return_list);
223 }
224
225 static void
226 keyrouter_handle_keygrab_unset_list(struct wl_client *client,
227         struct wl_resource *resource, struct wl_resource *surface,
228         struct wl_array *ungrab_list)
229 {
230     struct ds_tizen_keyrouter_client *keyrouter_client;
231     struct ds_tizen_keyrouter *keyrouter;
232     struct wl_array *return_list = NULL;
233     struct ds_tizen_ungrab_data *ungrab_data = NULL;
234     bool ret;
235
236     keyrouter_client = wl_resource_get_user_data(resource);
237     keyrouter = keyrouter_client->keyrouter;
238
239     if ((keyrouter_get_array_length(ungrab_list) % 3) != 0) {
240         ds_err("Invalid keycode and grab mode pair. Check arguments in a list.");
241         tizen_keyrouter_send_keygrab_notify_list(resource, surface, NULL);
242         return;
243     }
244
245     wl_array_for_each(ungrab_data, ungrab_list) {
246         keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
247             TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client);
248
249         ret = keyrouter_check_privilege(keyrouter_client, client,
250             TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key);
251         if (!ret) {
252             ungrab_data->err = TIZEN_KEYROUTER_ERROR_NO_PERMISSION;
253         } else {
254             keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
255                 TIZEN_KEYROUTER_MODE_EXCLUSIVE, ungrab_data->key, (void *)client);
256
257             keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
258                 TIZEN_KEYROUTER_MODE_OVERRIDABLE_EXCLUSIVE, ungrab_data->key, (void *)client);
259
260             keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
261                 TIZEN_KEYROUTER_MODE_TOPMOST, ungrab_data->key, (void *)client);
262
263             keyrouter_grab_ungrab_key(keyrouter->keyrouter_grab,
264                 TIZEN_KEYROUTER_MODE_SHARED, ungrab_data->key, (void *)client);
265
266             ungrab_data->err = TIZEN_KEYROUTER_ERROR_NONE;
267         }
268     }
269
270     return_list = ungrab_list;
271
272     tizen_keyrouter_send_keygrab_notify_list(resource, surface, return_list);
273 }
274
275 static void
276 keyrouter_handle_get_keygrab_list(struct wl_client *client,
277         struct wl_resource *resource, struct wl_resource *surface)
278 {
279     tizen_keyrouter_send_getgrab_notify_list(resource, surface, NULL);
280 }
281
282 static void
283 keyrouter_handle_set_register_none_key(struct wl_client *client,
284         struct wl_resource *resource, struct wl_resource *surface,
285         uint32_t data)
286 {
287     tizen_keyrouter_send_set_register_none_key_notify(resource, NULL, 0);
288 }
289
290 static void
291 keyrouter_handle_get_keyregister_status(struct wl_client *client,
292         struct wl_resource *resource, uint32_t key)
293 {
294     tizen_keyrouter_send_keyregister_notify(resource, (int)false);
295 }
296
297 static void
298 keyrouter_handle_set_input_config(struct wl_client *client,
299         struct wl_resource *resource, struct wl_resource *surface,
300         uint32_t config_mode, uint32_t value)
301 {
302     tizen_keyrouter_send_set_input_config_notify(resource, (int)false);
303 }
304
305 static void
306 keyrouter_handle_destory(struct wl_client *client,
307         struct wl_resource *resource)
308 {
309     wl_resource_destroy(resource);
310 }
311
312 static const struct tizen_keyrouter_interface tizen_keyrouter_impl = {
313    keyrouter_handle_keygrab_set,
314    keyrouter_handle_keygrab_unset,
315    keyrouter_handle_get_keygrab_status,
316    keyrouter_handle_keygrab_set_list,
317    keyrouter_handle_keygrab_unset_list,
318    keyrouter_handle_get_keygrab_list,
319    keyrouter_handle_set_register_none_key,
320    keyrouter_handle_get_keyregister_status,
321    keyrouter_handle_set_input_config,
322    keyrouter_handle_destory
323 };
324
325 static void
326 keyrouter_handle_resource_destory(struct wl_resource *resource)
327 {
328     struct ds_tizen_keyrouter_client *keyrouter_client = wl_resource_get_user_data(resource);
329
330     wl_list_remove(&keyrouter_client->link);
331     free(keyrouter_client);
332 }
333
334 static void
335 keyrouter_bind(struct wl_client *client, void *data, uint32_t version,
336         uint32_t id)
337 {
338     struct ds_tizen_keyrouter *keyrouter = data;
339     struct ds_tizen_keyrouter_client *keyrouter_client;
340
341     keyrouter_client = calloc(1, sizeof *keyrouter_client);
342     if (keyrouter_client == NULL) {
343         wl_client_post_no_memory(client);
344         return;
345     }
346
347     keyrouter_client->keyrouter = keyrouter;
348     keyrouter_client->resource =
349         wl_resource_create(client, &tizen_keyrouter_interface, MIN(version, 2), id);
350     if (keyrouter_client->resource == NULL) {
351         ds_err("wl_resource_create() failed.(version :%d, id:%d)", version, id);
352         free(keyrouter_client);
353         wl_client_post_no_memory(client);
354         return;
355     }
356
357     wl_resource_set_implementation(keyrouter_client->resource, &tizen_keyrouter_impl,
358         keyrouter_client, keyrouter_handle_resource_destory);
359
360     wl_list_insert(&keyrouter->clients, &keyrouter_client->link);
361 }
362
363 static bool
364 keyrouter_check_privilege(struct ds_tizen_keyrouter_client *keyrouter_client,
365         struct wl_client *client, uint32_t mode, uint32_t keycode)
366 {
367     struct ds_tizen_keyrouter *keyrouter = keyrouter_client->keyrouter;
368
369     pid_t pid = 0;
370     uid_t uid = 0;
371     gid_t gid = 0;
372
373     /* Top position grab is always allowed. This mode do not need privilege.*/
374     if (mode == TIZEN_KEYROUTER_MODE_TOPMOST)
375         return true;
376
377     // check no privilege option on the keycode
378     if (keyrouter->opts) {
379         if (keyrouter->opts[keycode].no_privilege)
380             return true;
381     }
382
383     // grabbed client is already checked the privilege before.
384     if (keyrouter_client->grabbed)
385         return true;
386
387     wl_client_get_credentials(client, &pid, &uid, &gid);
388
389     return tizen_security_check_privilege(pid, uid, "http://tizen.org/privilege/keygrab");
390 }
391
392 static void
393 keyrouter_options_set(struct ds_tizen_keyrouter *keyrouter)
394 {
395     FILE *file;
396     int keycode;
397     char *ret, *tmp, *buf_ptr, buf[1024] = {0,};
398
399     keyrouter->opts = calloc(KEYROUTER_MAX_KEYS,
400         sizeof(struct ds_tizen_keyrouter_key_options));
401     if (!keyrouter->opts) {
402         return;
403     }
404
405     file = fopen(KEYLAYOUT_DIR, "r");
406     if (!file) {
407         ds_err("Failed to open key layout file(%s): (err msg: %m)\n", KEYLAYOUT_DIR);
408         free(keyrouter->opts);
409         keyrouter->opts = NULL;
410         return;
411     }
412
413     while (!feof(file)) {
414         ret = fgets(buf, 1024, file);
415         if (!ret) continue;
416
417         tmp = strtok_r(buf, " ", &buf_ptr);
418         tmp = strtok_r(NULL, " ", &buf_ptr);
419         if (!tmp) continue;
420         keycode = atoi(tmp);
421         if ((0 >= keycode) || (keycode >= KEYROUTER_MAX_KEYS)) {
422             ds_err("Currently %d key is invalid to support\n", keycode);
423             continue;
424         }
425
426         keyrouter->opts[keycode].enabled = true;
427
428         if (strstr(buf_ptr, "no_priv") != NULL) {
429             keyrouter->opts[keycode].no_privilege = true;
430         }
431     }
432
433     fclose(file);
434 }