Fix a wrong implementation
[platform/core/appfw/aul-1.git] / src / widget.c
1 /*
2  * Copyright (c) 2000 - 2015 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the License);
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an AS IS BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #define _GNU_SOURCE
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <stdbool.h>
21 #include <string.h>
22 #include <ctype.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <glib.h>
27 #include <bundle.h>
28 #include <bundle_internal.h>
29
30 #include "aul.h"
31 #include "aul_util.h"
32 #include "aul_sock.h"
33 #include "aul_cmd.h"
34 #include "aul_error.h"
35 #include "launch.h"
36 #include "aul_widget.h"
37
38 struct aul_widget_info_s {
39         char *widget_id;
40         char *instance_id;
41         char *app_id;
42         char *package_id;
43         char *app_path;
44         unsigned int surf;
45         pid_t pid;
46 };
47
48 struct widget_cb_info {
49         aul_widget_info_cb callback;
50         void *user_data;
51 };
52
53 #define WIDGET_LOG_BUFFER_SIZE 10000
54 #define WIDGET_LOG_BUFFER_STRING_SIZE 256
55
56 static int __log_index;
57 static int __log_fd;
58 static bool __log_init = false;
59
60 static int __init_log(void)
61 {
62         int offset;
63         char buffer[256] = {0, };
64         char caller[255] = {0, };
65         int ret;
66
67         ret = aul_app_get_appid_bypid(getpid(), caller, sizeof(caller));
68         if (ret != AUL_R_OK) {
69                 _E("Failed to get appid by pid(%d)", getpid());
70                 return -1;
71         }
72
73         snprintf(buffer, sizeof(buffer),
74                         "/run/aul/log/widget/%d/widget_%s.log", getuid(), caller);
75         __log_fd = open(buffer, O_CREAT | O_WRONLY, 0644);
76         if (__log_fd < 0) {
77                 _E("Failed to open %s - %d", buffer, errno);
78                 return -1;
79         }
80
81         offset = lseek(__log_fd, 0, SEEK_END);
82         if (offset != 0) {
83                 __log_index = (int)(offset / WIDGET_LOG_BUFFER_STRING_SIZE);
84                 if (__log_index >= WIDGET_LOG_BUFFER_SIZE) {
85                         __log_index = 0;
86                         lseek(__log_fd, 0, SEEK_SET);
87                 }
88         }
89         __log_init = true;
90
91         return 0;
92 }
93
94 API int aul_widget_write_log(const char *tag, const char *format, ...)
95 {
96         int ret;
97         int offset;
98         time_t now;
99         char time_buf[32] = {0,};
100         char format_buffer[WIDGET_LOG_BUFFER_STRING_SIZE];
101         char buffer[WIDGET_LOG_BUFFER_STRING_SIZE];
102         va_list ap;
103
104         if (!__log_init)
105                 __init_log();
106
107         if (__log_fd < 0) {
108                 _E("Invalid file descriptor");
109                 return -1;
110         }
111
112         time(&now);
113         ctime_r(&now, time_buf);
114         if (__log_index != 0)
115                 offset = lseek(__log_fd, 0, SEEK_CUR);
116         else
117                 offset = lseek(__log_fd, 0, SEEK_SET);
118
119         if (offset == -1)
120                 _E("error in lseek: %d", errno);
121
122
123         va_start(ap, format);
124         vsnprintf(format_buffer, sizeof(format_buffer), format, ap);
125         va_end(ap);
126
127         snprintf(buffer, sizeof(buffer), "[%-6d][%-5d] %-15s %-50s %s",
128                         getpid(), __log_index, tag, format_buffer, time_buf);
129
130         ret = write(__log_fd, buffer, strlen(buffer));
131         if (ret < 0) {
132                 _E("Cannot write the amd log: %d", ret);
133                 return -1;
134         }
135
136         if (++__log_index >= WIDGET_LOG_BUFFER_SIZE)
137                 __log_index = 0;
138
139         return 0;
140 }
141
142 static const char *__to_appid(const char *widget_id)
143 {
144         const char *appid;
145         appid = g_strstr_len(widget_id, strlen(widget_id), "@") + 1;
146         if (appid != (const char *)1) {
147                 if (appid > widget_id + (sizeof(char) * strlen(widget_id)))
148                         appid = (char *)widget_id;
149         } else {
150                 appid = (char *)widget_id;
151         }
152
153         return appid;
154 }
155
156 API int aul_widget_instance_add(const char *widget_id, const char *instance_id)
157 {
158         int ret;
159         bundle *kb;
160
161         if (widget_id == NULL || instance_id == NULL)
162                 return AUL_R_EINVAL;
163
164         kb = bundle_create();
165         if (kb == NULL) {
166                 _E("out of memory");
167                 return AUL_R_ERROR;
168         }
169
170         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
171         bundle_add_str(kb, AUL_K_WIDGET_INSTANCE_ID, instance_id);
172
173         ret = aul_sock_send_bundle(AUL_UTIL_PID, getuid(), WIDGET_ADD, kb,
174                 AUL_SOCK_NONE);
175
176         bundle_free(kb);
177         if (ret < 0)
178                 return aul_error_convert(ret);
179
180         return AUL_R_OK;
181 }
182
183 API int aul_widget_instance_del(const char *widget_id, const char *instance_id)
184 {
185         int ret;
186         bundle *kb;
187
188         if (widget_id == NULL || instance_id == NULL)
189                 return AUL_R_EINVAL;
190
191         kb = bundle_create();
192         if (kb == NULL) {
193                 _E("out of memory");
194                 return AUL_R_ERROR;
195         }
196
197         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
198         bundle_add_str(kb, AUL_K_WIDGET_INSTANCE_ID, instance_id);
199
200         ret = aul_sock_send_bundle(AUL_UTIL_PID, getuid(), WIDGET_DEL, kb,
201                 AUL_SOCK_NONE);
202
203         bundle_free(kb);
204         if (ret < 0)
205                 return aul_error_convert(ret);
206
207         return AUL_R_OK;
208 }
209
210 struct __cb_data {
211         aul_widget_instance_foreach_cb cb;
212         void *data;
213 };
214
215 static void __foreach_cb(const char *key, const int type,
216                 const bundle_keyval_t *kv, void *user_data)
217 {
218         struct __cb_data *cb_data = (struct __cb_data *)user_data;
219
220         cb_data->cb(key, cb_data->data);
221 }
222
223 API int aul_widget_instance_foreach(const char *widget_id,
224                 aul_widget_instance_foreach_cb cb, void *data)
225 {
226         int ret;
227         int fd;
228         bundle *kb;
229         app_pkt_t *pkt = NULL;
230         bundle *list_kb = NULL;
231         struct __cb_data cb_data;
232
233         if (widget_id == NULL)
234                 return AUL_R_EINVAL;
235
236         kb = bundle_create();
237         if (kb == NULL) {
238                 _E("out of memory");
239                 return AUL_R_ERROR;
240         }
241
242         bundle_add_str(kb, AUL_K_APPID, __to_appid(widget_id));
243         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
244
245         fd = aul_sock_send_bundle(AUL_UTIL_PID, getuid(), WIDGET_LIST, kb,
246                 AUL_SOCK_ASYNC);
247
248         if (fd > 0) {
249                 ret = aul_sock_recv_reply_pkt(fd, &pkt);
250                 if (ret < 0 || pkt == NULL) {
251                         _E("failed to get instance list of %s", widget_id);
252                 } else {
253                         list_kb = bundle_decode(pkt->data, pkt->len);
254                         if (list_kb) {
255                                 cb_data.cb = cb;
256                                 cb_data.data = data;
257                                 bundle_foreach(list_kb, __foreach_cb, &cb_data);
258                                 bundle_free(list_kb);
259                         }
260                 }
261         } else {
262                 ret = fd;
263         }
264
265         if (pkt)
266                 free(pkt);
267
268         bundle_free(kb);
269
270         if (ret < 0)
271                 return aul_error_convert(ret);
272
273         return AUL_R_OK;
274 }
275
276 API int aul_widget_instance_update(const char *widget_id,
277                 const char *instance_id, bundle *param)
278 {
279         int ret;
280         bundle *kb = param;
281         const char *appid;
282
283         if (widget_id == NULL)
284                 return AUL_R_EINVAL;
285
286         if (kb == NULL)
287                 kb = bundle_create();
288
289         if (kb == NULL) {
290                 _E("out of memory");
291                 return AUL_R_ERROR;
292         }
293
294         appid = __to_appid(widget_id);
295
296         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
297
298         if (instance_id)
299                 bundle_add_str(kb, AUL_K_WIDGET_INSTANCE_ID, instance_id);
300
301         ret = app_request_to_launchpad_for_uid(WIDGET_UPDATE, appid, kb,
302                         getuid());
303
304         if (param == NULL)
305                 bundle_free(kb);
306
307         return ret;
308 }
309
310 API int aul_widget_instance_get_content(const char *widget_id,
311                 const char *instance_id, char **content)
312 {
313         int ret;
314         bundle *kb;
315         int fd[2] = { 0, };
316         app_pkt_t *pkt = NULL;
317
318         if (widget_id == NULL || instance_id == NULL || content == NULL)
319                 return AUL_R_EINVAL;
320
321         kb = bundle_create();
322         if (kb == NULL) {
323                 _E("out of memory");
324                 return AUL_R_ERROR;
325         }
326
327         bundle_add_str(kb, AUL_K_APPID, __to_appid(widget_id));
328         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
329         bundle_add_str(kb, AUL_K_WIDGET_INSTANCE_ID, instance_id);
330
331         ret = aul_sock_send_bundle(AUL_UTIL_PID, getuid(), WIDGET_GET_CONTENT,
332                         kb, AUL_SOCK_ASYNC);
333         if (ret > 0) {
334                 ret = aul_sock_recv_reply_sock_fd(ret, &fd, 1);
335                 if (ret == 0) {
336                         ret = aul_sock_recv_reply_pkt(fd[0], &pkt);
337                         if (ret == 0 && pkt && pkt->cmd == 0) {
338                                 *content = strdup((const char *)pkt->data);
339                                 _D("recieved content: %s", *content);
340                         } else {
341                                 if (pkt)
342                                         ret = pkt->cmd;
343
344                                 _E("failed to get content");
345                         }
346                 } else {
347                         _E("failed to get socket fd:%d", ret);
348                 }
349         }
350
351         bundle_free(kb);
352
353         if (pkt)
354                 free(pkt);
355         if (ret < 0)
356                 ret = aul_error_convert(ret);
357
358         return ret;
359 }
360
361 API int aul_widget_instance_count(const char *widget_id)
362 {
363         int ret;
364         bundle *kb;
365
366         if (widget_id == NULL)
367                 return AUL_R_EINVAL;
368
369         kb = bundle_create();
370         if (kb == NULL) {
371                 _E("out of memory");
372                 return AUL_R_ERROR;
373         }
374
375         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
376         ret = app_send_cmd(AUL_UTIL_PID, WIDGET_COUNT, kb);
377         bundle_free(kb);
378
379         return ret;
380 }
381
382 static void __foreach_widget_info(app_pkt_t *pkt, void *user_data)
383 {
384         struct widget_cb_info *cb_info = (struct widget_cb_info *)user_data;
385         struct aul_widget_info_s info = { 0, };
386         bundle *b = NULL;
387         const char *val;
388
389         if (pkt == NULL || cb_info == NULL) {
390                 _E("Invalid parameter");
391                 return;
392         }
393
394         if (pkt->cmd == APP_GET_INFO_ERROR) {
395                 _E("Failed to get widget info");
396                 return;
397         }
398
399         if (pkt->opt & AUL_SOCK_BUNDLE)
400                 b = bundle_decode(pkt->data, pkt->len);
401
402         if (b == NULL)
403                 return;
404
405         bundle_get_str(b, AUL_K_WIDGET_ID, &info.widget_id);
406         if (info.widget_id == NULL) {
407                 bundle_free(b);
408                 return;
409         }
410
411         bundle_get_str(b, AUL_K_WIDGET_INSTANCE_ID, &info.instance_id);
412         if (info.instance_id == NULL) {
413                 bundle_free(b);
414                 return;
415         }
416
417         bundle_get_str(b, AUL_K_APPID, &info.app_id);
418         if (info.app_id == NULL) {
419                 bundle_free(b);
420                 return;
421         }
422
423         bundle_get_str(b, AUL_K_PKGID, &info.package_id);
424         if (info.package_id == NULL) {
425                 bundle_free(b);
426                 return;
427         }
428
429         bundle_get_str(b, AUL_K_EXEC, &info.app_path);
430         if (info.app_path == NULL) {
431                 bundle_free(b);
432                 return;
433         }
434
435         val = bundle_get_val(b, AUL_K_WID);
436         if (val && isdigit(*val))
437                 info.surf = strtoul(val, NULL, 10);
438
439         val = bundle_get_val(b, AUL_K_PID);
440         if (val && isdigit(*val))
441                 info.pid = atoi(val);
442
443         cb_info->callback(&info, cb_info->user_data);
444
445         bundle_free(b);
446 }
447
448 API int aul_widget_info_foreach_for_uid(aul_widget_info_cb callback,
449                 void *user_data, uid_t uid)
450 {
451         struct widget_cb_info cb_info = {callback, user_data};
452         char buf[MAX_PID_STR_BUFSZ];
453         bundle *b;
454         int fd;
455         int r;
456
457         if (callback == NULL) {
458                 _E("Invalid parameter");
459                 return AUL_R_EINVAL;
460         }
461
462         b = bundle_create();
463         if (b == NULL) {
464                 _E("Out of memory");
465                 return AUL_R_ERROR;
466         }
467
468         snprintf(buf, sizeof(buf), "%u", uid);
469         r = bundle_add_str(b, AUL_K_TARGET_UID, buf);
470         if (r != BUNDLE_ERROR_NONE) {
471                 _E("Failed to add target uid(%u)", uid);
472                 bundle_free(b);
473                 return AUL_R_ERROR;
474         }
475
476         fd = aul_sock_send_bundle(AUL_UTIL_PID, uid, WIDGET_RUNNING_INFO,
477                         b, AUL_SOCK_ASYNC);
478         if (fd < 0) {
479                 bundle_free(b);
480                 return aul_error_convert(fd);
481         }
482         bundle_free(b);
483
484         r = aul_sock_recv_pkt_with_cb(fd, __foreach_widget_info, &cb_info);
485         if (r < 0)
486                 return aul_error_convert(r);
487
488         return AUL_R_OK;
489 }
490
491 API int aul_widget_info_foreach(aul_widget_info_cb callback, void *user_data)
492 {
493         return aul_widget_info_foreach_for_uid(callback, user_data, getuid());
494 }
495
496 API int aul_widget_info_get_pid(aul_widget_info_h info, pid_t *pid)
497 {
498         if (info == NULL || pid == NULL) {
499                 _E("Invalid parameter");
500                 return AUL_R_EINVAL;
501         }
502
503         *pid = info->pid;
504
505         return AUL_R_OK;
506 }
507
508 API int aul_widget_info_get_surface_id(aul_widget_info_h info,
509                 unsigned int *surf)
510 {
511         if (info == NULL || surf == NULL) {
512                 _E("Invalid parameter");
513                 return AUL_R_EINVAL;
514         }
515
516         *surf = info->surf;
517
518         return AUL_R_OK;
519 }
520
521 API int aul_widget_info_get_widget_id(aul_widget_info_h info, char **widget_id)
522 {
523         if (info == NULL || widget_id == NULL) {
524                 _E("Invalid parameter");
525                 return AUL_R_EINVAL;
526         }
527
528         *widget_id = strdup(info->widget_id);
529         if (*widget_id == NULL) {
530                 _E("Out of memory");
531                 return AUL_R_ERROR;
532         }
533
534         return AUL_R_OK;
535 }
536
537 API int aul_widget_info_get_instance_id(aul_widget_info_h info,
538                 char **instance_id)
539 {
540         if (info == NULL || instance_id == NULL) {
541                 _E("Invalid parameter");
542                 return AUL_R_EINVAL;
543         }
544
545         *instance_id = strdup(info->instance_id);
546         if (*instance_id == NULL) {
547                 _E("Out of memory");
548                 return AUL_R_ERROR;
549         }
550
551         return AUL_R_OK;
552 }
553
554 API int aul_widget_info_get_app_id(aul_widget_info_h info, char **app_id)
555 {
556         if (info == NULL || app_id == NULL) {
557                 _E("Invalid parameter");
558                 return AUL_R_EINVAL;
559         }
560
561         *app_id = strdup(info->app_id);
562         if (*app_id == NULL) {
563                 _E("Out of memory");
564                 return AUL_R_ERROR;
565         }
566
567         return AUL_R_OK;
568 }
569
570 API int aul_widget_info_get_package_id(aul_widget_info_h info,
571                 char **package_id)
572 {
573         if (info == NULL || package_id == NULL) {
574                 _E("Invalid parameter");
575                 return AUL_R_EINVAL;
576         }
577
578         *package_id = strdup(info->package_id);
579         if (*package_id == NULL) {
580                 _E("Out of memory");
581                 return AUL_R_ERROR;
582         }
583
584         return AUL_R_OK;
585 }
586
587 API int aul_widget_info_get_app_path(aul_widget_info_h info, char **app_path)
588 {
589         if (info == NULL || app_path == NULL) {
590                 _E("Invalid parameter");
591                 return AUL_R_EINVAL;
592         }
593
594         *app_path = strdup(info->app_path);
595         if (*app_path == NULL) {
596                 _E("Out of memory");
597                 return AUL_R_ERROR;
598         }
599
600         return AUL_R_OK;
601 }
602
603 API int aul_widget_instance_change_status(const char *widget_id,
604                 const char *status)
605 {
606         int ret;
607         bundle *kb;
608
609         kb = bundle_create();
610         if (kb == NULL) {
611                 _E("out of memory");
612                 return AUL_R_ERROR;
613         }
614
615         bundle_add_str(kb, AUL_K_STATUS, status);
616         bundle_add_str(kb, AUL_K_WIDGET_ID, widget_id);
617         ret = aul_sock_send_bundle(AUL_UTIL_PID, getuid(),
618                         WIDGET_CHANGE_STATUS, kb, AUL_SOCK_NOREPLY);
619
620         bundle_free(kb);
621         if (ret < 0) {
622                 _E("send error %d, %s", ret, status);
623                 return aul_error_convert(ret);
624         }
625
626         return AUL_R_OK;
627 }