Add logs for analyzing issues
[platform/core/uifw/autofill-daemon.git] / src / autofill-daemon.c
1 /*
2  * Copyright (c) 2018 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 #include <tizen.h>
18 #include <stdlib.h>
19 #include <service_app.h>
20 #include <dlog.h>
21 #include <glib.h>
22 #include <rpc-port.h>
23 #include <app_manager.h>
24 #include <Ecore.h>
25
26 #include "autofill_daemon_dlog.h"
27 #include "autofill_stub.h"
28 #include "autofill_service_proxy.h"
29 #include "autofill_manager_stub.h"
30 #include "autofill_config.h"
31
32 #define RECONNECT_PERIOD 1.0
33
34 static rpc_port_proxy_AutofillSvcPort_h svc_rpc_h = NULL;
35 static rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_h fill_response_received_cb_h = NULL;
36 static rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_h auth_info_cb_h = NULL;
37 static rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_h error_info_cb_h = NULL;
38
39 typedef struct {
40     char *app_id;
41     int context_id;
42
43     rpc_port_AutofillAppPort_autofill_auth_info_received_cb_h auth_info_cb;
44     rpc_port_AutofillAppPort_autofill_fill_response_received_cb_h fill_response_received_cb;
45     rpc_port_AutofillAppPort_autofill_error_info_received_cb_h error_info_cb;
46 } autofill_client_s;
47
48 static GList *__client_list = NULL;
49 static Ecore_Timer *g_connect_timer = NULL;
50 static bool g_connected = false;
51
52 static bool connect_service();
53 static void terminate_autofill_service();
54
55 static autofill_client_s *
56 get_autofill_client(const char *app_id, int context_id)
57 {
58     GList *iter;
59     autofill_client_s *client;
60
61     iter = __client_list;
62     while (iter) {
63         client = iter->data;
64
65         iter = g_list_next(iter);
66
67         if (!client) {
68             LOGW("Warning: value is NULL");
69             continue;
70         }
71
72         if ((client->context_id == context_id) &&
73             client->app_id && strcmp(client->app_id, app_id) == 0) {
74             return client;
75         }
76     }
77
78     return NULL;
79 }
80
81 static autofill_client_s *__create_client(const char *app_id, int context_id,
82         rpc_port_AutofillAppPort_autofill_auth_info_received_cb_h auth_info_cb,
83         rpc_port_AutofillAppPort_autofill_fill_response_received_cb_h fill_response_received_cb,
84         rpc_port_AutofillAppPort_autofill_error_info_received_cb_h error_info_cb)
85 {
86     LOGD("");
87     autofill_client_s *handle;
88
89     handle = calloc(1, sizeof(autofill_client_s));
90     if (!handle) {
91         LOGE("Out of memory");
92         return NULL;
93     }
94
95     handle->app_id = strdup(app_id);
96     if (!handle->app_id) {
97         LOGE("Out of memory");
98         free(handle);
99         return NULL;
100     }
101
102     handle->context_id = context_id;
103
104     rpc_port_AutofillAppPort_autofill_auth_info_received_cb_clone(auth_info_cb, &handle->auth_info_cb);
105     if (!handle->auth_info_cb) {
106         LOGE("Out of memory");
107         free(handle->app_id);
108         free(handle);
109         return NULL;
110     }
111
112     rpc_port_AutofillAppPort_autofill_fill_response_received_cb_clone(fill_response_received_cb, &handle->fill_response_received_cb);
113
114     if (!handle->fill_response_received_cb) {
115         LOGE("Out of memory");
116         free(handle->app_id);
117         rpc_port_AutofillAppPort_autofill_auth_info_received_cb_destroy(handle->auth_info_cb);
118         free(handle);
119         return NULL;
120     }
121
122     rpc_port_AutofillAppPort_autofill_error_info_received_cb_clone(error_info_cb, &handle->error_info_cb);
123     if (!handle->error_info_cb) {
124         LOGE("Out of memory");
125         free(handle->app_id);
126         rpc_port_AutofillAppPort_autofill_auth_info_received_cb_destroy(handle->auth_info_cb);
127         rpc_port_AutofillAppPort_autofill_fill_response_received_cb_destroy(handle->fill_response_received_cb);
128         free(handle);
129         return NULL;
130     }
131
132     return handle;
133 }
134
135 static void __destroy_client(gpointer data)
136 {
137     LOGD("");
138     autofill_client_s *handle = data;
139
140     if (!handle)
141         return;
142
143     if (handle->auth_info_cb) {
144         rpc_port_AutofillAppPort_autofill_auth_info_received_cb_destroy(handle->auth_info_cb);
145         handle->auth_info_cb = NULL;
146     }
147
148     if (handle->fill_response_received_cb) {
149         rpc_port_AutofillAppPort_autofill_fill_response_received_cb_destroy(handle->fill_response_received_cb);
150         handle->fill_response_received_cb = NULL;
151     }
152
153     if (handle->error_info_cb) {
154         rpc_port_AutofillAppPort_autofill_error_info_received_cb_destroy(handle->error_info_cb);
155         handle->error_info_cb = NULL;
156     }
157
158     if (handle->app_id) {
159         free(handle->app_id);
160         handle->app_id = NULL;
161     }
162
163     free(handle);
164 }
165
166 static void __remove_client(rpc_port_stub_AutofillAppPort_context_h context)
167 {
168     autofill_client_s *client = NULL;
169     rpc_port_stub_AutofillAppPort_context_get_tag(context, (void *)&client);
170     if (!client)
171         return;
172
173     rpc_port_stub_AutofillAppPort_context_set_tag(context, NULL);
174
175     LOGI("name(%s)", client->app_id);
176
177     __client_list = g_list_remove(__client_list, client);
178     __destroy_client(client);
179
180     if (g_list_length(__client_list) == 0) {
181         terminate_autofill_service();
182
183         LOGI("terminate autofill daemon");
184         service_app_exit();
185     }
186 }
187
188 static void __client_create(rpc_port_stub_AutofillAppPort_context_h context,
189         void *user_data)
190 {
191     LOGD("context : %p", context);
192     char *sender = NULL;
193
194     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
195     if (!sender)
196         return;
197
198     LOGD("sender(%s)", sender);
199     free(sender);
200 }
201
202 static gboolean __client_remove_cb(void *data)
203 {
204     rpc_port_stub_AutofillAppPort_context_h context = data;
205
206     LOGD("client remove callback (%p)", context);
207
208     __remove_client(context);
209
210     return false;
211 }
212
213 static void __client_terminate(rpc_port_stub_AutofillAppPort_context_h context,
214         void *user_data)
215 {
216     LOGD("context : %p", context);
217     char *sender = NULL;
218
219     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
220     if (!sender)
221         return;
222
223     LOGD("[__RPC_PORT__] sender(%s)", sender);
224     free(sender);
225
226     g_idle_add(__client_remove_cb, context);
227 }
228
229 static int __client_register(rpc_port_stub_AutofillAppPort_context_h context,
230                               int context_id,
231                               rpc_port_AutofillAppPort_autofill_auth_info_received_cb_h auth_info_cb,
232                               rpc_port_AutofillAppPort_autofill_fill_response_received_cb_h fill_response_received_cb,
233                               rpc_port_AutofillAppPort_autofill_error_info_received_cb_h error_info_cb,
234                               void *user_data)
235 {
236     LOGD("context : %p", context);
237     char *sender = NULL;
238     autofill_client_s *client = NULL;
239
240     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
241     if (!sender)
242         return -1;
243
244     LOGD("sender(%s)", sender);
245
246     client = __create_client(sender, context_id, auth_info_cb, fill_response_received_cb, error_info_cb);
247     free(sender);
248
249     if (!client)
250         return -1;
251
252     __client_list = g_list_append(__client_list, client);
253
254     rpc_port_stub_AutofillAppPort_context_set_tag(context, client);
255
256     return 0;
257 }
258
259 static void __client_unregister(rpc_port_stub_AutofillAppPort_context_h context, int context_id, void *user_data)
260 {
261     LOGD("context : %p", context);
262     __remove_client(context);
263 }
264
265 static void __manager_create(rpc_port_stub_AutofillManagerPort_context_h context,
266         void *user_data)
267 {
268     LOGD("");
269 }
270
271 static void __manager_terminate(rpc_port_stub_AutofillManagerPort_context_h context,
272         void *user_data)
273 {
274     LOGD("");
275 }
276
277 bool __view_info_item_cb(rpc_port_autofill_item_h items, void *user_data)
278 {
279     char *id = NULL;
280     char *label = NULL;
281     char *value = NULL;
282     int autofill_hint;
283     bool sensitive_data;
284
285     rpc_port_autofill_svc_view_info_h svi = (rpc_port_autofill_svc_view_info_h)user_data;
286
287     rpc_port_autofill_svc_item_h svc_item = NULL;
288
289     if (rpc_port_autofill_svc_item_create(&svc_item) != 0) {
290         LOGW("Failed to create autofill item");
291         return true;
292     }
293
294     rpc_port_autofill_item_get_id(items, &id);
295     rpc_port_autofill_svc_item_set_id(svc_item, id);
296     if (id) {
297         free(id);
298     }
299
300     rpc_port_autofill_item_get_label(items, &label);
301     rpc_port_autofill_svc_item_set_label(svc_item, label);
302     if (label) {
303         free(label);
304     }
305
306     rpc_port_autofill_item_get_value(items, &value);
307     rpc_port_autofill_svc_item_set_value(svc_item, value);
308     if (value) {
309         free(value);
310     }
311
312     rpc_port_autofill_item_get_autofill_hint(items, &autofill_hint);
313     rpc_port_autofill_svc_item_set_autofill_hint(svc_item, autofill_hint);
314
315     rpc_port_autofill_item_get_is_sensitive_data(items, &sensitive_data);
316     rpc_port_autofill_svc_item_set_is_sensitive_data(svc_item, sensitive_data);
317
318     if (rpc_port_autofill_svc_view_info_add_items(svi, svc_item) != 0) {
319         LOGW("Failed to add item");
320     }
321
322     rpc_port_autofill_svc_item_destroy(svc_item);
323
324     return true;
325 }
326
327 bool __save_item_cb(rpc_port_autofill_save_item_h items, void *user_data)
328 {
329     char *id = NULL;
330     char *label = NULL;
331     char *value = NULL;
332     int autofill_hint;
333     bool sensitive_data;
334
335     rpc_port_autofill_svc_save_view_info_h svi = (rpc_port_autofill_svc_save_view_info_h)user_data;
336
337     rpc_port_autofill_svc_save_item_h svc_save_item = NULL;
338
339     if (rpc_port_autofill_svc_save_item_create(&svc_save_item) != 0)
340         return true;
341
342     rpc_port_autofill_save_item_get_id(items, &id);
343     rpc_port_autofill_svc_save_item_set_id(svc_save_item, id);
344     if (id) {
345         free(id);
346     }
347
348     rpc_port_autofill_save_item_get_label(items, &label);
349     rpc_port_autofill_svc_save_item_set_label(svc_save_item, label);
350     if (label) {
351         free(label);
352     }
353
354     rpc_port_autofill_save_item_get_value(items, &value);
355     rpc_port_autofill_svc_save_item_set_value(svc_save_item, value);
356     if (value) {
357         free(value);
358     }
359
360     rpc_port_autofill_save_item_get_autofill_hint(items, &autofill_hint);
361     rpc_port_autofill_svc_save_item_set_autofill_hint(svc_save_item, autofill_hint);
362
363     rpc_port_autofill_save_item_get_is_sensitive_data(items, &sensitive_data);
364     rpc_port_autofill_svc_save_item_set_is_sensitive_data(svc_save_item, sensitive_data);
365
366     rpc_port_autofill_svc_save_view_info_add_items(svi, svc_save_item);
367
368     rpc_port_autofill_svc_save_item_destroy(svc_save_item);
369
370     return true;
371 }
372
373 static int __auth_info_request_cb(rpc_port_stub_AutofillAppPort_context_h context, int context_id, rpc_port_autofill_view_info_h vi, void *user_data)
374 {
375     char *sender = NULL;
376     char *view_id = NULL;
377
378     if (!g_connected) {
379         LOGW("Not connected to autofill service");
380         return 0;
381     }
382
383     if (!svc_rpc_h) {
384         LOGW("RPC port for autofill service is not created");
385         return 0;
386     }
387
388     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
389
390     rpc_port_autofill_view_info_get_view_id(vi, &view_id);
391     LOGD("app id : %s, view id : %s", sender, view_id);
392
393     /* create view info */
394     rpc_port_autofill_svc_view_info_h svi = NULL;
395     if (rpc_port_autofill_svc_view_info_create(&svi) != 0) {
396         goto end;
397     }
398
399     rpc_port_autofill_svc_view_info_set_app_id(svi, sender);
400     rpc_port_autofill_svc_view_info_set_view_id(svi, view_id);
401
402     rpc_port_autofill_view_info_foreach_items(vi, __view_info_item_cb, svi);
403
404     rpc_port_proxy_AutofillSvcPort_invoke_request_auth_info(svc_rpc_h, context_id, svi);
405
406     rpc_port_autofill_svc_view_info_destroy(svi);
407
408 end:
409     if (sender) {
410         free(sender);
411     }
412
413     if (view_id) {
414         free(view_id);
415     }
416
417     return 0;
418 }
419
420 static int __autofill_fill_request_cb(rpc_port_stub_AutofillAppPort_context_h context, int context_id, rpc_port_autofill_view_info_h vi, void *user_data)
421 {
422     char *sender = NULL;
423     char *view_id = NULL;
424
425     if (!g_connected) {
426         LOGW("Not connected to autofill service");
427         return 0;
428     }
429
430     if (!svc_rpc_h) {
431         LOGW("RPC port for autofill service is not created");
432         return 0;
433     }
434
435     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
436     rpc_port_autofill_view_info_get_view_id(vi, &view_id);
437
438     LOGD("app id : %s, view id : %s, context id : %d", sender, view_id, context_id);
439
440     rpc_port_autofill_svc_view_info_h svi = NULL;
441     if (rpc_port_autofill_svc_view_info_create(&svi) != 0) {
442         goto end;
443     }
444
445     rpc_port_autofill_svc_view_info_set_app_id(svi, sender);
446     rpc_port_autofill_svc_view_info_set_view_id(svi, view_id);
447
448     rpc_port_autofill_view_info_foreach_items(vi, __view_info_item_cb, svi);
449
450     rpc_port_proxy_AutofillSvcPort_invoke_send_fill_request(svc_rpc_h, context_id, svi);
451
452     rpc_port_autofill_svc_view_info_destroy(svi);
453
454 end:
455     if (sender)
456         free(sender);
457
458     if (view_id)
459         free(view_id);
460
461     return 0;
462 }
463
464 static int __autofill_cancel_fill_request_cb(rpc_port_stub_AutofillAppPort_context_h context, int context_id, rpc_port_autofill_view_info_h vi, void *user_data)
465 {
466     char *sender = NULL;
467     char *view_id = NULL;
468
469     if (!g_connected) {
470         LOGW("Not connected to autofill service");
471         return 0;
472     }
473
474     if (!svc_rpc_h) {
475         LOGW("RPC port for autofill service is not created");
476         return 0;
477     }
478
479     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
480     rpc_port_autofill_view_info_get_view_id(vi, &view_id);
481
482     LOGD("app id : %s, view id : %s, context id : %d", sender, view_id, context_id);
483
484     rpc_port_autofill_svc_view_info_h svi = NULL;
485     if (rpc_port_autofill_svc_view_info_create(&svi) != 0) {
486         goto end;
487     }
488
489     rpc_port_autofill_svc_view_info_set_app_id(svi, sender);
490     rpc_port_autofill_svc_view_info_set_view_id(svi, view_id);
491
492     rpc_port_autofill_view_info_foreach_items(vi, __view_info_item_cb, svi);
493
494     rpc_port_proxy_AutofillSvcPort_invoke_cancel_fill_request(svc_rpc_h, context_id, svi);
495
496     rpc_port_autofill_svc_view_info_destroy(svi);
497
498 end:
499     if (sender)
500         free(sender);
501
502     if (view_id)
503         free(view_id);
504
505     return 0;
506 }
507
508 static int __commit_cb(rpc_port_stub_AutofillAppPort_context_h context, int context_id, rpc_port_autofill_save_view_info_h vi, void *user_data)
509 {
510     char *sender = NULL;
511     char *view_id = NULL;
512     char *view_title = NULL;
513
514     if (!g_connected) {
515         LOGW("Not connected to autofill service");
516         return 0;
517     }
518
519     if (!svc_rpc_h) {
520         LOGW("RPC port for autofill service is not created");
521         return 0;
522     }
523
524     rpc_port_autofill_svc_save_view_info_h svi = NULL;
525     if (rpc_port_autofill_svc_save_view_info_create(&svi) != 0) {
526         return 0;
527     }
528
529     rpc_port_stub_AutofillAppPort_context_get_sender(context, &sender);
530
531     if (sender) {
532         rpc_port_autofill_svc_save_view_info_set_app_id(svi, sender);
533         LOGD("sender(%s)", sender);
534         free(sender);
535     }
536
537     rpc_port_autofill_save_view_info_get_view_id(vi, &view_id);
538     rpc_port_autofill_save_view_info_get_view_title(vi, &view_title);
539
540     LOGI("view id : '%s', view title : '%s'", view_id, view_title);
541     rpc_port_autofill_svc_save_view_info_set_view_id(svi, view_id);
542     rpc_port_autofill_svc_save_view_info_set_view_title(svi, view_title);
543
544     rpc_port_autofill_save_view_info_foreach_items(vi, __save_item_cb, svi);
545
546     rpc_port_proxy_AutofillSvcPort_invoke_commit(svc_rpc_h, context_id, svi);
547
548     if (view_id)
549         free(view_id);
550
551     if (view_title)
552         free(view_title);
553
554     rpc_port_autofill_svc_save_view_info_destroy(svi);
555
556     return 0;
557 }
558
559 bool fill_response_item_cb(rpc_port_autofill_svc_response_item_h response_items, void *user_data)
560 {
561     rpc_port_autofill_response_group_h res_group = (rpc_port_autofill_response_group_h)user_data;
562
563     char *id = NULL;
564     char *presentation_text = NULL;
565     char *value = NULL;
566     int autofill_hint;
567
568     rpc_port_autofill_response_item_h res_item = NULL;
569
570     if (rpc_port_autofill_response_item_create(&res_item) != 0) {
571         return true;
572     }
573
574     rpc_port_autofill_svc_response_item_get_id(response_items, &id);
575     rpc_port_autofill_response_item_set_id(res_item, id);
576
577     rpc_port_autofill_svc_response_item_get_presentation_text(response_items, &presentation_text);
578     rpc_port_autofill_response_item_set_presentation_text(res_item, presentation_text);
579
580     rpc_port_autofill_svc_response_item_get_value(response_items, &value);
581     rpc_port_autofill_response_item_set_value(res_item, value);
582
583     rpc_port_autofill_svc_response_item_get_autofill_hint(response_items, &autofill_hint);
584     rpc_port_autofill_response_item_set_autofill_hint(res_item, autofill_hint);
585
586     rpc_port_autofill_response_group_add_response_items(res_group, res_item);
587
588     if (id)
589         free(id);
590
591     if (presentation_text)
592         free(presentation_text);
593
594     if (value)
595         free(value);
596
597     rpc_port_autofill_response_item_destroy(res_item);
598
599     return true;
600 }
601
602 bool fill_response_group_cb(rpc_port_autofill_svc_response_group_h response_groups, void *user_data)
603 {
604     rpc_port_autofill_fill_response_h fr_h = (rpc_port_autofill_fill_response_h)user_data;
605
606     rpc_port_autofill_response_group_h res_group = NULL;
607     if (rpc_port_autofill_response_group_create(&res_group) != 0)
608         return true;
609
610     rpc_port_autofill_svc_response_group_foreach_response_items(response_groups, fill_response_item_cb, res_group);
611
612     rpc_port_autofill_fill_response_add_response_groups(fr_h, res_group);
613
614     rpc_port_autofill_response_group_destroy(res_group);
615
616     return true;
617 }
618
619 static void __fill_response_recv_cb(void *user_data, int context_id, rpc_port_autofill_svc_fill_response_h response_h)
620 {
621     // recv fill response from service
622     char *view_id = NULL;
623     char *app_id = NULL;
624
625     /* create autofill response */
626     rpc_port_autofill_fill_response_h fill_response_h = NULL;
627     if (rpc_port_autofill_fill_response_create(&fill_response_h) != 0)
628         return;
629
630     rpc_port_autofill_svc_fill_response_get_app_id(response_h, &app_id);
631     rpc_port_autofill_svc_fill_response_get_view_id(response_h, &view_id);
632
633     rpc_port_autofill_fill_response_set_app_id(fill_response_h, app_id);
634     rpc_port_autofill_fill_response_set_view_id(fill_response_h, view_id);
635
636     rpc_port_autofill_svc_fill_response_foreach_response_groups(response_h, fill_response_group_cb, fill_response_h);
637
638     autofill_client_s *sender_client = get_autofill_client(app_id, context_id);
639     if (sender_client)
640         rpc_port_AutofillAppPort_autofill_fill_response_received_cb_invoke(sender_client->fill_response_received_cb, fill_response_h);
641
642     rpc_port_autofill_fill_response_destroy(fill_response_h);
643
644     if (app_id)
645         free(app_id);
646
647     if (view_id)
648         free(view_id);
649 }
650
651 static void __auth_info_recv_cb(void *user_data, int context_id, rpc_port_autofill_svc_auth_info_h svc_auth_info_h)
652 {
653     bool exist_autofill_data = false;
654     bool need_authentication = false;
655     char *service_name = NULL;
656     char *service_logo_image_path = NULL;
657     char *service_message = NULL;
658     char *app_id = NULL;
659     char *view_id = NULL;
660
661     rpc_port_autofill_svc_auth_info_get_app_id(svc_auth_info_h, &app_id);
662     rpc_port_autofill_svc_auth_info_get_view_id(svc_auth_info_h, &view_id);
663     rpc_port_autofill_svc_auth_info_get_exist_autofill_data(svc_auth_info_h, &exist_autofill_data);
664     rpc_port_autofill_svc_auth_info_get_need_authentication(svc_auth_info_h, &need_authentication);
665     rpc_port_autofill_svc_auth_info_get_service_name(svc_auth_info_h, &service_name);
666     rpc_port_autofill_svc_auth_info_get_service_logo_image_path(svc_auth_info_h, &service_logo_image_path);
667     rpc_port_autofill_svc_auth_info_get_service_message(svc_auth_info_h, &service_message);
668
669     LOGD("app id : %s, service name : %s, message : %s, logo path : %s", app_id, service_name, service_message, service_logo_image_path);
670
671     /* transfer auth info */
672     rpc_port_autofill_auth_info_h auth_info_h = NULL;
673     rpc_port_autofill_auth_info_create(&auth_info_h);
674     rpc_port_autofill_auth_info_set_app_id(auth_info_h, app_id);
675     rpc_port_autofill_auth_info_set_view_id(auth_info_h, view_id);
676     rpc_port_autofill_auth_info_set_exist_autofill_data(auth_info_h, exist_autofill_data);
677     rpc_port_autofill_auth_info_set_need_authentication(auth_info_h, need_authentication);
678     rpc_port_autofill_auth_info_set_service_name(auth_info_h, service_name);
679     rpc_port_autofill_auth_info_set_service_message(auth_info_h, service_message);
680     rpc_port_autofill_auth_info_set_service_logo_image_path(auth_info_h, service_logo_image_path);
681
682     autofill_client_s *sender_client = get_autofill_client(app_id, context_id);
683     if (sender_client)
684         rpc_port_AutofillAppPort_autofill_auth_info_received_cb_invoke(sender_client->auth_info_cb, auth_info_h);
685
686     rpc_port_autofill_auth_info_destroy(auth_info_h);
687
688     if (app_id)
689         free(app_id);
690
691     if (view_id)
692         free(view_id);
693
694     if (service_name)
695         free(service_name);
696
697     if (service_logo_image_path)
698         free(service_logo_image_path);
699
700     if (service_message)
701         free(service_message);
702 }
703
704 static void __error_info_recv_cb(void *user_data, int context_id, rpc_port_autofill_svc_error_info_h svc_error_info_h)
705 {
706     char *app_id = NULL;
707     int error_code = 0;
708
709     rpc_port_autofill_svc_error_info_get_app_id(svc_error_info_h, &app_id);
710     rpc_port_autofill_svc_error_info_get_error_code(svc_error_info_h, &error_code);
711
712     /* transfer error info */
713     rpc_port_autofill_error_info_h error_info_h = NULL;
714     rpc_port_autofill_error_info_create(&error_info_h);
715     rpc_port_autofill_error_info_set_app_id(error_info_h, app_id);
716     rpc_port_autofill_error_info_set_error_code(error_info_h, error_code);
717
718     autofill_client_s *sender_client = get_autofill_client(app_id, context_id);
719     if (sender_client)
720         rpc_port_AutofillAppPort_autofill_error_info_received_cb_invoke(sender_client->error_info_cb, error_info_h);
721
722     rpc_port_autofill_error_info_destroy(error_info_h);
723
724     LOGI("error code : %#x, message : '%s'", error_code, get_error_message(error_code));
725
726     if (app_id)
727         free(app_id);
728 }
729
730 static void __on_connected(rpc_port_proxy_AutofillSvcPort_h h, void *user_data)
731 {
732     LOGI("Autofill service connected");
733
734     if (g_connect_timer) {
735         ecore_timer_del(g_connect_timer);
736         g_connect_timer = NULL;
737     }
738
739     if (fill_response_received_cb_h) {
740         free(fill_response_received_cb_h);
741     }
742
743     if (auth_info_cb_h) {
744         free(auth_info_cb_h);
745     }
746
747     if (error_info_cb_h) {
748         free(error_info_cb_h);
749     }
750
751     fill_response_received_cb_h = rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_create(__fill_response_recv_cb, false, NULL);
752     auth_info_cb_h = rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_create(__auth_info_recv_cb, false, NULL);
753     error_info_cb_h = rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_create(__error_info_recv_cb, false, NULL);
754
755     int r = rpc_port_proxy_AutofillSvcPort_invoke_Register(h, auth_info_cb_h, fill_response_received_cb_h, error_info_cb_h);
756     if (r != 0)
757         LOGW("Failed to invoke Register");
758
759     g_connected = true;
760 }
761
762 static Eina_Bool connect_timer_cb(void *data)
763 {
764     if (connect_service()) {
765         g_connect_timer = NULL;
766         return ECORE_CALLBACK_CANCEL;
767     }
768
769     return ECORE_CALLBACK_RENEW;
770 }
771
772 static void retry_connect_service()
773 {
774     svc_rpc_h = NULL;
775
776     if (fill_response_received_cb_h) {
777         free(fill_response_received_cb_h);
778         fill_response_received_cb_h = NULL;
779     }
780
781     if (auth_info_cb_h) {
782         free(auth_info_cb_h);
783         auth_info_cb_h = NULL;
784     }
785
786     if (error_info_cb_h) {
787         free(error_info_cb_h);
788         error_info_cb_h = NULL;
789     }
790
791     g_connected = false;
792
793     // try to connect again
794     if (!connect_service()) {
795         if (g_connect_timer)
796             ecore_timer_del(g_connect_timer);
797
798         g_connect_timer = ecore_timer_add(RECONNECT_PERIOD, connect_timer_cb, NULL);
799     }
800 }
801
802 //LCOV_EXCL_START
803 static void __on_disconnected(rpc_port_proxy_AutofillSvcPort_h h, void *user_data)
804 {
805     LOGW("Autofill service is disconnected");
806
807     retry_connect_service();
808 }
809
810 static void __on_rejected(rpc_port_proxy_AutofillSvcPort_h h, void *user_data)
811 {
812     LOGW("Rejected to connect autofill service");
813
814     retry_connect_service();
815 }
816 //LCOV_EXCL_STOP
817
818 static void terminate_autofill_service()
819 {
820     if (svc_rpc_h) {
821         LOGI("Send terminate message to autofill service");
822         // terminate service
823         rpc_port_proxy_AutofillSvcPort_invoke_request_terminate(svc_rpc_h);
824
825         int ret = rpc_port_proxy_AutofillSvcPort_destroy(svc_rpc_h);
826         LOGD("ret : %#x", ret);
827         if (ret == RPC_PORT_ERROR_NONE) {
828             fill_response_received_cb_h = NULL;
829             auth_info_cb_h = NULL;
830             error_info_cb_h = NULL;
831
832             g_connected = false;
833         }
834     }
835
836     svc_rpc_h = NULL;
837 }
838
839 static bool __manager_set_autofill_service_cb(rpc_port_stub_AutofillManagerPort_context_h context, const char *app_id, void *user_data)
840 {
841     LOGI("autofill service app id: '%s'", app_id);
842
843     if (app_id)
844         autofill_config_set_autofill_service_app_id(app_id);
845
846     terminate_autofill_service();
847
848     connect_service();
849
850     return true;
851 }
852
853 static char * __manager_get_autofill_service_cb(rpc_port_stub_AutofillManagerPort_context_h context, void *user_data)
854 {
855     if (!svc_rpc_h) {
856         LOGW("Not initialized");
857         return false;
858     }
859
860     char *app_id = NULL;
861     autofill_config_get_autofill_service_app_id(&app_id, NULL);
862
863     LOGI("app id : %s", app_id);
864
865     return app_id;
866 }
867
868 bool add_autofill_service_cb(app_info_h app_info, void *user_data)
869 {
870     char *app_id = NULL;
871     rpc_port_list_string_h service_info_list = (rpc_port_list_string_h)user_data;
872
873     int ret = app_info_get_app_id(app_info, &app_id);
874     if (ret != APP_MANAGER_ERROR_NONE) {
875         LOGW("app_info_get_app_id failed (%#x)", ret);
876         return true;
877     }
878
879     LOGI("Find autofill service : %s", app_id);
880
881     rpc_port_list_string_add_list_strings(service_info_list, app_id);
882
883     if (app_id) {
884         free(app_id);
885     }
886
887     return true;
888 }
889
890 static bool __manager_get_autofill_service_list_cb(rpc_port_stub_AutofillManagerPort_context_h context, rpc_port_list_string_h *service_info_list, void *user_data)
891 {
892     int ret;
893     app_info_metadata_filter_h handle = NULL;
894
895     // Get the Autofill service list
896     ret = app_info_metadata_filter_create(&handle);
897     if (ret != APP_MANAGER_ERROR_NONE) {
898         LOGW("app_info_metadata_filter_create failed (%#x)", ret);
899         app_info_metadata_filter_destroy(handle);
900         return false;
901     }
902
903     ret = app_info_metadata_filter_add(handle, "autofill-service", "true");
904     if (ret != APP_MANAGER_ERROR_NONE) {
905         LOGW("app_info_metadata_filter_add failed (%#x)", ret);
906         app_info_metadata_filter_destroy(handle);
907         return false;
908     }
909
910     rpc_port_list_string_h app_id_list_h = NULL;
911     rpc_port_list_string_create(&app_id_list_h);
912
913     ret = app_info_metadata_filter_foreach(handle, add_autofill_service_cb, app_id_list_h);
914     if (ret != APP_MANAGER_ERROR_NONE) {
915         LOGW("app_info_metadata_filter_foreach failed (%#x)", ret);
916     }
917
918     *service_info_list = app_id_list_h;
919
920     app_info_metadata_filter_destroy(handle);
921
922     return true;
923 }
924
925 static bool connect_service()
926 {
927     int ret;
928     size_t service_id_len = 0;
929     char *active_autofill_service_id = NULL;
930     bool sys_config = false;
931
932     rpc_port_proxy_AutofillSvcPort_callback_s rpc_callback = {
933         .connected = __on_connected,
934         .disconnected = __on_disconnected,
935         .rejected = __on_rejected
936     };
937
938     if (svc_rpc_h) {
939         LOGI("connecting..\n");
940         return true;
941     }
942
943     if (g_connected) {
944         LOGI("already connected\n");
945         return true;
946     }
947
948     LOGD("get autofill service app id");
949     autofill_config_get_autofill_service_app_id(&active_autofill_service_id, &sys_config);
950     LOGI("active autofill service app id: '%s'", active_autofill_service_id);
951
952     if (!active_autofill_service_id) {
953         active_autofill_service_id = strdup(AUTOFILL_SERVICE_APP_ID);
954     }
955
956     if (!active_autofill_service_id)
957         return false;
958
959     if (!sys_config)
960         autofill_config_set_autofill_service_app_id(active_autofill_service_id);
961
962     service_id_len = strlen(active_autofill_service_id);
963
964     if (service_id_len > 0) {
965         ret = rpc_port_proxy_AutofillSvcPort_create(active_autofill_service_id, &rpc_callback, NULL, &svc_rpc_h);
966     }
967     else if (service_id_len == 0) {
968         LOGW("No Autofill service to connect");
969         free(active_autofill_service_id);
970         return false;
971     }
972
973     if (ret != RPC_PORT_ERROR_NONE) {
974         LOGW("Failed to create rpc port. error code: %#x, message: %s", ret, get_error_message(ret));
975         free(active_autofill_service_id);
976         return false;
977     }
978
979     LOGI("Connect to autofill service: '%s'", active_autofill_service_id);
980     free(active_autofill_service_id);
981     ret = rpc_port_proxy_AutofillSvcPort_connect(svc_rpc_h);
982     if (ret != RPC_PORT_ERROR_NONE) {
983         LOGW("Failed to connect. error code: %#x, message: %s", ret, get_error_message(ret));
984         rpc_port_proxy_AutofillSvcPort_destroy(svc_rpc_h);
985         svc_rpc_h = NULL;
986         return false;
987     }
988
989     return true;
990 }
991
992 bool service_app_create(void *data)
993 {
994     // Todo: add your code here.
995     LOGD("");
996
997     int ret;
998     // register app port
999     rpc_port_stub_AutofillAppPort_callback_s callback = {
1000         __client_create,
1001         __client_terminate,
1002         __client_register,
1003         __client_unregister,
1004         __auth_info_request_cb,
1005         __autofill_fill_request_cb,
1006         __commit_cb,
1007         __autofill_cancel_fill_request_cb
1008     };
1009
1010     ret = rpc_port_stub_AutofillAppPort_register(&callback, NULL);
1011     if (ret != 0)
1012         LOGW("Failed to register app port");
1013     else
1014         LOGI("Succeeded to register app port");
1015
1016     // register manager port
1017     rpc_port_stub_AutofillManagerPort_callback_s manager_callback = {
1018         __manager_create,
1019         __manager_terminate,
1020         __manager_set_autofill_service_cb,
1021         __manager_get_autofill_service_cb,
1022         __manager_get_autofill_service_list_cb,
1023     };
1024
1025     ret = rpc_port_stub_AutofillManagerPort_register(&manager_callback, NULL);
1026     if (ret != 0)
1027         LOGW("Failed to register manager port");
1028     else
1029         LOGI("Succeeded to register manager port");
1030
1031     connect_service();
1032
1033     return true;
1034 }
1035
1036 void service_app_terminate(void *data)
1037 {
1038     // Todo: add your code here.
1039     LOGD("");
1040
1041     if (__client_list) {
1042         g_list_free_full(__client_list, __destroy_client);
1043         __client_list = NULL;
1044     }
1045
1046     if (g_connect_timer) {
1047         ecore_timer_del(g_connect_timer);
1048         g_connect_timer = NULL;
1049     }
1050
1051     rpc_port_stub_AutofillAppPort_unregister();
1052
1053     return;
1054 }
1055
1056 void service_app_control(app_control_h app_control, void *data)
1057 {
1058     // Todo: add your code here.
1059     return;
1060 }
1061
1062 static void
1063 service_app_lang_changed(app_event_info_h event_info, void *user_data)
1064 {
1065     /*APP_EVENT_LANGUAGE_CHANGED*/
1066     return;
1067 }
1068
1069 static void
1070 service_app_region_changed(app_event_info_h event_info, void *user_data)
1071 {
1072     /*APP_EVENT_REGION_FORMAT_CHANGED*/
1073 }
1074
1075 static void
1076 service_app_low_battery(app_event_info_h event_info, void *user_data)
1077 {
1078     /*APP_EVENT_LOW_BATTERY*/
1079 }
1080
1081 static void
1082 service_app_low_memory(app_event_info_h event_info, void *user_data)
1083 {
1084     /*APP_EVENT_LOW_MEMORY*/
1085 }
1086
1087 /**
1088  * Entry point for this application.
1089  */
1090 int main(int argc, char *argv[])
1091 {
1092     LOGI("BEGIN");
1093
1094     char ad[50] = {0,};
1095     service_app_lifecycle_callback_s event_callback;
1096     app_event_handler_h handlers[5] = {NULL, };
1097
1098     event_callback.create = service_app_create;
1099     event_callback.terminate = service_app_terminate;
1100     event_callback.app_control = service_app_control;
1101
1102     service_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, service_app_low_battery, &ad);
1103     service_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, service_app_low_memory, &ad);
1104     service_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, service_app_lang_changed, &ad);
1105     service_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], APP_EVENT_REGION_FORMAT_CHANGED, service_app_region_changed, &ad);
1106
1107     return service_app_main(argc, argv, &event_callback, ad);
1108 }