Fix potential memory leak issue when setting invocation name several times
[platform/core/uifw/voice-control.git] / client / vc_client.c
1 /*
2 * Copyright (c) 2011-2015 Samsung Electronics Co., Ltd All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17
18 #include "vc_client.h"
19
20 typedef struct {
21         /* base info */
22         vc_h    vc;
23         int     pid;
24         int     uid;            /*<< unique id = pid + handle */
25         int     xid;            /*<< main X window id */
26
27         vc_result_cb                    result_cb;
28         void*                           result_user_data;
29         vc_error_cb                     error_cb;
30         void*                           error_user_data;
31         vc_service_state_changed_cb     service_state_changed_cb;
32         void*                           service_state_changed_user_data;
33         vc_state_changed_cb             state_changed_cb;
34         void*                           state_changed_user_data;
35         vc_current_language_changed_cb  current_lang_changed_cb;
36         void*                           current_lang_changed_user_data;
37
38 #if 0
39         /* exclusive option */
40         bool                    exclusive_cmd;
41 #endif
42
43         /* service state */
44         vc_service_state_e      service_state;
45
46         /* state */
47         vc_state_e      before_state;
48         vc_state_e      current_state;
49
50         /* mutex */
51         int     cb_ref_count;
52
53         /* error data */
54         int     reason;
55
56         /* Authority */
57         vc_auth_state_e         auth_before_state;
58         vc_auth_state_e         auth_current_state;
59         vc_auth_state_changed_cb        auth_state_changed_cb;
60         void*                           auth_state_changed_user_data;
61
62         int     mgr_pid;
63
64         /* is foreground */
65         bool    is_foreground;
66
67         /* Invocation name */
68         char*   invocation_name;
69 } vc_client_s;
70
71 /* client list */
72 static GSList *g_client_list = NULL;
73
74
75 static vc_client_s* __client_get(vc_h vc)
76 {
77         if (vc == NULL) {
78                 return NULL;
79         }
80
81         vc_client_s *data = NULL;
82
83         int count = g_slist_length(g_client_list);
84         int i;
85
86         for (i = 0; i < count; i++) {
87                 data = g_slist_nth_data(g_client_list, i);
88
89                 if (NULL != data) {
90                         if (vc->handle == data->vc->handle) {
91                                 return data;
92                         }
93                 }
94         }
95
96         SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] Fail to get client by vc");
97
98         return NULL;
99 }
100
101 int vc_client_create(vc_h* vc)
102 {
103         vc_client_s *client = NULL;
104
105         client = (vc_client_s*)calloc(1, sizeof(vc_client_s));
106         if (NULL == client) {
107                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to allocate memory");
108                 return VC_ERROR_OUT_OF_MEMORY;
109         }
110
111         vc_h temp = (vc_h)calloc(1, sizeof(struct vc_s));
112         if (NULL == temp) {
113                 SLOG(LOG_ERROR, TAG_VCC, "[ERROR] Fail to allocate memory");
114                 free(client);
115                 return VC_ERROR_OUT_OF_MEMORY;
116         }
117
118         temp->handle = getpid();
119
120         /* initialize client data */
121         client->vc = temp;
122         client->pid = getpid();
123         client->uid = temp->handle;
124         client->xid = -1;
125
126         client->result_cb = NULL;
127         client->result_user_data = NULL;
128         client->service_state_changed_cb = NULL;
129         client->service_state_changed_user_data = NULL;
130         client->state_changed_cb = NULL;
131         client->state_changed_user_data = NULL;
132         client->current_lang_changed_cb = NULL;
133         client->current_lang_changed_user_data = NULL;
134         client->error_cb = NULL;
135         client->error_user_data = NULL;
136
137 #if 0
138         client->exclusive_cmd = false;
139 #endif
140
141         client->service_state = VC_RUNTIME_INFO_NO_FOREGROUND;
142
143         client->before_state = VC_STATE_INITIALIZED;
144         client->current_state = VC_STATE_INITIALIZED;
145
146         client->cb_ref_count = 0;
147
148         /* Authority */
149         client->auth_before_state = VC_AUTH_STATE_NONE;
150         client->auth_current_state = VC_AUTH_STATE_NONE;
151         client->auth_state_changed_cb = NULL;
152         client->auth_state_changed_user_data = NULL;
153
154         client->is_foreground = false;
155         client->invocation_name = NULL;
156
157         g_client_list = g_slist_append(g_client_list, client);
158
159         *vc = temp;
160
161         return 0;
162 }
163
164 int vc_client_destroy(vc_h vc)
165 {
166         if (vc == NULL) {
167                 SLOG(LOG_ERROR, TAG_VCC, "Input parameter is NULL");
168                 return 0;
169         }
170
171         vc_client_s *data = NULL;
172
173         int count = g_slist_length(g_client_list);
174         int i;
175
176         for (i = 0; i < count; i++) {
177                 data = g_slist_nth_data(g_client_list, i);
178
179                 if (NULL != data) {
180                         if (vc->handle == data->vc->handle) {
181                                 g_client_list =  g_slist_remove(g_client_list, data);
182
183                                 while (0 != data->cb_ref_count) {
184                                         /* wait for release callback function */
185                                 }
186                                 if (NULL != data->invocation_name) {
187                                         free(data->invocation_name);
188                                         data->invocation_name = NULL;
189                                 }
190                                 free(data);
191                                 free(vc);
192                                 data = NULL;
193                                 vc = NULL;
194                                 return 0;
195                         }
196                 }
197         }
198
199         SLOG(LOG_ERROR, TAG_VCC, "[ERROR] client Not found");
200
201         return -1;
202 }
203
204 bool vc_client_is_valid(vc_h vc)
205 {
206         vc_client_s* client = __client_get(vc);
207
208         /* check handle */
209         if (NULL == client) {
210                 SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] vc is not valid");
211                 return false;
212         }
213
214         return true;
215 }
216
217 bool vc_client_is_valid_by_uid(int uid)
218 {
219         vc_client_s *data = NULL;
220
221         int count = g_slist_length(g_client_list);
222         int i;
223
224         for (i = 0; i < count; i++) {
225                 data = g_slist_nth_data(g_client_list, i);
226
227                 if (NULL != data) {
228                         if (uid == data->vc->handle)
229                                 return true;
230                 }
231         }
232
233         SLOG(LOG_DEBUG, TAG_VCC, "[DEBUG] Fail to get client by vc");
234
235         return false;
236 }
237
238 int vc_client_get_handle(int uid, vc_h* vc)
239 {
240         vc_client_s *data = NULL;
241
242         int count = g_slist_length(g_client_list);
243         int i;
244
245         for (i = 0; i < count; i++) {
246                 data = g_slist_nth_data(g_client_list, i);
247
248                 if (NULL != data) {
249                         if (uid == data->vc->handle) {
250                                 *vc = data->vc;
251                                 return 0;
252                         }
253                 }
254         }
255
256         return -1;
257 }
258
259 /* set/get callback function */
260 int vc_client_set_result_cb(vc_h vc, vc_result_cb callback, void* user_data)
261 {
262         vc_client_s* client = __client_get(vc);
263
264         /* check handle */
265         if (NULL == client)
266                 return VC_ERROR_INVALID_PARAMETER;
267
268         client->result_cb = callback;
269         client->result_user_data = user_data;
270
271         return 0;
272 }
273
274 int vc_client_get_result_cb(vc_h vc, vc_result_cb* callback, void** user_data)
275 {
276         vc_client_s* client = __client_get(vc);
277
278         /* check handle */
279         if (NULL == client)
280                 return VC_ERROR_INVALID_PARAMETER;
281
282         *callback = client->result_cb;
283         *user_data = client->result_user_data;
284
285         return 0;
286 }
287
288 int vc_client_set_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb callback, void* user_data)
289 {
290         vc_client_s* client = __client_get(vc);
291
292         /* check handle */
293         if (NULL == client)
294                 return VC_ERROR_INVALID_PARAMETER;
295
296         client->service_state_changed_cb = callback;
297         client->service_state_changed_user_data = user_data;
298
299         return 0;
300 }
301
302 int vc_client_get_service_state_changed_cb(vc_h vc, vc_service_state_changed_cb* callback, void** user_data)
303 {
304         vc_client_s* client = __client_get(vc);
305
306         /* check handle */
307         if (NULL == client)
308                 return VC_ERROR_INVALID_PARAMETER;
309
310         *callback = client->service_state_changed_cb;
311         *user_data = client->service_state_changed_user_data;
312
313         return 0;
314 }
315
316 int vc_client_set_state_changed_cb(vc_h vc, vc_state_changed_cb callback, void* user_data)
317 {
318         vc_client_s* client = __client_get(vc);
319
320         /* check handle */
321         if (NULL == client)
322                 return VC_ERROR_INVALID_PARAMETER;
323
324         client->state_changed_cb = callback;
325         client->state_changed_user_data = user_data;
326
327         return 0;
328 }
329
330 int vc_client_get_state_changed_cb(vc_h vc, vc_state_changed_cb* callback, void** user_data)
331 {
332         vc_client_s* client = __client_get(vc);
333
334         /* check handle */
335         if (NULL == client)
336                 return VC_ERROR_INVALID_PARAMETER;
337
338         *callback = client->state_changed_cb;
339         *user_data = client->state_changed_user_data;
340
341         return 0;
342 }
343
344 int vc_client_set_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb callback, void* user_data)
345 {
346         vc_client_s* client = __client_get(vc);
347
348         /* check handle */
349         if (NULL == client)
350                 return VC_ERROR_INVALID_PARAMETER;
351
352         client->current_lang_changed_cb = callback;
353         client->current_lang_changed_user_data = user_data;
354
355         return 0;
356 }
357
358 int vc_client_get_current_lang_changed_cb(vc_h vc, vc_current_language_changed_cb* callback, void** user_data)
359 {
360         vc_client_s* client = __client_get(vc);
361
362         /* check handle */
363         if (NULL == client)
364                 return VC_ERROR_INVALID_PARAMETER;
365
366         *callback = client->current_lang_changed_cb;
367         *user_data = client->current_lang_changed_user_data;
368
369         return 0;
370 }
371
372 int vc_client_set_error_cb(vc_h vc, vc_error_cb callback, void* user_data)
373 {
374         vc_client_s* client = __client_get(vc);
375
376         /* check handle */
377         if (NULL == client)
378                 return VC_ERROR_INVALID_PARAMETER;
379
380         client->error_cb = callback;
381         client->error_user_data = user_data;
382
383         return 0;
384 }
385
386 int vc_client_get_error_cb(vc_h vc, vc_error_cb* callback, void** user_data)
387 {
388         vc_client_s* client = __client_get(vc);
389
390         /* check handle */
391         if (NULL == client)
392                 return VC_ERROR_INVALID_PARAMETER;
393
394         *callback = client->error_cb;
395         *user_data = client->error_user_data;
396
397         return 0;
398 }
399
400 /* set/get option */
401 int vc_client_set_service_state(vc_h vc, vc_service_state_e state)
402 {
403         vc_client_s* client = __client_get(vc);
404
405         /* check handle */
406         if (NULL == client)
407                 return VC_ERROR_INVALID_PARAMETER;
408
409         client->service_state = state;
410
411         return 0;
412 }
413
414 int vc_client_get_service_state(vc_h vc, vc_service_state_e* state)
415 {
416         vc_client_s* client = __client_get(vc);
417
418         /* check handle */
419         if (NULL == client)
420                 return VC_ERROR_INVALID_PARAMETER;
421
422         *state = client->service_state;
423
424         return 0;
425 }
426
427 int vc_client_set_client_state(vc_h vc, vc_state_e state)
428 {
429         vc_client_s* client = __client_get(vc);
430
431         /* check handle */
432         if (NULL == client)
433                 return VC_ERROR_INVALID_PARAMETER;
434
435         client->before_state = client->current_state;
436         client->current_state = state;
437
438         return 0;
439 }
440
441 int vc_client_get_client_state(vc_h vc, vc_state_e* state)
442 {
443         vc_client_s* client = __client_get(vc);
444
445         /* check handle */
446         if (NULL == client)
447                 return VC_ERROR_INVALID_PARAMETER;
448
449         *state = client->current_state;
450
451         return 0;
452 }
453
454 int vc_client_get_client_state_by_uid(int uid, vc_state_e* state)
455 {
456         vc_client_s *data = NULL;
457
458         int count = g_slist_length(g_client_list);
459         int i;
460
461         for (i = 0; i < count; i++) {
462                 data = g_slist_nth_data(g_client_list, i);
463
464                 if (NULL != data) {
465                         if (uid == data->vc->handle) {
466                                 *state = data->current_state;
467                                 return 0;
468                         }
469                 }
470         }
471
472         return -1;
473 }
474
475 int vc_client_get_before_state(vc_h vc, vc_state_e* state, vc_state_e* before_state)
476 {
477         vc_client_s* client = __client_get(vc);
478
479         /* check handle */
480         if (NULL == client)
481                 return VC_ERROR_INVALID_PARAMETER;
482
483         *before_state = client->before_state;
484         *state = client->current_state;
485
486         return 0;
487 }
488
489 int vc_client_set_invocation_name(vc_h vc, const char* invocation_name)
490 {
491         vc_client_s* client = __client_get(vc);
492
493         /* check handle */
494         if (NULL == client)
495                 return VC_ERROR_INVALID_PARAMETER;
496
497         if (NULL != client->invocation_name)
498                 free(client->invocation_name);
499
500         client->invocation_name = NULL;
501
502         if (NULL != invocation_name) {
503                 client->invocation_name = strdup(invocation_name);
504         }
505         return 0;
506 }
507
508 int vc_client_get_invocation_name(vc_h vc, char** invocation_name)
509 {
510         vc_client_s* client = __client_get(vc);
511
512         /* check handle */
513         if (NULL == client)
514                 return VC_ERROR_INVALID_PARAMETER;
515
516         if (NULL != client->invocation_name)
517                 *invocation_name = strdup(client->invocation_name);
518         return 0;
519 }
520
521 int vc_client_set_xid(vc_h vc, int xid)
522 {
523         vc_client_s* client = __client_get(vc);
524
525         /* check handle */
526         if (NULL == client)
527                 return VC_ERROR_INVALID_PARAMETER;
528
529         client->xid = xid;
530
531         return 0;
532 }
533
534 int vc_client_get_xid(vc_h vc, int* xid)
535 {
536         vc_client_s* client = __client_get(vc);
537
538         /* check handle */
539         if (NULL == client)
540                 return VC_ERROR_INVALID_PARAMETER;
541
542         *xid = client->xid;
543
544         return 0;
545 }
546
547 int vc_client_set_is_foreground(vc_h vc, bool value)
548 {
549         vc_client_s* client = __client_get(vc);
550
551         /* check handle */
552         if (NULL == client)
553                 return VC_ERROR_INVALID_PARAMETER;
554
555         client->is_foreground = value;
556         return 0;
557 }
558
559 int vc_client_get_is_foreground(vc_h vc, bool* value)
560 {
561         vc_client_s* client = __client_get(vc);
562
563         /* check handle */
564         if (NULL == client)
565                 return VC_ERROR_INVALID_PARAMETER;
566
567         *value = client->is_foreground;
568
569         return 0;
570 }
571
572 #if 0
573 int vc_client_set_exclusive_cmd(vc_h vc, bool value)
574 {
575         vc_client_s* client = __client_get(vc);
576
577         /* check handle */
578         if (NULL == client)
579                 return VC_ERROR_INVALID_PARAMETER;
580
581         client->exclusive_cmd = value;
582
583         return 0;
584 }
585
586 int vc_client_get_exclusive_cmd(vc_h vc, bool* value)
587 {
588         vc_client_s* client = __client_get(vc);
589
590         /* check handle */
591         if (NULL == client)
592                 return VC_ERROR_INVALID_PARAMETER;
593
594         *value = client->exclusive_cmd;
595
596         return 0;
597 }
598 #endif
599
600 int vc_client_set_error(vc_h vc, int reason)
601 {
602         vc_client_s* client = __client_get(vc);
603
604         /* check handle */
605         if (NULL == client)
606                 return VC_ERROR_INVALID_PARAMETER;
607
608         client->reason = reason;
609
610         return 0;
611 }
612
613 int vc_client_get_error(vc_h vc, int* reason)
614 {
615         vc_client_s* client = __client_get(vc);
616
617         /* check handle */
618         if (NULL == client)
619                 return VC_ERROR_INVALID_PARAMETER;
620
621         *reason = client->reason;
622
623         return 0;
624 }
625
626
627 /* utils */
628 int vc_client_get_count()
629 {
630         return g_slist_length(g_client_list);
631 }
632
633 int vc_client_use_callback(vc_h vc)
634 {
635         vc_client_s* client = __client_get(vc);
636
637         /* check handle */
638         if (NULL == client)
639                 return VC_ERROR_INVALID_PARAMETER;
640
641         client->cb_ref_count++;
642         return 0;
643 }
644
645 int vc_client_not_use_callback(vc_h vc)
646 {
647         vc_client_s* client = __client_get(vc);
648
649         /* check handle */
650         if (NULL == client)
651                 return VC_ERROR_INVALID_PARAMETER;
652
653         client->cb_ref_count--;
654         return 0;
655 }
656
657 /* Authority */
658 int vc_client_set_auth_state_changed_cb(vc_h vc, vc_auth_state_changed_cb callback, void* user_data)
659 {
660         vc_client_s* client = __client_get(vc);
661
662         /* check handle */
663         if (NULL == client)
664                 return VC_ERROR_INVALID_PARAMETER;
665
666         client->auth_state_changed_cb = callback;
667         client->auth_state_changed_user_data = user_data;
668
669         return 0;
670 }
671
672 int vc_client_get_auth_state_changed_cb(vc_h vc, vc_auth_state_changed_cb* callback, void** user_data)
673 {
674         vc_client_s* client = __client_get(vc);
675
676         /* check handle */
677         if (NULL == client)
678                 return VC_ERROR_INVALID_PARAMETER;
679
680         *callback = client->auth_state_changed_cb;
681         *user_data = client->auth_state_changed_user_data;
682
683         return 0;
684 }
685
686 int vc_client_unset_auth_state_changed_cb(vc_h vc)
687 {
688         vc_client_s* client = __client_get(vc);
689
690         /* check handle */
691         if (NULL == client)
692                 return VC_ERROR_INVALID_PARAMETER;
693
694         client->auth_state_changed_cb = NULL;
695         client->auth_state_changed_user_data = NULL;
696
697         return 0;
698 }
699
700 int vc_client_set_auth_state(vc_h vc, vc_auth_state_e state)
701 {
702         vc_client_s* client = __client_get(vc);
703
704         /* check handle */
705         if (NULL == client)
706                 return VC_ERROR_INVALID_PARAMETER;
707
708         client->auth_before_state = client->auth_current_state;
709         client->auth_current_state = state;
710
711         return 0;
712 }
713
714 int vc_client_get_auth_state(vc_h vc, vc_auth_state_e* state)
715 {
716         vc_client_s* client = __client_get(vc);
717
718         /* check handle */
719         if (NULL == client)
720                 return VC_ERROR_INVALID_PARAMETER;
721
722         *state = client->auth_current_state;
723
724         return 0;
725 }
726
727 int vc_client_get_before_auth_state(vc_h vc, vc_auth_state_e* before, vc_auth_state_e* current)
728 {
729         vc_client_s* client = __client_get(vc);
730
731         /* check handle */
732         if (NULL == client)
733                 return VC_ERROR_INVALID_PARAMETER;
734
735         *before = client->auth_before_state;
736         *current = client->auth_current_state;
737
738         return 0;
739 }
740
741 int vc_client_set_mgr_pid(vc_h vc, int mgr_pid)
742 {
743         vc_client_s* client = __client_get(vc);
744
745         /* check handle */
746         if (NULL == client)
747                 return VC_ERROR_INVALID_PARAMETER;
748
749         client->mgr_pid = mgr_pid;
750
751         return 0;
752 }
753
754 int vc_client_get_mgr_pid(vc_h vc, int* mgr_pid)
755 {
756         vc_client_s* client = __client_get(vc);
757
758         /* check handle */
759         if (NULL == client)
760                 return VC_ERROR_INVALID_PARAMETER;
761
762         *mgr_pid = client->mgr_pid;
763
764         return 0;
765 }