tizen 2.3.1 release
[apps/home/installer.git] / installer_service / src / installer-service.c
1 /*
2  * Copyright (c) 2000 - 2011 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 <unistd.h>
19 #include <dlog.h>
20 #include <service_app.h>
21 #include <string.h>
22 #include <stdlib.h>
23
24 #include <aul.h>
25 #include <bundle.h>
26 #include <errno.h>
27
28 #include <appsvc.h>
29 #include <notification.h>
30 #include <notification_internal.h>
31
32 #include <pkgmgr-info.h>
33 #include <package-manager.h>
34 #include <package-manager-types.h>
35
36 #include "installer-service.h"
37
38 #define KEY_PACKAGE_LABEL               "__KEY_PACKAGE_LABEL__"
39 #define KEY_PACKAGE_PATH                "__KEY_PACKAGE_PATH__"
40 #define KEY_PACKAGE_ICON_PATH   "__KEY_PACKAGE_ICON_PATH__"
41
42 static const char DEFAULT_ICON[] = "/usr/apps/org.tizen.installer/shared/res/org.tizen.installer.png";
43
44 typedef struct _appdata
45 {
46         char *file_path;
47         char *pkg_label;
48         char *pkg_icon_path;
49 } appdata;
50
51 pkgmgr_client *__pc;
52 int __priv_id;
53
54 static char * __get_file_extension(const char *file_path)
55 {
56         return strrchr(file_path, '.') + 1;
57 }
58
59 static int __get_pkg_mainappid(const char *pkgid, char **mainappid)
60 {
61         int res = 0;
62         char *appid = NULL;
63         pkgmgrinfo_pkginfo_h handle;
64         res = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
65         if (res != PMINFO_R_OK)
66         {
67                 LOGE("%s pkgmgrinfo_pkginfo_get_pkginfo() failed.(%d)", __func__, res);
68                 return -1;
69         }
70         res = pkgmgrinfo_pkginfo_get_mainappid(handle, &appid);
71         if (res != PMINFO_R_OK)
72         {
73                 LOGE("%s pkgmgrinfo_pkginfo_get_mainappid() failed.(%d)", __func__, res);
74                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
75                 return -1;
76         }
77         *mainappid = strdup(appid);
78         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
79
80         return 0;
81 }
82
83 static int __get_pkg_icon(const char *pkgid, char **pkg_icon_path)
84 {
85         int res = 0;
86         char *icon = NULL;
87         pkgmgrinfo_pkginfo_h handle;
88         res = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
89         if (res != PMINFO_R_OK)
90         {
91                 LOGE("%s pkgmgrinfo_pkginfo_get_pkginfo() failed.(%d)", __func__, res);
92                 return -1;
93         }
94         res = pkgmgrinfo_pkginfo_get_icon(handle, &icon);
95         if (res != PMINFO_R_OK)
96         {
97                 LOGE("%s pkgmgrinfo_pkginfo_get_icon() failed.(%d)", __func__, res);
98                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
99                 return -1;
100         }
101
102         if (icon == NULL)
103         {
104                 LOGE("%s icon is NULL.(%d)", __func__, res);
105                 pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
106                 return -1;
107         }
108
109         *pkg_icon_path = strdup(icon);
110         pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
111
112         return 0;
113 }
114
115 int __notify_notification(const char *pkg_id, const char *pkg_label, const char *pkg_icon_path, bool result)
116 {
117         notification_h noti_h = NULL;
118         notification_error_e noti_err = NOTIFICATION_ERROR_NONE;
119
120         noti_h = notification_create(NOTIFICATION_TYPE_NOTI);
121         if (noti_h == NULL)
122         {
123                 LOGE("%s notification_create() failed.", __func__);
124                 return -1;
125         }
126
127         if(result)
128         {
129                 noti_err = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_TITLE, "Installation completed.", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
130         }
131         else
132         {
133                 noti_err = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_TITLE, "Installation failed.", NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
134         }
135
136         if (noti_err != NOTIFICATION_ERROR_NONE)
137         {
138                 LOGE("%s notification_set_text() failed.(%d)", __func__, noti_err);
139                 notification_free(noti_h);
140                 return -1;
141         }
142
143         noti_err = notification_set_text(noti_h, NOTIFICATION_TEXT_TYPE_CONTENT, pkg_label, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
144         if (noti_err != NOTIFICATION_ERROR_NONE)
145         {
146                 LOGE("%s notification_set_ ... failed.(%d)", __func__, noti_err);
147                 notification_free(noti_h);
148                 return -1;
149         }
150
151         noti_err = notification_set_image(noti_h, NOTIFICATION_IMAGE_TYPE_ICON, pkg_icon_path);
152         if (noti_err != NOTIFICATION_ERROR_NONE)
153         {
154                 LOGE("%s notification_set_image(icon) failed.(%d)", __func__, noti_err);
155                 notification_free(noti_h);
156                 return -1;
157         }
158
159         noti_err = notification_set_image(noti_h, NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR, pkg_icon_path);
160         if (noti_err != NOTIFICATION_ERROR_NONE)
161         {
162                 LOGE("%s notification_set_image(indicator) failed.(%d)", __func__, noti_err);
163                 notification_free(noti_h);
164                 return -1;
165         }
166
167         //TODO: Add sound state checking routine.
168         noti_err = notification_set_sound(noti_h, NOTIFICATION_SOUND_TYPE_DEFAULT, NULL);
169         if (noti_err != NOTIFICATION_ERROR_NONE)
170         {
171                 LOGE("%s notification_set_sound() failed.(%d)", __func__, noti_err);
172                 notification_free(noti_h);
173                 return -1;
174         }
175
176         //TODO: Add vibration state checking routine.
177         noti_err = notification_set_vibration(noti_h, NOTIFICATION_VIBRATION_TYPE_DEFAULT, NULL);
178         if (noti_err != NOTIFICATION_ERROR_NONE)
179         {
180                 LOGE("%s notification_set_vibration() failed.(%d)", __func__, noti_err);
181                 notification_free(noti_h);
182                 return -1;
183         }
184
185         // App launch
186         char *mainappid = NULL;
187         int res = 0;
188         res = __get_pkg_mainappid(pkg_id, &mainappid);
189         if (res < 0)
190         {
191                 LOGE("%s __get_pkg_mainappid() failed.(%d)", __func__, res);
192         }
193         SECURE_LOGI("%s launch pkg_id: %s, mainappid: %s", __func__, pkg_id, mainappid);
194
195         bundle *b = NULL;
196         b = bundle_create();
197         if (b == NULL)
198         {
199                 LOGE("%s bundle_create() failed.", __func__);
200                 notification_free(noti_h);
201                 free(mainappid);
202                 return -1;
203         }
204         appsvc_set_operation(b, "http://tizen.org/appcontrol/operation/view");
205         appsvc_set_appid(b, mainappid);
206         noti_err = notification_set_execute_option(noti_h, NOTIFICATION_EXECUTE_TYPE_SINGLE_LAUNCH, NULL, NULL, b);
207
208         if (b)
209         {
210                 bundle_free(b);
211         }
212
213         if (noti_err != NOTIFICATION_ERROR_NONE)
214         {
215                 LOGE("%s notification_set_execute_option() failed.", __func__);
216                 notification_free(noti_h);
217                 free(mainappid);
218                 return -1;
219         }
220         free(mainappid);
221
222         noti_err = notification_insert(noti_h, &__priv_id);
223         if (noti_err != NOTIFICATION_ERROR_NONE)
224         {
225                 LOGE("%s notification_insert() failed.(%d)", __func__, noti_err);
226                 notification_free(noti_h);
227
228                 return -1;
229         }
230
231 /*
232         noti_err = notification_update(noti_h);
233         if (noti_err != NOTIFICATION_ERROR_NONE)
234         {
235                 LOGE("%s notification_update() failed.(%d)", __func__, noti_err);
236                 notification_free(noti_h);
237                 return -1;
238         }
239 */
240         return 0;
241 }
242
243
244 int _install_cb(int req_id, const char *pkg_type,
245                                 const char *pkgid, const char *key,
246                                 const char *val, const void *pmsg, void *data)
247 {
248         LOGD("%s pkgmgr_handler()", __func__);
249
250         appdata *ad = (appdata *)data;
251         bool result = true;
252
253         if (strcmp(key, "start") == 0)
254         {
255                 char str[256];
256                 snprintf(str, 256, "installing %s.%s ..", pkgid, pkg_type);
257                 notification_status_message_post(str);
258         }
259         else if (strcmp(key, "install_percent") == 0)
260         {
261         //TODO: percent bar
262                 int percent = atoi(val);
263                 notification_update_progress(NULL, __priv_id, (double)(percent/100));
264         }
265         else if (strcmp(key, "end") == 0)
266         {
267                 if(strcasecmp(val,"fail") == 0){
268                         result = false;
269                 }
270                 SECURE_LOGD("pkg_type(%s), pkgid(%s), key(%s), val(%s), label(%s), icon_path(%s) result(%d)"
271                         , pkg_type, pkgid, key, val, ad->pkg_label, ad->pkg_icon_path, result);
272
273                 char *pkg_icon_path = NULL;
274                 int res = __get_pkg_icon(pkgid, &pkg_icon_path);
275                 if (res < 0)
276                 {
277                         pkg_icon_path = strdup(DEFAULT_ICON);
278                 }
279
280                 res = __notify_notification(pkgid, ad->pkg_label, pkg_icon_path, result);
281                 if (res < 0)
282                 {
283                         LOGE("%s __notify_notification() failed.(%d)", __func__, res);
284                         free(pkg_icon_path);
285                         return -1;
286                 }
287
288                 if (__pc)
289                 {
290                         int request_id = pkgmgr_client_free(__pc);
291                         if (request_id < 0)
292                         {
293                                 LOGE("%s pkgmgr_client_free() failed.(%d)", __func__, request_id);
294                                 free(pkg_icon_path);
295                                 return -1;
296                         }
297                 }
298                 if (pkg_icon_path)
299                 {
300                         free(pkg_icon_path);
301                 }
302
303                 service_app_exit();
304         }
305         return 0;
306 }
307
308 int __install_package(const appdata *ad)
309 {
310         if (ad->file_path == NULL)
311         {
312                 LOGE("%s file_path is NULL", __func__);
313                 return -1;
314         }
315         if (ad->pkg_label == NULL)
316         {
317                 LOGE("%s pkg_label is NULL", __func__);
318                 return -1;
319         }
320         LOGD("%s Install file_path[%s] pkg_label[%s] ", __func__, ad->file_path, ad->pkg_label);
321
322         int request_id = 0;
323         char *extension = NULL;
324
325         __pc = pkgmgr_client_new(PC_REQUEST);
326         if (__pc == NULL)
327         {
328                 LOGE("%s pkgmgr_client_new(PC_REQUEST) failed", __func__);
329         }
330
331         extension = __get_file_extension(ad->file_path);
332         LOGD("%s Install extension = [%s]", __func__, extension);
333
334         request_id = pkgmgr_client_install(__pc, extension, NULL, ad->file_path, NULL,
335                                 PM_QUIET, _install_cb, (void *)ad);
336         if (request_id < 0)
337         {
338             LOGE("%s pkgmgr_client_isntall fail(%d)", __func__, request_id);
339                 return -1;
340         }
341
342         return 0;
343 }
344
345
346 static int __parse_argv(int argc, char **argv, appdata *ad)
347 {
348         LOGD("%s", __func__);
349         static bundle *b = NULL;
350         if (b)
351         {
352                 bundle_free(b);
353         }
354
355         b = bundle_import_from_argv(argc, argv);
356         if (b == NULL)
357         {
358                 LOGD("%s bundle for bundle_import_from_argv is NULL", __func__);
359         }
360
361         errno = 0;
362         if (bundle_get_val(b, KEY_PACKAGE_PATH))
363         {
364                 ad->file_path = (char *)bundle_get_val(b, KEY_PACKAGE_PATH);
365         }
366         if (bundle_get_val(b, KEY_PACKAGE_LABEL))
367         {
368                 ad->pkg_label = (char *)bundle_get_val(b, KEY_PACKAGE_LABEL);
369         }
370         if (bundle_get_val(b, KEY_PACKAGE_ICON_PATH))
371         {
372                 ad->pkg_icon_path = (char *)bundle_get_val(b, KEY_PACKAGE_ICON_PATH);
373         }
374
375         if (errno)
376         {
377                 LOGE("%s errno: %d(%s)", __func__, errno, strerror(errno));
378                 return -1;
379         }
380         return 0;
381 }
382
383
384 static bool __service_create(void* data)
385 {
386         return true;
387 }
388
389 static void __service_terminate(void* data)
390 {
391         LOGD("%s", __func__);
392         return;
393 }
394
395 static void __service_control(app_control_h app_control, void* data)
396 {
397         appdata *ad = (appdata *)data;
398         int res = 0;
399
400         res = __install_package(ad);
401         if (res < 0)
402         {
403                 LOGE("%s __install_package() failed.(%d)", __func__, res);
404                 service_app_exit();
405         }
406
407         return;
408 }
409
410 int main(int argc, char* argv[])
411 {
412         LOGD("service_app_main() is called");
413
414         appdata ad = {0,};
415         service_app_lifecycle_callback_s callback = {0,};
416
417         callback.create                 = __service_create;
418         callback.terminate              = __service_terminate;
419         callback.app_control    = __service_control;
420
421         if (__parse_argv(argc, argv, &ad))
422         {
423                 LOGE("%s Failed to parse argv()", __func__);
424                 return -1;
425         }
426
427         return service_app_main(argc, argv, &callback, &ad);
428 }