c53c86ecee30de847d5c7c116656b562730f06e1
[platform/core/uifw/autofill.git] / client / autofill.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 <Eina.h>
23 #include <autofill.h>
24 #include <rpc-port.h>
25 #include "autofill_private.h"
26 #include "autofill_proxy.h"
27
28 #define AUTOFILL_DAEMON_APP_ID "org.tizen.autofilld"
29
30 #ifdef LOG_TAG
31 #undef LOG_TAG
32 #endif
33 #define LOG_TAG "AUTOFILL"
34
35 static int _autofill_context_count = 0;
36
37 //LCOV_EXCL_START
38 static bool fill_response_item_cb(rpc_port_autofill_response_item_h response_items, void *user_data)
39 {
40     char *id = NULL;
41     char *presentation_text = NULL;
42     char *value = NULL;
43     autofill_fill_response_group_h res_group = (autofill_fill_response_group_h)user_data;
44
45     if (!res_group)
46         return true;
47
48     rpc_port_autofill_response_item_get_id(response_items, &id);
49     rpc_port_autofill_response_item_get_presentation_text(response_items, &presentation_text);
50     rpc_port_autofill_response_item_get_value(response_items, &value);
51
52     LOGD("id : %s, presentation text : %s, value : %s", id, presentation_text, value);
53
54     autofill_fill_response_item_h ritem;
55
56     autofill_fill_response_item_create(&ritem);
57     autofill_fill_response_item_set_id(ritem, id);
58     autofill_fill_response_item_set_presentation_text(ritem, presentation_text);
59     autofill_fill_response_item_set_value(ritem, value);
60
61     autofill_fill_response_group_add_item(res_group, ritem);
62
63     if (id)
64         free(id);
65
66     if (presentation_text)
67         free(presentation_text);
68
69     if (value)
70         free(value);
71
72     autofill_fill_response_item_destroy(ritem);
73
74     return true;
75 }
76
77 static bool fill_response_group_cb(rpc_port_autofill_response_group_h response_groups, void *user_data)
78 {
79     autofill_fill_response_h rh = (autofill_fill_response_h)user_data;
80     autofill_fill_response_group_h res_group;
81
82     autofill_fill_response_group_create(&res_group);
83
84     rpc_port_autofill_response_group_foreach_response_items(response_groups, fill_response_item_cb, res_group);
85
86     autofill_fill_response_add_group(rh, res_group);
87
88     autofill_fill_response_group_destroy(res_group);
89
90     return true;
91 }
92
93 static void __fill_response_recv_cb(void *user_data, rpc_port_autofill_fill_response_h response_h)
94 {
95     char *app_id = NULL;
96     char *view_id = NULL;
97     autofill_h ah = user_data;
98     autofill_fill_response_h rh;
99
100     autofill_fill_response_create(&rh);
101
102     rpc_port_autofill_fill_response_get_app_id(response_h, &app_id);
103     rpc_port_autofill_fill_response_get_view_id(response_h, &view_id);
104
105     LOGD("app id : %s, view id : %s", app_id, view_id);
106
107     if (app_id) {
108         autofill_fill_response_set_app_id(rh, app_id);
109         free(app_id);
110     }
111
112     if (view_id) {
113         autofill_fill_response_set_view_id(rh, view_id);
114         free(view_id);
115     }
116
117     rpc_port_autofill_fill_response_foreach_response_groups(response_h, fill_response_group_cb, rh);
118
119     if (ah->autofill_fill_response_received_cb)
120         ah->autofill_fill_response_received_cb(ah, rh, ah->autofill_fill_response_data);
121
122     autofill_fill_response_destroy(rh);
123 }
124
125 static void __auth_info_recv_cb(void *user_data, rpc_port_autofill_auth_info_h auth_info_h)
126 {
127     autofill_auth_info_h aih;
128     autofill_h ah = user_data;
129
130     autofill_auth_info_create(&aih);
131
132     bool autofill_data_present = false;
133     bool authentication_needed = false;
134     char *app_id = NULL;
135     char *view_id = NULL;
136     char *service_name = NULL;
137     char *service_logo_image_path = NULL;
138     char *service_message = NULL;
139
140     rpc_port_autofill_auth_info_get_app_id(auth_info_h, &app_id);
141     rpc_port_autofill_auth_info_get_view_id(auth_info_h, &view_id);
142     rpc_port_autofill_auth_info_get_exist_autofill_data(auth_info_h, &autofill_data_present);
143     rpc_port_autofill_auth_info_get_need_authentication(auth_info_h, &authentication_needed);
144     rpc_port_autofill_auth_info_get_service_name(auth_info_h, &service_name);
145     rpc_port_autofill_auth_info_get_service_logo_image_path(auth_info_h, &service_logo_image_path);
146     rpc_port_autofill_auth_info_get_service_message(auth_info_h, &service_message);
147
148     LOGD("app id : %s, view id : %s, service name : %s", app_id, view_id, service_name);
149
150     autofill_auth_info_set_app_id(aih, app_id);
151     autofill_auth_info_set_view_id(aih, view_id);
152     autofill_auth_info_set_autofill_data_present(aih, autofill_data_present);
153     autofill_auth_info_set_authentication_needed(aih, authentication_needed);
154     autofill_auth_info_set_service_name(aih, service_name);
155     autofill_auth_info_set_service_logo_image_path(aih, service_logo_image_path);
156     autofill_auth_info_set_service_message(aih, service_message);
157
158     if (app_id)
159         free(app_id);
160
161     if (view_id)
162         free(view_id);
163
164     if (service_name)
165         free(service_name);
166
167     if (service_logo_image_path)
168         free(service_logo_image_path);
169
170     if (service_message)
171         free(service_message);
172
173     if (ah) {
174         if (ah->autofill_auth_info_received_cb)
175             ah->autofill_auth_info_received_cb(ah, aih, ah->autofill_auth_info_data);
176     }
177     else {
178         LOGW("no user data");
179     }
180
181     autofill_auth_info_destroy(aih);
182 }
183
184 static void __error_info_recv_cb(void *user_data, rpc_port_autofill_error_info_h error_info_h)
185 {
186     autofill_error_info_h eih = NULL;
187     autofill_h ah = user_data;
188
189     int error_code = 0;
190     char *app_id = NULL;
191
192     autofill_error_info_create(&eih);
193
194     rpc_port_autofill_error_info_get_app_id(error_info_h, &app_id);
195     rpc_port_autofill_error_info_get_error_code(error_info_h, &error_code);
196
197     autofill_error_info_set_app_id(eih, app_id);
198     autofill_error_info_set_error_code(eih, error_code);
199
200     LOGI("error code : %x", error_code);
201
202     if (app_id)
203         free(app_id);
204
205     if (ah) {
206         if (ah->autofill_error_info_received_cb)
207             ah->autofill_error_info_received_cb(ah, eih, ah->autofill_error_info_data);
208     }
209     else {
210         LOGW("no user data");
211     }
212
213     autofill_error_info_destroy(eih);
214 }
215 //LCOV_EXCL_STOP
216
217 static void __on_connected(rpc_port_proxy_AutofillAppPort_h h, void *user_data)
218 {
219     autofill_h ah = user_data;
220     if (!ah) {
221         LOGW("no user data");
222         return;
223     }
224
225     ah->connected = true;
226
227     LOGI("connected");
228     rpc_port_AutofillAppPort_autofill_fill_response_received_cb_h fill_response_received_cb = rpc_port_AutofillAppPort_autofill_fill_response_received_cb_create(__fill_response_recv_cb, false, ah);
229     rpc_port_AutofillAppPort_autofill_auth_info_received_cb_h auth_info_received_cb = rpc_port_AutofillAppPort_autofill_auth_info_received_cb_create(__auth_info_recv_cb, false, ah);
230     rpc_port_AutofillAppPort_autofill_error_info_received_cb_h error_info_received_cb = rpc_port_AutofillAppPort_autofill_error_info_received_cb_create(__error_info_recv_cb, false, ah);
231
232     int r = rpc_port_proxy_AutofillAppPort_invoke_Register(h, ah->context_id, auth_info_received_cb, fill_response_received_cb, error_info_received_cb);
233     if (r != 0)
234         LOGW("[ERROR] Failed to invoke Register");
235
236     if (ah->connection_callback)
237         ah->connection_callback(ah, AUTOFILL_CONNECTION_STATUS_CONNECTED, ah->connection_userdata);
238 }
239
240 //LCOV_EXCL_START
241 static void __on_disconnected(rpc_port_proxy_AutofillAppPort_h h, void *user_data)
242 {
243     LOGI("disconnected");
244
245     autofill_h ah = user_data;
246     if (ah) {
247         ah->connected = false;
248
249         if (ah && ah->connection_callback)
250             ah->connection_callback(ah, AUTOFILL_CONNECTION_STATUS_DISCONNECTED, ah->connection_userdata);
251
252         ah->rpc_h = NULL;
253     }
254 }
255
256 static void __on_rejected(rpc_port_proxy_AutofillAppPort_h h, void *user_data)
257 {
258     LOGI("rejected");
259
260     autofill_h ah = user_data;
261
262     if (ah && ah->connection_callback)
263         ah->connection_callback(ah, AUTOFILL_CONNECTION_STATUS_REJECTED, ah->connection_userdata);
264 }
265 //LCOV_EXCL_STOP
266
267 EXPORT_API int autofill_create(autofill_h *ah)
268 {
269     int ret;
270
271     if (!ah)
272         return AUTOFILL_ERROR_INVALID_PARAMETER;
273
274     rpc_port_proxy_AutofillAppPort_callback_s rpc_callback = {
275         .connected = __on_connected,
276         .disconnected = __on_disconnected,
277         .rejected = __on_rejected
278     };
279
280     struct autofill_s *as = (autofill_h)calloc(1, sizeof(struct autofill_s));
281     if (!as)
282         return AUTOFILL_ERROR_OUT_OF_MEMORY;
283
284     ret = rpc_port_proxy_AutofillAppPort_create(AUTOFILL_DAEMON_APP_ID, &rpc_callback, as, &as->rpc_h);
285     if (ret != RPC_PORT_ERROR_NONE) {
286         LOGW("[ERROR] Failed to create rpc port. err = %d", ret);
287         free(as);
288         return AUTOFILL_ERROR_OUT_OF_MEMORY;
289     }
290
291     as->context_id = _autofill_context_count++;
292     *ah = as;
293
294     return AUTOFILL_ERROR_NONE;
295 }
296
297 EXPORT_API int autofill_destroy(autofill_h ah)
298 {
299     if (!ah)
300         return AUTOFILL_ERROR_INVALID_PARAMETER;
301
302     ah->connection_callback = NULL;
303     ah->autofill_fill_response_received_cb = NULL;
304     ah->autofill_auth_info_received_cb = NULL;
305     ah->autofill_error_info_received_cb = NULL;
306
307     if (ah->rpc_h) {
308         rpc_port_proxy_AutofillAppPort_destroy(ah->rpc_h);
309         ah->rpc_h = NULL;
310     }
311
312     free(ah);
313
314     return AUTOFILL_ERROR_NONE;
315 }
316
317 EXPORT_API int autofill_connect(autofill_h ah, autofill_connection_status_changed_cb callback, void *user_data)
318 {
319     LOGD("autofill connect. handle : %p", ah);
320
321     int ret;
322
323     if (!ah || !callback) {
324         LOGW("[ERROR] Invalid parameter");
325         return AUTOFILL_ERROR_INVALID_PARAMETER;
326     }
327
328     if (!ah->rpc_h) {
329         return AUTOFILL_ERROR_OPERATION_FAILED;
330     }
331
332     ah->connection_callback = callback;
333     ah->connection_userdata = user_data;
334
335     ret = rpc_port_proxy_AutofillAppPort_connect(ah->rpc_h);
336     if (ret != RPC_PORT_ERROR_NONE) {
337         switch(ret) {
338             case RPC_PORT_ERROR_IO_ERROR:
339                 LOGW("[ERROR] Failed to connect rpc port. I/O Error");
340                 break;
341             case RPC_PORT_ERROR_OUT_OF_MEMORY:
342                 LOGW("[ERROR] Failed to connect rpc port. Out of memory");
343                 break;
344             case RPC_PORT_ERROR_INVALID_PARAMETER:
345                 LOGW("[ERROR] Failed to connect rpc port. Invalid parameter");
346                 break;
347             case RPC_PORT_ERROR_PERMISSION_DENIED:
348                 LOGW("[ERROR] Failed to connect rpc port. Permission denied");
349                 break;
350             default:
351                 LOGW("[ERROR] Failed to connect rpc port. errcode = %d", ret);
352                 break;
353         }
354         return AUTOFILL_ERROR_OPERATION_FAILED;
355     }
356     else {
357         return AUTOFILL_ERROR_NONE;
358     }
359 }
360
361 EXPORT_API int autofill_commit(autofill_h ah, autofill_save_view_info_h vi)
362 {
363     rpc_port_autofill_save_view_info_h vih;
364     char *id = NULL;
365     char *label = NULL;
366     char *value = NULL;
367     autofill_hint_e autofill_hint;
368     bool sensitive_data;
369
370     if (!ah || !vi) {
371         LOGW("[ERROR] Invalid parameter");
372         return AUTOFILL_ERROR_INVALID_PARAMETER;
373     }
374
375     if (!ah->rpc_h) {
376         return AUTOFILL_ERROR_OPERATION_FAILED;
377     }
378
379     if (!ah->connected) {
380         LOGW("[ERROR] Not connected");
381         return AUTOFILL_ERROR_OPERATION_FAILED;
382     }
383
384     rpc_port_autofill_save_view_info_create(&vih);
385     rpc_port_autofill_save_view_info_set_view_id(vih, vi->view_id);
386     rpc_port_autofill_save_view_info_set_view_title(vih, vi->view_title);
387
388     Eina_List *l;
389     autofill_save_item_h it;
390     EINA_LIST_FOREACH(vi->autofill_save_item_list, l, it)
391     {
392         autofill_save_item_get_id(it, &id);
393         autofill_save_item_get_label(it, &label);
394         autofill_save_item_get_value(it, &value);
395         autofill_save_item_get_autofill_hint(it, &autofill_hint);
396         autofill_save_item_get_sensitive_data(it, &sensitive_data);
397
398         LOGD("it : %p, id : %s, label : %s, hint : %d, sensitive : %d", it, id, label, autofill_hint, sensitive_data);
399
400         rpc_port_autofill_save_item_h aih;
401         rpc_port_autofill_save_item_create(&aih);
402         rpc_port_autofill_save_item_set_id(aih, id);
403         rpc_port_autofill_save_item_set_label(aih, label);
404         rpc_port_autofill_save_item_set_value(aih, value);
405         rpc_port_autofill_save_item_set_autofill_hint(aih, (int)autofill_hint);
406         rpc_port_autofill_save_item_set_is_sensitive_data(aih, sensitive_data);
407         rpc_port_autofill_save_view_info_add_items(vih, aih);
408
409         if (id) {
410             free(id);
411             id = NULL;
412         }
413
414         if (label) {
415             free(label);
416             label = NULL;
417         }
418
419         if (value) {
420             free(value);
421             value = NULL;
422         }
423
424         rpc_port_autofill_save_item_destroy(aih);
425     }
426
427     LOGD("app id : %s, view id : '%s', view title : '%s'", vi->app_id, vi->view_id, vi->view_title);
428
429     int ret = rpc_port_proxy_AutofillAppPort_invoke_commit(ah->rpc_h, ah->context_id, vih);
430
431     rpc_port_autofill_save_view_info_destroy(vih);
432
433     if (ret != RPC_PORT_ERROR_NONE) {
434         LOGW("[ERROR] Failed to commit. rpc err = %d", ret);
435         return AUTOFILL_ERROR_OPERATION_FAILED;
436     }
437     else {
438         return AUTOFILL_ERROR_NONE;
439     }
440 }
441
442 EXPORT_API int autofill_error_info_set_received_cb(autofill_h ah, autofill_error_info_received_cb callback, void *user_data)
443 {
444     if (!ah || !callback) {
445         LOGW("[ERROR] Invalid parameter");
446         return AUTOFILL_ERROR_INVALID_PARAMETER;
447     }
448
449     ah->autofill_error_info_received_cb = callback;
450     ah->autofill_error_info_data = user_data;
451
452     return AUTOFILL_ERROR_NONE;
453 }
454
455 EXPORT_API int autofill_error_info_unset_received_cb(autofill_h ah)
456 {
457     if (!ah) {
458         LOGW("[ERROR] Invalid parameter");
459         return AUTOFILL_ERROR_INVALID_PARAMETER;
460     }
461
462     ah->autofill_error_info_received_cb = NULL;
463     ah->autofill_error_info_data = NULL;
464
465     return AUTOFILL_ERROR_NONE;
466 }