2 * Copyright 2013 Samsung Electronics Co., Ltd
4 * Licensed under the Flora License, Version 1.1 (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
8 * http://floralicense.org/license/
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.
22 #include <package-manager.h>
23 #include <dynamicbox_errno.h>
35 enum pkgmgr_event_type type;
36 enum pkgmgr_status status;
40 pkgmgr_client *listen_pc;
43 Eina_List *install_event;
44 Eina_List *uninstall_event;
45 Eina_List *update_event;
46 Eina_List *download_event;
47 Eina_List *recover_event;
52 .install_event = NULL,
53 .uninstall_event = NULL,
55 .download_event = NULL,
56 .recover_event = NULL,
60 int (*cb)(const char *pkgname, enum pkgmgr_status status, double value, void *data);
64 static inline void invoke_install_event_handler(const char *pkgname, enum pkgmgr_status status, double value)
67 struct event_item *item;
69 EINA_LIST_FOREACH(s_info.install_event, l, item) {
71 item->cb(pkgname, status, value, item->data);
76 static inline void invoke_uninstall_event_handler(const char *pkgname, enum pkgmgr_status status, double value)
79 struct event_item *item;
81 EINA_LIST_FOREACH(s_info.uninstall_event, l, item) {
83 item->cb(pkgname, status, value, item->data);
88 static inline void invoke_update_event_handler(const char *pkgname, enum pkgmgr_status status, double value)
91 struct event_item *item;
93 EINA_LIST_FOREACH(s_info.update_event, l, item) {
95 item->cb(pkgname, status, value, item->data);
100 static inline void invoke_download_event_handler(const char *pkgname, enum pkgmgr_status status, double value)
103 struct event_item *item;
105 EINA_LIST_FOREACH(s_info.download_event, l, item) {
107 item->cb(pkgname, status, value, item->data);
112 static inline void invoke_recover_event_handler(const char *pkgname, enum pkgmgr_status status, double value)
115 struct event_item *item;
117 EINA_LIST_FOREACH(s_info.recover_event, l, item) {
119 item->cb(pkgname, status, value, item->data);
124 static inline void invoke_callback(const char *pkgname, struct item *item, double value)
126 switch (item->type) {
127 case PKGMGR_EVENT_DOWNLOAD:
128 invoke_download_event_handler(pkgname, item->status, value);
130 case PKGMGR_EVENT_UNINSTALL:
131 invoke_uninstall_event_handler(pkgname, item->status, value);
133 case PKGMGR_EVENT_INSTALL:
134 invoke_install_event_handler(pkgname, item->status, value);
136 case PKGMGR_EVENT_UPDATE:
137 invoke_update_event_handler(pkgname, item->status, value);
139 case PKGMGR_EVENT_RECOVER:
140 invoke_recover_event_handler(pkgname, item->status, value);
143 ErrPrint("Unknown type: %d\n", item->type);
148 static inline int is_valid_status(struct item *item, const char *status)
150 const char *expected_status;
152 switch (item->type) {
153 case PKGMGR_EVENT_DOWNLOAD:
154 expected_status = "download";
156 case PKGMGR_EVENT_UNINSTALL:
157 expected_status = "uninstall";
159 case PKGMGR_EVENT_INSTALL:
160 expected_status = "install";
162 case PKGMGR_EVENT_UPDATE:
163 expected_status = "update";
165 case PKGMGR_EVENT_RECOVER:
166 expected_status = "recover";
172 return !strcasecmp(status, expected_status);
175 static struct item *find_item(const char *pkgname)
181 ErrPrint("Package name is not valid\n");
185 EINA_LIST_FOREACH(s_info.item_list, l, item) {
186 if (strcmp(item->pkgname, pkgname)) {
193 DbgPrint("Package %s is not found\n", pkgname);
197 static int start_cb(const char *pkgname, const char *val, void *data)
201 DbgPrint("[%s] %s\n", pkgname, val);
203 item = calloc(1, sizeof(*item));
205 ErrPrint("Heap: %s\n", strerror(errno));
206 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
209 item->pkgname = strdup(pkgname);
210 if (!item->pkgname) {
211 ErrPrint("Heap: %s\n", strerror(errno));
213 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
216 item->status = PKGMGR_STATUS_START;
218 if (!strcasecmp(val, "download")) {
219 item->type = PKGMGR_EVENT_DOWNLOAD;
220 } else if (!strcasecmp(val, "uninstall")) {
221 item->type = PKGMGR_EVENT_UNINSTALL;
222 } else if (!strcasecmp(val, "install")) {
223 item->type = PKGMGR_EVENT_INSTALL;
224 } else if (!strcasecmp(val, "update")) {
225 item->type = PKGMGR_EVENT_UPDATE;
226 } else if (!strcasecmp(val, "recover")) {
227 item->type = PKGMGR_EVENT_RECOVER;
229 DbgFree(item->pkgname);
231 ErrPrint("Invalid val: %s\n", val);
232 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
235 s_info.item_list = eina_list_append(s_info.item_list, item);
237 invoke_callback(pkgname, item, 0.0f);
238 return DBOX_STATUS_ERROR_NONE;
241 static int icon_path_cb(const char *pkgname, const char *val, void *data)
245 DbgPrint("[%s] %s\n", pkgname, val);
247 item = find_item(pkgname);
249 return DBOX_STATUS_ERROR_NOT_EXIST;
256 item->icon = strdup(val);
258 ErrPrint("Heap: %s\n", strerror(errno));
259 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
262 return DBOX_STATUS_ERROR_NONE;
265 static int command_cb(const char *pkgname, const char *val, void *data)
269 DbgPrint("[%s] %s\n", pkgname, val);
271 item = find_item(pkgname);
273 return DBOX_STATUS_ERROR_NOT_EXIST;
276 if (!is_valid_status(item, val)) {
277 DbgPrint("Invalid status: %d, %s\n", item->type, val);
278 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
281 item->status = PKGMGR_STATUS_COMMAND;
282 invoke_callback(pkgname, item, 0.0f);
283 return DBOX_STATUS_ERROR_NONE;
286 static int error_cb(const char *pkgname, const char *val, void *data)
291 DbgPrint("[%s] %s\n", pkgname, val);
293 item = find_item(pkgname);
295 return DBOX_STATUS_ERROR_NOT_EXIST;
298 item->status = PKGMGR_STATUS_ERROR;
299 invoke_callback(pkgname, item, 0.0f);
300 return DBOX_STATUS_ERROR_NONE;
303 static int change_pkgname_cb(const char *pkgname, const char *val, void *data)
308 DbgPrint("[%s] %s\n", pkgname, val);
310 item = find_item(pkgname);
312 return DBOX_STATUS_ERROR_NOT_EXIST;
315 new_pkgname = strdup(val);
317 ErrPrint("Heap: %s\n", strerror(errno));
318 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
321 DbgFree(item->pkgname);
322 item->pkgname = new_pkgname;
323 return DBOX_STATUS_ERROR_NONE;
326 static int download_cb(const char *pkgname, const char *val, void *data)
332 DbgPrint("[%s] %s\n", pkgname, val);
334 item = find_item(pkgname);
336 DbgPrint("ITEM is not started from the start_cb\n");
337 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
340 if (item->type != PKGMGR_EVENT_DOWNLOAD) {
341 DbgPrint("TYPE is not \"download\" : %d\n", item->type);
342 item->type = PKGMGR_EVENT_DOWNLOAD;
345 switch (item->status) {
346 case PKGMGR_STATUS_START:
347 case PKGMGR_STATUS_COMMAND:
348 item->status = PKGMGR_STATUS_PROCESSING;
349 case PKGMGR_STATUS_PROCESSING:
352 ErrPrint("Invalid state [%s, %s]\n", pkgname, val);
353 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
357 if (sscanf(val, "%lf", &value) != 1) {
358 value = (double)DBOX_STATUS_ERROR_INVALID_PARAMETER;
361 value = (double)DBOX_STATUS_ERROR_INVALID_PARAMETER;
364 invoke_download_event_handler(pkgname, item->status, value);
365 return DBOX_STATUS_ERROR_NONE;
368 static int progress_cb(const char *pkgname, const char *val, void *data)
374 DbgPrint("[%s] %s\n", pkgname, val);
376 item = find_item(pkgname);
378 ErrPrint("ITEM is not started from the start_cb\n");
379 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
382 switch (item->status) {
383 case PKGMGR_STATUS_START:
384 case PKGMGR_STATUS_COMMAND:
385 item->status = PKGMGR_STATUS_PROCESSING;
386 case PKGMGR_STATUS_PROCESSING:
389 ErrPrint("Invalid state [%s, %s]\n", pkgname, val);
390 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
394 if (sscanf(val, "%lf", &value) != 1) {
395 value = (double)DBOX_STATUS_ERROR_INVALID_PARAMETER;
398 value = (double)DBOX_STATUS_ERROR_INVALID_PARAMETER;
401 invoke_callback(pkgname, item, value);
402 return DBOX_STATUS_ERROR_NONE;
405 static int end_cb(const char *pkgname, const char *val, void *data)
409 DbgPrint("[%s] %s\n", pkgname, val);
411 item = find_item(pkgname);
413 return DBOX_STATUS_ERROR_NOT_EXIST;
416 item->status = !strcasecmp(val, "ok") ? PKGMGR_STATUS_END : PKGMGR_STATUS_ERROR;
418 invoke_callback(pkgname, item, 0.0f);
420 s_info.item_list = eina_list_remove(s_info.item_list, item);
422 DbgFree(item->pkgname);
424 return DBOX_STATUS_ERROR_NONE;
427 static struct pkgmgr_handler {
429 int (*func)(const char *package, const char *val, void *data);
431 { "install_percent", progress_cb },
432 { "download_percent", download_cb },
433 { "start", start_cb },
435 { "change_pkg_name", change_pkgname_cb },
436 { "icon_path", icon_path_cb },
437 { "command", command_cb },
438 { "error", error_cb },
442 static int pkgmgr_cb(int req_id, const char *type, const char *pkgname, const char *key, const char *val, const void *pmsg, void *data)
447 for (i = 0; handler[i].key; i++) {
448 if (strcasecmp(key, handler[i].key)) {
452 ret = handler[i].func(pkgname, val, data);
454 DbgPrint("REQ[%d] pkgname[%s], type[%s], key[%s], val[%s], ret = %d\n",
455 req_id, pkgname, type, key, val, ret);
459 return DBOX_STATUS_ERROR_NONE;
462 HAPI int pkgmgr_init(void)
464 if (s_info.listen_pc) {
465 return DBOX_STATUS_ERROR_ALREADY;
468 s_info.listen_pc = pkgmgr_client_new(PC_LISTENING);
469 if (!s_info.listen_pc) {
470 return DBOX_STATUS_ERROR_FAULT;
473 if (pkgmgr_client_listen_status(s_info.listen_pc, pkgmgr_cb, NULL) != PKGMGR_R_OK) {
474 return DBOX_STATUS_ERROR_FAULT;
477 return DBOX_STATUS_ERROR_NONE;
480 HAPI int pkgmgr_fini(void)
482 struct event_item *item;
485 if (!s_info.listen_pc) {
486 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
489 if (pkgmgr_client_free(s_info.listen_pc) != PKGMGR_R_OK) {
490 return DBOX_STATUS_ERROR_FAULT;
493 s_info.listen_pc = NULL;
495 EINA_LIST_FREE(s_info.download_event, item) {
499 EINA_LIST_FREE(s_info.uninstall_event, item) {
503 EINA_LIST_FREE(s_info.install_event, item) {
507 EINA_LIST_FREE(s_info.update_event, item) {
511 EINA_LIST_FREE(s_info.recover_event, item) {
515 EINA_LIST_FREE(s_info.item_list, ctx) {
516 DbgFree(ctx->pkgname);
521 return DBOX_STATUS_ERROR_NONE;
524 HAPI int pkgmgr_add_event_callback(enum pkgmgr_event_type type, int (*cb)(const char *pkgname, enum pkgmgr_status status, double value, void *data), void *data)
526 struct event_item *item;
528 item = calloc(1, sizeof(*item));
530 ErrPrint("Heap: %s\n", strerror(errno));
531 return DBOX_STATUS_ERROR_OUT_OF_MEMORY;
538 case PKGMGR_EVENT_DOWNLOAD:
539 s_info.download_event = eina_list_prepend(s_info.download_event, item);
541 case PKGMGR_EVENT_UNINSTALL:
542 s_info.uninstall_event = eina_list_prepend(s_info.uninstall_event, item);
544 case PKGMGR_EVENT_INSTALL:
545 s_info.install_event = eina_list_prepend(s_info.install_event, item);
547 case PKGMGR_EVENT_UPDATE:
548 s_info.update_event = eina_list_prepend(s_info.update_event, item);
550 case PKGMGR_EVENT_RECOVER:
551 s_info.recover_event = eina_list_prepend(s_info.recover_event, item);
555 return DBOX_STATUS_ERROR_INVALID_PARAMETER;
558 return DBOX_STATUS_ERROR_NONE;
561 HAPI void *pkgmgr_del_event_callback(enum pkgmgr_event_type type, int (*cb)(const char *pkgname, enum pkgmgr_status status, double value, void *data), void *data)
563 struct event_item *item;
568 case PKGMGR_EVENT_DOWNLOAD:
569 EINA_LIST_FOREACH(s_info.download_event, l, item) {
570 if (item->cb == cb && item->data == data) {
571 s_info.download_event = eina_list_remove(s_info.download_event, item);
578 case PKGMGR_EVENT_UNINSTALL:
579 EINA_LIST_FOREACH(s_info.uninstall_event, l, item) {
580 if (item->cb == cb && item->data == data) {
581 s_info.uninstall_event = eina_list_remove(s_info.uninstall_event, item);
588 case PKGMGR_EVENT_INSTALL:
589 EINA_LIST_FOREACH(s_info.install_event, l, item) {
590 if (item->cb == cb && item->data == data) {
591 s_info.install_event = eina_list_remove(s_info.install_event, item);
598 case PKGMGR_EVENT_UPDATE:
599 EINA_LIST_FOREACH(s_info.update_event, l, item) {
600 if (item->cb == cb && item->data == data) {
601 s_info.update_event = eina_list_remove(s_info.update_event, item);
608 case PKGMGR_EVENT_RECOVER:
609 EINA_LIST_FOREACH(s_info.recover_event, l, item) {
610 if (item->cb == cb && item->data == data) {
611 s_info.recover_event = eina_list_remove(s_info.recover_event, item);
619 ErrPrint("Invalid type\n");