Moved procfs for app lifecycle to plugin and separate plugins
[platform/core/connectivity/stc-manager.git] / plugin / exception / stc-plugin-exception.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
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 <errno.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <syspopup_caller.h>
22 #include <bundle.h>
23 #include <bundle_internal.h>
24 #include <dlog.h>
25 #include <gio/gio.h>
26 #include <pkgmgr-info.h>
27
28 #include "stc-plugin-exception.h"
29
30 #define EXE_TYPE_APPLICATION "app"
31 #define EXE_TYPE_INSTRUCTION "inst"
32 #define EXE_TYPE_SYSTEM      "sys"
33 #define EXE_TYPE_SCRIPT      "script"
34
35 /* 1 day */
36 #define EXCNS_TIMER_INTERVAL 86400
37
38 #define EXCEPTION_BUF_MAX   64
39 #define EXCEPTION_STORAGE   "/var/lib/stc/exceptions"
40
41 #define INTERNET_PRIVILEGE  "http://tizen.org/privilege/internet"
42
43 typedef struct {
44         char *process_name;
45         char *exe_type;
46 } stc_exceptions_info;
47
48 typedef stc_cb_ret_e
49 (*stc_exceptions_info_cb)(const stc_exceptions_info *info,
50                               void *user_data);
51
52 static GHashTable *g_excns_hash;  /**< exception hash table */
53 static GHashTable *g_pkginfo_filter_hash;
54 static guint g_excns_timer_id;
55
56 static int __pkginfo_filter_list_cb(pkgmgrinfo_pkginfo_h handle, void *user_data)
57 {
58         int ret = 0;
59         char *pkgname = NULL;
60
61         ret = pkgmgrinfo_pkginfo_get_pkgname(handle, &pkgname);
62         if (ret == PMINFO_R_OK) {
63                 if (g_hash_table_insert(g_pkginfo_filter_hash,
64                                 g_strdup(pkgname), g_strdup(EXE_TYPE_APPLICATION)) != TRUE)
65                         STC_LOGE("Failed to insert hash table");
66         }
67
68         return STC_CONTINUE;
69 }
70
71 static int __pkginfo_pkg_list_cb(pkgmgrinfo_pkginfo_h handle, void *user_data)
72 {
73         int ret = 0;
74         char *pkgname = NULL;
75         char *exe_type = NULL;
76         stc_exceptions_info data;
77         const stc_exceptions_info_cb excn_cb = user_data;
78
79         ret = pkgmgrinfo_pkginfo_get_pkgname(handle, &pkgname);
80         if (ret == PMINFO_R_OK) {
81                 exe_type = g_hash_table_lookup(g_pkginfo_filter_hash, pkgname);
82                 if (exe_type)
83                         return STC_CONTINUE;
84
85                 data.process_name = pkgname;
86                 data.exe_type = EXE_TYPE_APPLICATION;
87
88                 if (excn_cb(&data, NULL) == STC_CANCEL)
89                         STC_LOGE("Failed to insert hash table");
90         }
91
92         return STC_CONTINUE;
93 }
94
95 static void __excn_hash_foreach_print(gpointer key, gpointer value,
96                                           gpointer data)
97 {
98         const char *process_name = key;
99         const char *exe_type = value;
100
101         STC_LOGI("excn info => process_name [%s] exe_type [%s]",
102                 process_name, exe_type);
103 }
104
105 static void __excn_hash_printall(void)
106 {
107         g_hash_table_foreach(g_excns_hash,
108                 __excn_hash_foreach_print, NULL);
109 }
110
111 static gboolean __remove_exception_app(gpointer key, gpointer value,
112                                         gpointer data)
113 {
114         const char *exe_type = value;
115
116         if (g_strcmp0(exe_type, EXE_TYPE_APPLICATION) == 0)
117                 return TRUE;
118
119         return FALSE;
120 }
121
122 static void __remove_exception_appall(void)
123 {
124         g_hash_table_foreach_remove(g_excns_hash,
125                 __remove_exception_app, NULL);
126 }
127
128 static stc_cb_ret_e __insert_exception_cb(const stc_exceptions_info *info,
129                                             void *user_data)
130 {
131         stc_cb_ret_e ret = STC_CONTINUE;
132
133         if (g_hash_table_insert(g_excns_hash,
134                         g_strdup(info->process_name),
135                         g_strdup(info->exe_type)) != TRUE)
136                 ret = STC_CANCEL;
137
138         return ret;
139 }
140
141 static gboolean __update_exceptions_app_list(void *user_data)
142 {
143         stc_plugin_exception_update_list();
144         return TRUE;
145 }
146
147 static stc_error_e pkginfo_exceptions_foreach(const stc_exceptions_info_cb exception_cb,
148                                        void *user_data)
149 {
150         int ret = 0;
151         int err = STC_ERROR_NONE;
152         pkgmgrinfo_pkginfo_filter_h handle;
153
154         g_pkginfo_filter_hash = g_hash_table_new_full(g_str_hash,
155                                                 g_str_equal, g_free, g_free);
156
157         ret = pkgmgrinfo_pkginfo_filter_create(&handle);
158         ret_value_msg_if(ret != PMINFO_R_OK, STC_ERROR_FAIL,
159                         "Failed to create pkginfo filter");
160
161         ret = pkgmgrinfo_pkginfo_filter_add_string(handle,
162                         PMINFO_PKGINFO_PROP_PACKAGE_PRIVILEGE,
163                         INTERNET_PRIVILEGE);
164         if (ret != PMINFO_R_OK) {
165                 STC_LOGE("Failed to add pkginfo filter string");
166                 err = STC_ERROR_FAIL;
167                 goto out;
168         }
169
170         ret = pkgmgrinfo_pkginfo_filter_foreach_pkginfo(handle,
171                         __pkginfo_filter_list_cb, NULL);
172         if (ret != PMINFO_R_OK) {
173                 STC_LOGE("Failed to foreach pkginfo filter");
174                 err = STC_ERROR_FAIL;
175                 goto out;
176         }
177
178         ret = pkgmgrinfo_pkginfo_get_list(__pkginfo_pkg_list_cb, exception_cb);
179         if (ret != PMINFO_R_OK) {
180                 STC_LOGE("Failed to get pkginfo list");
181                 err = STC_ERROR_FAIL;
182                 goto out;
183         }
184
185 out:
186         if (g_pkginfo_filter_hash) {
187                 g_hash_table_destroy(g_pkginfo_filter_hash);
188                 g_pkginfo_filter_hash = NULL;
189         }
190
191         if (handle)
192                 pkgmgrinfo_pkginfo_filter_destroy(handle);
193
194         return err;
195 }
196
197 static stc_error_e table_exceptions_foreach(const stc_exceptions_info_cb exception_cb,
198                                        void *user_data)
199 {
200         stc_error_e error_code = STC_ERROR_NONE;
201         stc_exceptions_info data;
202
203         FILE *fp = NULL;
204         char buf[EXCEPTION_BUF_MAX] = {0, };
205
206         fp = fopen(EXCEPTION_STORAGE, "r");
207         ret_value_msg_if(!fp, STC_ERROR_FAIL, "Failed to open %s file");
208
209         while (fgets(buf, sizeof(buf), fp) != NULL) {
210                 char *process_name, *exe_type;
211                 char *save_ptr = NULL;
212
213                 process_name = strtok_r(buf, ":", &save_ptr);
214                 if (process_name != NULL)
215                         data.process_name = process_name;
216                 else
217                         data.process_name = "none";
218
219                 exe_type = strtok_r(NULL, "\n", &save_ptr);
220                 if (exe_type != NULL)
221                         data.exe_type = exe_type;
222                 else
223                         data.exe_type = "none";
224
225                 if (exception_cb(&data, user_data) == STC_CANCEL)
226                         break;
227         }
228         fclose(fp);
229
230         return error_code;
231 }
232
233 int stc_plugin_exception_initialize(void)
234 {
235         g_excns_hash = g_hash_table_new_full(g_str_hash,
236                                         g_str_equal, g_free, g_free);
237
238         return STC_ERROR_NONE;
239 }
240
241 int stc_plugin_exception_deinitialize(void)
242 {
243         if (g_excns_timer_id > 0) {
244                 g_source_remove(g_excns_timer_id);
245                 g_excns_timer_id = 0;
246         }
247
248         g_hash_table_destroy(g_excns_hash);
249
250         return STC_ERROR_NONE;
251 }
252
253 int stc_plugin_exception_fill_list(void)
254 {
255         table_exceptions_foreach(__insert_exception_cb, NULL);
256         pkginfo_exceptions_foreach(__insert_exception_cb, NULL);
257
258         if (STC_DEBUG_LOG)
259                 __excn_hash_printall();
260
261         g_excns_timer_id = g_timeout_add_seconds(EXCNS_TIMER_INTERVAL,
262                         __update_exceptions_app_list,
263                         NULL);
264
265         return STC_ERROR_NONE;
266 }
267
268 int stc_plugin_exception_update_list(void)
269 {
270         __remove_exception_appall();
271         pkginfo_exceptions_foreach(__insert_exception_cb, NULL);
272
273         if (STC_DEBUG_LOG)
274                 __excn_hash_printall();
275
276         return STC_ERROR_NONE;
277 }
278
279 int stc_plugin_exception_check_by_cmdline(char *cmdline)
280 {
281         char *exe_type = NULL;
282
283         exe_type = g_hash_table_lookup(g_excns_hash, cmdline);
284         if (!exe_type)
285                 return STC_ERROR_NO_DATA;
286
287         return STC_ERROR_NONE;
288 }
289
290 API stc_plugin_exception_s stc_plugin_exception = {
291         .initialize_plugin =
292                 stc_plugin_exception_initialize,
293         .deinitialize_plugin =
294                 stc_plugin_exception_deinitialize,
295         .fill_exception_list =
296                 stc_plugin_exception_fill_list,
297         .update_exception_list =
298                 stc_plugin_exception_update_list,
299         .check_exception_by_cmdline =
300                 stc_plugin_exception_check_by_cmdline
301 };