[Release] wrt_0.8.166 for tizen_2.1 branch
[platform/framework/web/wrt.git] / src / wrt-launchpad-daemon / include / launchpad_util.h
1 /*
2  * Copyright (c) 2013 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  * @file    launchpad_util.h
18  * @author  Tae-Jeong Lee (taejeong.lee@samsung.com)
19  * @version 0.1
20  * @brief   Api library to support launchpad operation.
21  */
22
23 #ifndef __LAUNCHPAD_UTIL_H_
24 #define __LAUNCHPAD_UTIL_H_
25
26 #include <aul.h>
27 #include <bundle.h>
28 #include <privilege-control.h>
29 #include <sys/prctl.h>
30
31 #include "config.h"
32 #include "gl.h"
33 #include "app_sock.h"
34 #include "menu_db_util.h"
35 #include "simple_util.h"
36 #include "access_control.h"
37
38 #define _static_ static inline
39 #define WRT_AUL_PR_NAME 16
40 #define PKG_ID_LENGTH   11
41 #define SDK_CODE_COVERAGE "CODE_COVERAGE"
42 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
43 #define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so"
44 #define PATH_APP_ROOT "/opt/usr/apps"
45 #define PATH_DATA "/data"
46
47 // Prototype
48 _static_ char** __create_argc_argv(bundle * kb, int *margc);
49 _static_ void   __set_sdk_env(app_info_from_db* menu_info, char* str);
50 _static_ int    __parser(const char *arg, char *out, int out_size);
51 _static_ void   __modify_bundle(bundle * kb, int caller_pid, app_info_from_db * menu_info, int cmd);
52 _static_ void   __set_oom();
53 _static_ void   __set_env(app_info_from_db * menu_info, bundle * kb);
54 _static_ int    __wrt_prepare_exec(const char *pkg_name, const char *app_path, app_info_from_db * menu_info, bundle * kb);
55 _static_ void   __wrt_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv);
56
57 // Implementation
58
59 _static_ char** __create_argc_argv(bundle * kb, int *margc)
60 {
61     char **argv;
62     int argc;
63
64     argc = bundle_export_to_argv(kb, &argv);
65
66     *margc = argc;
67     return argv;
68 }
69
70 _static_ void __set_sdk_env(app_info_from_db* menu_info, char* str)
71 {
72     char buf[MAX_LOCAL_BUFSZ];
73     int ret;
74
75     _D("key : %s / value : %s", AUL_K_SDK, str);
76     /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
77     /* GCOV_PREFIX contains the prefix to add to the absolute paths in the
78      *object file. */
79     /*          Prefix can be absolute, or relative. The default is no prefix.
80      * */
81     /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
82     /*          to stripoff the hardwired absolute paths. Default value is 0. */
83     if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
84         snprintf(buf,
85                  MAX_LOCAL_BUFSZ,
86                  PATH_APP_ROOT "/%s"PATH_DATA,
87                  _get_pkgname(menu_info));
88         ret = setenv("GCOV_PREFIX", buf, 1);
89         _D("GCOV_PREFIX : %d", ret);
90         ret = setenv("GCOV_PREFIX_STRIP", "4096", 1);
91         _D("GCOV_PREFIX_STRIP : %d", ret);
92     } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
93         ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
94         _D("LD_PRELOAD : %d", ret);
95     }
96 }
97
98
99 /*
100  * Parsing original app path to retrieve default bundle
101  *
102  * -1 : Invalid sequence
103  * -2 : Buffer overflow
104  *
105  */
106 _static_ int __parser(const char *arg, char *out, int out_size)
107 {
108     register int i;
109     int state = 1;
110     char *start_out = out;
111
112     if (arg == NULL || out == NULL) {
113         /* Handles null buffer*/
114         return 0;
115     }
116
117     for (i = 0; out_size > 1; i++) {
118         switch (state) {
119         case 1:
120             switch (arg[i]) {
121             case ' ':
122             case '\t':
123                 state = 5;
124                 break;
125             case '\0':
126                 state = 7;
127                 break;
128             case '\"':
129                 state = 2;
130                 break;
131             case '\\':
132                 state = 4;
133                 break;
134             default:
135                 *out = arg[i];
136                 out++;
137                 out_size--;
138                 break;
139             }
140             break;
141         case 2:         /* escape start*/
142             switch (arg[i]) {
143             case '\0':
144                 state = 6;
145                 break;
146             case '\"':
147                 state = 1;
148                 break;
149             default:
150                 *out = arg[i];
151                 out++;
152                 out_size--;
153                 break;
154             }
155             break;
156         case 4:         /* character escape*/
157             if (arg[i] == '\0') {
158                 state = 6;
159             } else {
160                 *out = arg[i];
161                 out++;
162                 out_size--;
163                 state = 1;
164             }
165             break;
166         case 5:         /* token*/
167             if (out != start_out) {
168                 *out = '\0';
169                 out_size--;
170                 return i;
171             }
172             i--;
173             state = 1;
174             break;
175         case 6:
176             return -1;                  /* error*/
177         case 7:         /* terminate*/
178             *out = '\0';
179             out_size--;
180             return 0;
181         default:
182             state = 6;
183             break;              /* error*/
184         }
185     }
186
187     if (out_size == 1) {
188         *out = '\0';
189     }
190     /* Buffer overflow*/
191     return -2;
192 }
193
194
195 _static_ void __modify_bundle(bundle * kb, int caller_pid,
196                               app_info_from_db * menu_info, int cmd)
197 {
198     // warning: unused parameter
199     caller_pid = caller_pid;
200
201     bundle_del(kb, AUL_K_PKG_NAME);
202     bundle_del(kb, AUL_K_EXEC);
203     bundle_del(kb, AUL_K_PACKAGETYPE);
204     bundle_del(kb, AUL_K_HWACC);
205
206     /* Parse app_path to retrieve default bundle*/
207     if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd ==
208         APP_RESUME)
209     {
210         char *ptr;
211         char exe[MAX_PATH_LEN];
212         int flag;
213
214         ptr = _get_original_app_path(menu_info);
215
216         flag = __parser(ptr, exe, sizeof(exe));
217         if (flag > 0) {
218             char key[256];
219             char value[256];
220
221             ptr += flag;
222             _D("parsing app_path: EXEC - %s\n", exe);
223
224             do {
225                 flag = __parser(ptr, key, sizeof(key));
226                 if (flag <= 0) {
227                     break;
228                 }
229                 ptr += flag;
230
231                 flag = __parser(ptr, value, sizeof(value));
232                 if (flag < 0) {
233                     break;
234                 }
235                 ptr += flag;
236
237                 /*bundle_del(kb, key);*/
238                 bundle_add(kb, key, value);
239             } while (flag > 0);
240         } else if (flag == 0) {
241             _D("parsing app_path: No arguments\n");
242         } else {
243             _D("parsing app_path: Invalid argument\n");
244         }
245     }
246 }
247
248
249 _static_ void __set_oom()
250 {
251     char buf[MAX_LOCAL_BUFSZ];
252     FILE *fp;
253
254     /* we should reset oomadj value as default because child
255      * inherits from parent oom_adj*/
256     snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
257     fp = fopen(buf, "w");
258     if (fp == NULL) {
259         return;
260     }
261     fprintf(fp, "%d", -16);
262     fclose(fp);
263 }
264
265 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
266 {
267     const char *str;
268     const char **str_array;
269     int len;
270     int i;
271
272     setenv("PKG_NAME", _get_pkgname(menu_info), 1);
273
274     USE_ENGINE("gl")
275
276     str = bundle_get_val(kb, AUL_K_STARTTIME);
277     if (str != NULL) {
278         setenv("APP_START_TIME", str, 1);
279     }
280
281     if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
282         str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
283         if (str_array != NULL) {
284             for (i = 0; i < len; i++) {
285                 _D("index : [%d]", i);
286                 __set_sdk_env(menu_info, (char *)str_array[i]);
287             }
288         }
289     } else {
290         str = bundle_get_val(kb, AUL_K_SDK);
291         if (str != NULL) {
292             __set_sdk_env(menu_info, (char *)str);
293         }
294     }
295     if (menu_info->hwacc != NULL) {
296         setenv("HWACC", menu_info->hwacc, 1);
297     }
298 }
299
300 _static_ int __wrt_prepare_exec(const char *pkg_name,
301                             const char *app_path, app_info_from_db * menu_info,
302                             bundle * kb)
303 {
304     const char *file_name;
305     char process_name[WRT_AUL_PR_NAME];
306
307     /* SET PRIVILEGES*/
308     char pkg_id[PKG_ID_LENGTH];
309     memset(pkg_id, '\0', PKG_ID_LENGTH);
310     snprintf(pkg_id, PKG_ID_LENGTH, "%s", pkg_name);
311
312     if (__set_access(pkg_id, menu_info->pkg_type, app_path) < 0) {
313         _D("fail to set privileges - check your package's credential\n");
314         return -1;
315     }
316
317     /* SET PROCESS NAME*/
318     if (app_path == NULL) {
319         _D("app_path should not be NULL - check menu db");
320         return -1;
321     }
322     file_name = strrchr(app_path, '/') + 1;
323     if (file_name == NULL) {
324         _D("can't locate file name to execute");
325         return -1;
326     }
327     memset(process_name, '\0', WRT_AUL_PR_NAME);
328     snprintf(process_name, WRT_AUL_PR_NAME, "%s", file_name);
329     prctl(PR_SET_NAME, process_name);
330
331     /* SET ENVIROMENT*/
332     __set_env(menu_info, kb);
333
334     return 0;
335 }
336
337 _static_ void __wrt_launchpad_main_loop(app_pkt_t* pkt, char* out_app_path, int* out_argc, char ***out_argv)
338
339 {
340     bundle *kb = NULL;
341     app_info_from_db *menu_info = NULL;
342
343     const char *pkg_name = NULL;
344     const char *app_path = NULL;
345     struct ucred cr;
346
347     kb = bundle_decode(pkt->data, pkt->len);
348     if (!kb) {
349         _E("bundle decode error");
350         exit(-1);
351     }
352
353     pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
354     _D("pkg name : %s", pkg_name);
355
356     menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
357     if (menu_info == NULL) {
358         _D("such pkg no found");
359         exit(-1);
360     }
361
362     app_path = _get_app_path(menu_info);
363
364     if (app_path == NULL) {
365         _E("app_path is NULL");
366         exit(-1);
367     }
368
369     if (app_path[0] != '/') {
370         _E("app_path is not absolute path");
371         exit(-1);
372     }
373
374     __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
375     pkg_name = _get_pkgname(menu_info);
376     _D("pkg name : %s", pkg_name);
377
378     __wrt_prepare_exec(pkg_name, app_path, menu_info, kb);
379
380     if (out_app_path != NULL && out_argc != NULL && out_argv != NULL)
381     {
382         int i;
383
384         sprintf(out_app_path, "%s", app_path);
385
386         *out_argv = __create_argc_argv(kb, out_argc);
387         (*out_argv)[0] = out_app_path;
388
389         for (i = 0; i < *out_argc; i++)
390         {
391             _D("input argument %d : %s##", i, (*out_argv)[i]);
392         }
393     }
394     else
395     {
396         exit(-1);
397     }
398
399
400 #if 0 // intentional
401     if (menu_info != NULL) {
402         _free_app_info_from_db(menu_info);
403     }
404
405     if (kb != NULL) {
406         bundle_free(kb);
407     }
408 #endif
409 }
410
411 #endif // __LAUNCHPAD_UTIL_H_