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