ebca4b5f9f9d58db83d0dfc6a36c254da2b8cca8
[platform/core/uifw/autofill.git] / service_lib / autofill_service.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 <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <dlog.h>
21 #include <unistd.h>
22 #include <autofill.h>
23 #include <rpc-port.h>
24 #include <glib.h>
25 #include <Eina.h>
26 #include <Ecore.h>
27
28 #include "autofill_service.h"
29 #include "autofill_private.h"
30 #include "autofill_service_stub.h"
31
32 #ifdef LOG_TAG
33 #undef LOG_TAG
34 #endif
35 #define LOG_TAG "AUTOFILL_SERVICE"
36
37 static autofill_service_fill_requested_cb g_autofill_service_fill_requested_cb;
38 static void *g_autofill_service_fill_request_data = NULL;
39
40 static autofill_service_auth_info_requested_cb g_autofill_service_auth_info_requested_cb;
41 static void *g_autofill_service_auth_info_request_data = NULL;
42
43 static autofill_service_commited_cb g_autofill_service_commited_cb;
44 static void *g_autofill_service_commit_data = NULL;
45
46 static autofill_service_terminate_received_cb g_autofill_service_terminate_received_cb;
47 static void *g_autofill_service_terminate_received_data = NULL;
48
49 rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_h g_auth_info_cb;
50 rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_h g_fill_response_received_cb;
51 rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_h g_send_error_cb;
52
53 typedef struct {
54     char *app_id;
55
56     rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_h auth_info_cb;
57     rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_h fill_response_received_cb;
58     rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_h send_error_cb;
59 } autofill_svc_s;
60
61 static GList *__client_list = NULL;
62
63 //LCOV_EXCL_START
64 bool __autofill_item_cb(rpc_port_autofill_svc_item_h items, void *user_data)
65 {
66     char *id = NULL;
67     char *label = NULL;
68     char *value = NULL;
69     int autofill_hint;
70     bool sensitive_data;
71
72     autofill_view_info_h vi = (autofill_view_info_h)user_data;
73
74     autofill_item_h ai;
75     autofill_item_create(&ai);
76
77     rpc_port_autofill_svc_item_get_id(items, &id);
78     autofill_item_set_id(ai, id);
79     if (id) {
80         LOGD("id : %s", id);
81         free(id);
82     }
83
84     rpc_port_autofill_svc_item_get_label(items, &label);
85     autofill_item_set_label(ai, label);
86     if (label) {
87         LOGD("label : %s", label);
88         free(label);
89     }
90
91     rpc_port_autofill_svc_item_get_value(items, &value);
92     autofill_item_set_value(ai, value);
93     if (value) {
94         LOGD("value : %s", value);
95         free(value);
96     }
97
98     rpc_port_autofill_svc_item_get_autofill_hint(items, &autofill_hint);
99     autofill_item_set_autofill_hint(ai, autofill_hint);
100     LOGD("autofill hint : %d", autofill_hint);
101
102     rpc_port_autofill_svc_item_get_is_sensitive_data(items, &sensitive_data);
103     autofill_item_set_sensitive_data(ai, sensitive_data);
104     LOGD("sensitive data : %d", sensitive_data);
105
106     autofill_view_info_add_item(vi, ai);
107
108     autofill_item_destroy(ai);
109
110     return true;
111 }
112
113 bool __save_item_cb(rpc_port_autofill_svc_save_item_h items, void *user_data)
114 {
115     char *id = NULL;
116     char *label = NULL;
117     char *value = NULL;
118     int autofill_hint;
119     bool sensitive_data;
120
121     autofill_save_view_info_h vi = (autofill_save_view_info_h)user_data;
122
123     autofill_save_item_h ai;
124     autofill_save_item_create(&ai);
125
126     rpc_port_autofill_svc_save_item_get_id(items, &id);
127     autofill_save_item_set_id(ai, id);
128     if (id) {
129         LOGD("id : %s", id);
130         free(id);
131     }
132
133     rpc_port_autofill_svc_save_item_get_label(items, &label);
134     autofill_save_item_set_label(ai, label);
135     if (label) {
136         LOGD("label : %s", label);
137         free(label);
138     }
139
140     rpc_port_autofill_svc_save_item_get_value(items, &value);
141     autofill_save_item_set_value(ai, value);
142     if (value) {
143         LOGD("value : %s", value);
144         free(value);
145     }
146
147     rpc_port_autofill_svc_save_item_get_autofill_hint(items, &autofill_hint);
148     autofill_save_item_set_autofill_hint(ai, autofill_hint);
149     LOGD("autofill hint : %d", autofill_hint);
150
151     rpc_port_autofill_svc_save_item_get_is_sensitive_data(items, &sensitive_data);
152     autofill_save_item_set_sensitive_data(ai, sensitive_data);
153     LOGD("sensitive data : %d", sensitive_data);
154
155     autofill_save_view_info_add_item(vi, ai);
156
157     autofill_save_item_destroy(ai);
158
159     return true;
160 }
161
162 static void __auth_info_request_cb(rpc_port_stub_AutofillSvcPort_context_h context, int context_id, rpc_port_autofill_svc_view_info_h vi, void *user_data)
163 {
164     char *sender = NULL;
165
166     rpc_port_stub_AutofillSvcPort_context_get_sender(context, &sender);
167     if (sender) {
168         LOGD("sender(%s)", sender);
169         free(sender);
170     }
171
172     char *app_id = NULL;
173     char *view_id = NULL;
174     rpc_port_autofill_svc_view_info_get_app_id(vi, &app_id);
175     rpc_port_autofill_svc_view_info_get_view_id(vi, &view_id);
176     LOGD("app id : %s, view id : %s", app_id, view_id);
177
178     autofill_view_info_h view_info;
179     autofill_view_info_create(&view_info);
180     autofill_view_info_set_app_id(view_info, app_id);
181     autofill_view_info_set_view_id(view_info, view_id);
182
183     rpc_port_autofill_svc_view_info_foreach_items(vi, __autofill_item_cb, view_info);
184
185     if (g_autofill_service_auth_info_requested_cb)
186         g_autofill_service_auth_info_requested_cb(context_id, view_info, g_autofill_service_auth_info_request_data);
187
188     autofill_view_info_destroy(view_info);
189
190     if (view_id)
191         free(view_id);
192
193     if (app_id)
194         free(app_id);
195 }
196
197 static void __autofill_fill_request_cb(rpc_port_stub_AutofillSvcPort_context_h context, int context_id, rpc_port_autofill_svc_view_info_h vi, void *user_data)
198 {
199     char *app_id = NULL;
200     char *view_id = NULL;
201
202     rpc_port_autofill_svc_view_info_get_app_id(vi, &app_id);
203     rpc_port_autofill_svc_view_info_get_view_id(vi, &view_id);
204
205     LOGD("app id : %s, view id : %s", app_id, view_id);
206
207     autofill_view_info_h view_info;
208     autofill_view_info_create(&view_info);
209     autofill_view_info_set_app_id(view_info, app_id);
210     autofill_view_info_set_view_id(view_info, view_id);
211
212     rpc_port_autofill_svc_view_info_foreach_items(vi, __autofill_item_cb, view_info);
213
214     if (g_autofill_service_fill_requested_cb)
215         g_autofill_service_fill_requested_cb(context_id, view_info, g_autofill_service_auth_info_request_data);
216
217     autofill_view_info_destroy(view_info);
218
219     if (app_id)
220         free(app_id);
221
222     if (view_id)
223         free(view_id);
224 }
225
226 static void __autofill_commit_cb(rpc_port_stub_AutofillSvcPort_context_h context, int context_id, rpc_port_autofill_svc_save_view_info_h vi, void *user_data)
227 {
228     char *app_id = NULL;
229     char *view_id = NULL;
230     char *view_title = NULL;
231
232     rpc_port_autofill_svc_save_view_info_get_app_id(vi, &app_id);
233     rpc_port_autofill_svc_save_view_info_get_view_id(vi, &view_id);
234     rpc_port_autofill_svc_save_view_info_get_view_title(vi, &view_title);
235
236     LOGD("app id : %s, view id : %s", app_id, view_id);
237
238     autofill_save_view_info_h view_info;
239     autofill_save_view_info_create(&view_info);
240     autofill_save_view_info_set_app_id(view_info, app_id);
241     autofill_save_view_info_set_view_id(view_info, view_id);
242     autofill_save_view_info_set_view_title(view_info, view_title);
243
244     rpc_port_autofill_svc_save_view_info_foreach_items(vi, __save_item_cb, view_info);
245
246     if (g_autofill_service_commited_cb)
247         g_autofill_service_commited_cb(context_id, view_info, g_autofill_service_commit_data);
248
249     autofill_save_view_info_destroy(view_info);
250
251     if (app_id) {
252         free(app_id);
253     }
254
255     if (view_id) {
256         free(view_id);
257     }
258
259     if (view_title) {
260         free(view_title);
261     }
262 }
263
264 static void __terminate_received_cb(rpc_port_stub_AutofillSvcPort_context_h context, void *user_data)
265 {
266     LOGD("");
267
268     if (g_autofill_service_terminate_received_cb)
269         g_autofill_service_terminate_received_cb(g_autofill_service_terminate_received_data);
270
271     ecore_main_loop_quit();
272 }
273
274 static autofill_svc_s *__create_client(const char *app_id,
275             rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_h auth_info_cb,
276             rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_h fill_response_received_cb,
277             rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_h send_error_cb)
278 {
279     LOGD("");
280     autofill_svc_s *handle;
281
282     handle = calloc(1, sizeof(autofill_svc_s));
283     if (!handle) {
284         LOGE("Out of memory");
285         return NULL;
286     }
287
288     handle->app_id = strdup(app_id);
289     if (!handle->app_id) {
290         LOGE("Out of memory");
291         free(handle);
292         return NULL;
293     }
294
295     rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_clone(auth_info_cb, &handle->auth_info_cb);
296     if (!handle->auth_info_cb) {
297         LOGE("Out of memory");
298         free(handle->app_id);
299         free(handle);
300         return NULL;
301     }
302
303     rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_clone(fill_response_received_cb, &handle->fill_response_received_cb);
304
305     if (!handle->fill_response_received_cb) {
306         LOGE("Out of memory");
307         free(handle->app_id);
308         rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_destroy(handle->auth_info_cb);
309         free(handle);
310         return NULL;
311     }
312
313     rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_clone(send_error_cb, &handle->send_error_cb);
314     if (!handle->send_error_cb) {
315         LOGE("Out of memory");
316         free(handle->app_id);
317         rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_destroy(handle->auth_info_cb);
318         rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_destroy(handle->fill_response_received_cb);
319         free(handle);
320         return NULL;
321     }
322
323     return handle;
324 }
325
326 static void __destroy_client(gpointer data)
327 {
328     LOGD("");
329     autofill_svc_s *handle = data;
330
331     if (!handle)
332         return;
333
334     if (handle->auth_info_cb) {
335         rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_destroy(handle->auth_info_cb);
336         handle->auth_info_cb = NULL;
337     }
338
339     if (handle->fill_response_received_cb) {
340         rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_destroy(handle->fill_response_received_cb);
341         handle->fill_response_received_cb = NULL;
342     }
343
344     if (handle->send_error_cb) {
345         rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_destroy(handle->send_error_cb);
346         handle->send_error_cb = NULL;
347     }
348
349     if (handle->app_id) {
350         free(handle->app_id);
351         handle->app_id = NULL;
352     }
353
354     free(handle);
355 }
356
357 static int __message_register(rpc_port_stub_AutofillSvcPort_context_h context,
358                               rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_h auth_info_cb,
359                               rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_h fill_response_received_cb,
360                               rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_h send_error_cb,
361                               void *user_data)
362 {
363     LOGD("");
364     char *sender = NULL;
365
366     rpc_port_stub_AutofillSvcPort_context_get_sender(context, &sender);
367     if (!sender)
368         return -1;
369
370     autofill_svc_s *client;
371     client = __create_client(sender, auth_info_cb, fill_response_received_cb, send_error_cb);
372     free(sender);
373
374     if (!client)
375         return -1;
376
377     rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_clone(auth_info_cb, &g_auth_info_cb);
378     rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_clone(fill_response_received_cb, &g_fill_response_received_cb);
379     rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_clone(send_error_cb, &g_send_error_cb);
380
381     __client_list = g_list_append(__client_list, client);
382
383     rpc_port_stub_AutofillSvcPort_context_set_tag(context, client);
384
385     return 0;
386 }
387
388 static void __message_unregister(rpc_port_stub_AutofillSvcPort_context_h context, void *user_data)
389 {
390     autofill_svc_s *client = NULL;
391     rpc_port_stub_AutofillSvcPort_context_get_tag(context, (void *)&client);
392     if (client == NULL)
393         return;
394
395     rpc_port_stub_AutofillSvcPort_context_set_tag(context, NULL);
396     LOGI("name(%s)", client->app_id);
397
398     __client_list = g_list_remove(__client_list, client);
399     __destroy_client(client);
400 }
401 //LCOV_EXCL_STOP
402
403 EXPORT_API int autofill_service_initialize(void)
404 {
405     LOGD("autofill service initialize");
406
407     int ret;
408
409     rpc_port_stub_AutofillSvcPort_callback_s callback = {
410         NULL,
411         NULL,
412         __message_register,
413         __message_unregister,
414         __auth_info_request_cb,
415         __autofill_fill_request_cb,
416         __autofill_commit_cb,
417         __terminate_received_cb
418     };
419
420     ret = rpc_port_stub_AutofillSvcPort_register(&callback, NULL);
421     if (ret != 0)
422         LOGW("Failed to register message");
423     else
424         LOGI("Succeeded to register message");
425
426     return ret;
427 }
428
429 EXPORT_API int autofill_service_deinitialize(void)
430 {
431     LOGD("autofill service deinitialize");
432
433     if (__client_list) {
434         g_list_free_full(__client_list, __destroy_client);
435         __client_list = NULL;
436     }
437
438     rpc_port_stub_AutofillSvcPort_unregister();
439
440     return AUTOFILL_ERROR_NONE;
441 }
442
443 EXPORT_API int autofill_service_set_auth_info_requested_cb(autofill_service_auth_info_requested_cb callback, void *user_data)
444 {
445     if (!callback) {
446         LOGW("[ERROR] Invalid parameter");
447         return AUTOFILL_ERROR_INVALID_PARAMETER;
448     }
449
450     g_autofill_service_auth_info_requested_cb = callback;
451     g_autofill_service_auth_info_request_data = user_data;
452
453     return AUTOFILL_ERROR_NONE;
454 }
455
456 EXPORT_API int autofill_service_unset_auth_info_requested_cb()
457 {
458     g_autofill_service_auth_info_requested_cb = NULL;
459     g_autofill_service_auth_info_request_data = NULL;
460
461     return AUTOFILL_ERROR_NONE;
462 }
463
464 EXPORT_API int autofill_service_send_auth_info(int context_id, autofill_auth_info_h h)
465 {
466     bool autofill_data_present = false;
467     bool authentication_needed = false;
468     char *app_id = NULL;
469     char *view_id = NULL;
470     char *service_name = NULL;
471     char *service_logo_image_path = NULL;
472     char *service_message = NULL;
473     int ret = AUTOFILL_ERROR_NONE;
474
475     if (!h) {
476         LOGW("[ERROR] Invalid parameter");
477         return AUTOFILL_ERROR_INVALID_PARAMETER;
478     }
479
480     autofill_auth_info_get_app_id(h, &app_id);
481     autofill_auth_info_get_view_id(h, &view_id);
482     autofill_auth_info_get_autofill_data_present(h, &autofill_data_present);
483     autofill_auth_info_get_authentication_needed(h, &authentication_needed);
484     autofill_auth_info_get_service_name(h, &service_name);
485     autofill_auth_info_get_service_message(h, &service_message);
486     autofill_auth_info_get_service_logo_image_path(h, &service_logo_image_path);
487
488     LOGD("app_id : %s", app_id);
489
490     /* create auth info */
491     rpc_port_autofill_svc_auth_info_h auth_info_h;
492     rpc_port_autofill_svc_auth_info_create(&auth_info_h);
493     rpc_port_autofill_svc_auth_info_set_app_id(auth_info_h, app_id);
494     rpc_port_autofill_svc_auth_info_set_view_id(auth_info_h, view_id);
495     rpc_port_autofill_svc_auth_info_set_exist_autofill_data(auth_info_h, autofill_data_present);
496     rpc_port_autofill_svc_auth_info_set_need_authentication(auth_info_h, authentication_needed);
497     rpc_port_autofill_svc_auth_info_set_service_name(auth_info_h, service_name);
498     rpc_port_autofill_svc_auth_info_set_service_message(auth_info_h, service_message);
499     rpc_port_autofill_svc_auth_info_set_service_logo_image_path(auth_info_h, service_logo_image_path);
500
501     ret = rpc_port_AutofillSvcPort_autofill_svc_auth_info_cb_invoke(g_auth_info_cb, context_id, auth_info_h);
502
503     if (app_id)
504         free(app_id);
505
506     if (view_id)
507         free(view_id);
508
509     if (service_name)
510         free(service_name);
511
512     if (service_logo_image_path)
513         free(service_logo_image_path);
514
515     if (service_message)
516         free(service_message);
517
518     rpc_port_autofill_svc_auth_info_destroy(auth_info_h);
519
520     return ret;
521 }
522
523 // fill request
524 EXPORT_API int autofill_service_set_fill_requested_cb(autofill_service_fill_requested_cb callback, void *user_data)
525 {
526     if (!callback) {
527         LOGW("[ERROR] Invalid parameter");
528         return AUTOFILL_ERROR_INVALID_PARAMETER;
529     }
530
531     g_autofill_service_fill_requested_cb = callback;
532     g_autofill_service_fill_request_data = user_data;
533
534     return AUTOFILL_ERROR_NONE;
535 }
536
537 EXPORT_API int autofill_service_unset_fill_requested_cb()
538 {
539     g_autofill_service_fill_requested_cb = NULL;
540     g_autofill_service_fill_request_data = NULL;
541
542     return AUTOFILL_ERROR_NONE;
543 }
544
545 bool __fill_response_item_cb(autofill_fill_response_item_h it, void * user_data)
546 {
547     char *id = NULL;
548     char *value = NULL;
549     char *presentation_text = NULL;
550
551     rpc_port_autofill_svc_response_group_h res_group_h = (rpc_port_autofill_svc_response_group_h)user_data;
552
553     rpc_port_autofill_svc_response_item_h ritem_h;
554
555     autofill_fill_response_item_get_id(it, &id);
556     autofill_fill_response_item_get_value(it, &value);
557     autofill_fill_response_item_get_presentation_text(it, &presentation_text);
558
559     LOGD("it : %p, id : %s, value : %s, presentation text : %s", it, id, value, presentation_text);
560
561     rpc_port_autofill_svc_response_item_create(&ritem_h);
562     rpc_port_autofill_svc_response_item_set_id(ritem_h, id);
563     rpc_port_autofill_svc_response_item_set_presentation_text(ritem_h, presentation_text);
564     rpc_port_autofill_svc_response_item_set_value(ritem_h, value);
565
566     rpc_port_autofill_svc_response_group_add_response_items(res_group_h, ritem_h);
567
568     if (id) {
569         free(id);
570         id = NULL;
571     }
572
573     if (value) {
574         free(value);
575         value = NULL;
576     }
577
578     if (presentation_text) {
579         free(presentation_text);
580         presentation_text= NULL;
581     }
582
583     rpc_port_autofill_svc_response_item_destroy(ritem_h);
584
585     return true;
586 }
587
588 EXPORT_API int autofill_service_send_fill_response(int context_id, autofill_fill_response_h h)
589 {
590     /* create autofill response */
591     rpc_port_autofill_svc_fill_response_h fill_response_h;
592     int ret = AUTOFILL_ERROR_NONE;
593
594     Eina_List *l;
595     autofill_fill_response_group_h it;
596
597     if (!h) {
598         LOGW("[ERROR] Invalid parameter");
599         return AUTOFILL_ERROR_INVALID_PARAMETER;
600     }
601
602     rpc_port_autofill_svc_fill_response_create(&fill_response_h);
603
604     if (h->app_id)
605         rpc_port_autofill_svc_fill_response_set_app_id(fill_response_h, h->app_id);
606
607     if (h->view_id)
608         rpc_port_autofill_svc_fill_response_set_view_id(fill_response_h, h->view_id);
609
610     rpc_port_autofill_svc_response_group_h res_group_h;
611
612     EINA_LIST_FOREACH(h->autofill_fill_response_group_list, l, it)
613     {
614         res_group_h = NULL;
615         rpc_port_autofill_svc_response_group_create(&res_group_h);
616
617         autofill_fill_response_group_foreach_item(it, __fill_response_item_cb, res_group_h);
618
619         rpc_port_autofill_svc_fill_response_add_response_groups(fill_response_h, res_group_h);
620
621         rpc_port_autofill_svc_response_group_destroy(res_group_h);
622     }
623
624     ret = rpc_port_AutofillSvcPort_autofill_svc_fill_response_cb_invoke(g_fill_response_received_cb, context_id, fill_response_h);
625
626     rpc_port_autofill_svc_fill_response_destroy(fill_response_h);
627
628     return ret;
629 }
630
631 EXPORT_API int autofill_service_set_commited_cb(autofill_service_commited_cb callback, void *user_data)
632 {
633     if (!callback) {
634         LOGW("[ERROR] Invalid parameter");
635         return AUTOFILL_ERROR_INVALID_PARAMETER;
636     }
637
638     g_autofill_service_commited_cb = callback;
639     g_autofill_service_commit_data = user_data;
640
641     return AUTOFILL_ERROR_NONE;
642 }
643
644 EXPORT_API int autofill_service_unset_commited_cb(void)
645 {
646     g_autofill_service_commited_cb = NULL;
647     g_autofill_service_commit_data = NULL;
648
649     return AUTOFILL_ERROR_NONE;
650 }
651
652 EXPORT_API int autofill_service_set_terminate_received_cb(autofill_service_terminate_received_cb callback, void *user_data)
653 {
654     if (!callback) {
655         LOGW("[ERROR] Invalid parameter");
656         return AUTOFILL_ERROR_INVALID_PARAMETER;
657     }
658     g_autofill_service_terminate_received_cb = callback;
659     g_autofill_service_terminate_received_data = user_data;
660
661     return AUTOFILL_ERROR_NONE;
662 }
663
664 EXPORT_API int autofill_service_unset_terminate_received_cb(void)
665 {
666     g_autofill_service_terminate_received_cb = NULL;
667     g_autofill_service_terminate_received_data = NULL;
668
669     return AUTOFILL_ERROR_NONE;
670 }
671
672 EXPORT_API int autofill_service_send_error_info(int context_id, autofill_error_info_h h)
673 {
674     char *app_id = NULL;
675     autofill_error_e error_code;
676     rpc_port_autofill_svc_error_info_h error_info_h = NULL;
677
678     if (!h) {
679         LOGW("[ERROR] Invalid parameter");
680         return AUTOFILL_ERROR_INVALID_PARAMETER;
681     }
682
683     autofill_error_info_get_app_id(h, &app_id);
684     autofill_error_info_get_error_code(h, &error_code);
685
686     /* create error info */
687     rpc_port_autofill_svc_error_info_create(&error_info_h);
688     rpc_port_autofill_svc_error_info_set_app_id(error_info_h, app_id);
689     rpc_port_autofill_svc_error_info_set_error_code(error_info_h, error_code);
690
691     int ret = rpc_port_AutofillSvcPort_autofill_svc_send_error_cb_invoke(g_send_error_cb, context_id, error_info_h);
692
693     if (app_id)
694         free(app_id);
695
696     rpc_port_autofill_svc_error_info_destroy(error_info_h);
697
698     return ret;
699 }