Review the "handler" handling codes.
authorSung-jae Park <nicesj.park@samsung.com>
Sat, 26 May 2012 05:17:20 +0000 (14:17 +0900)
committerSung-jae Park <nicesj.park@samsung.com>
Sat, 26 May 2012 05:29:51 +0000 (14:29 +0900)
Add codes for handling more various cases about the API usage.
And check the resource leak.

Change-Id: I2876fff8c5ce77028f10d06573ecc0155e7390b9

include/livebox0.h
src/dbus.c
src/livebox.c

index 7ffef76..01a7300 100644 (file)
@@ -1,10 +1,10 @@
 extern int lb_set_group(struct livebox *handler, const char *cluster, const char *category);
-extern int lb_set_size(struct livebox *handler, int w, int h);
-extern int lb_set_pdsize(struct livebox *handler, int w, int h);
-extern int lb_invoke_event_handler(struct livebox *handler, const char *event);
-extern int lb_invoke_fault_handler(const char *event, const char *pkgname, const char *filename, const char *function);
+extern void lb_set_size(struct livebox *handler, int w, int h);
+extern void lb_set_pdsize(struct livebox *handler, int w, int h);
+extern void lb_invoke_event_handler(struct livebox *handler, const char *event);
+extern void lb_invoke_fault_handler(const char *event, const char *pkgname, const char *filename, const char *function);
 extern int lb_set_content(struct livebox *handler, const char *content);
-extern int lb_set_auto_launch(struct livebox *handler, int auto_launch);
+extern void lb_set_auto_launch(struct livebox *handler, int auto_launch);
 extern struct livebox *lb_find_livebox(const char *pkgname, const char *filename);
 extern struct livebox *lb_new_livebox(const char *pkgname, const char *filename);
 extern struct livebox *lb_find_livebox_by_timestamp(double timestamp);
@@ -24,8 +24,18 @@ extern void lb_set_text_pd(struct livebox *handler, int flag);
 extern int lb_text_lb(struct livebox *handler);
 extern int lb_text_pd(struct livebox *handler);
 extern void lb_set_period(struct livebox *handler, double period);
+extern void lb_ref(struct livebox *handler);
+extern void lb_unref(struct livebox *handler);
+extern int lb_send_delete(struct livebox *handler);
 
 struct livebox {
+       int refcnt;
+       enum {
+               NOT_DELETED = 0x0,
+               DELETE_THIS = 0x01, /* Delete only for this client */
+               DELETE_ALL = 0x02, /* Delete for all clients */
+       } deleted;
+
        char *cluster;
        char *category;
 
index 5cf7518..1112422 100644 (file)
@@ -102,19 +102,13 @@ GDBusProxy *dbus_get_proxy(void)
 
 static inline int send_acquire(void)
 {
-       GVariant *param;
+       GVariant *result;
        GError *err;
 
-       param = g_variant_new("(i)", getpid());
-       if (!param) {
-               ErrPrint("Failed to create variant\n");
-               return -EFAULT;
-       }
-
        err = NULL;
-       param = g_dbus_proxy_call_sync(s_info.proxy, "acquire", param,
+       result = g_dbus_proxy_call_sync(s_info.proxy, "acquire", g_variant_new("(i)", getpid()),
                                        G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &err);
-       if (!param) {
+       if (!result) {
                if (err) {
                        ErrPrint("Error: %s\n", err->message);
                        g_error_free(err);
@@ -124,25 +118,20 @@ static inline int send_acquire(void)
                return -EIO;
        }
 
+       g_variant_unref(result);
        return 0;
 }
 
 static inline int send_release(void)
 {
-       GVariant *param;
+       GVariant *result;
        GError *err;
 
-       param = g_variant_new("(i)", getpid());
-       if (!param) {
-               ErrPrint("Failed to create variant\n");
-               return -EFAULT;
-       }
-
        err = NULL;
-       param = g_dbus_proxy_call_sync(s_info.proxy, "release", param,
+       result = g_dbus_proxy_call_sync(s_info.proxy, "release", g_variant_new("(i)", getpid()),
                                        G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &err);
 
-       if (!param) {
+       if (!result) {
                if (err) {
                        ErrPrint("Error: %s\n", err->message);
                        g_error_free(err);
@@ -151,6 +140,7 @@ static inline int send_release(void)
                return -EIO;
        }
 
+       g_variant_unref(result);
        return 0;
 }
 
@@ -192,6 +182,8 @@ static void done_cb(GDBusProxy *proxy, GAsyncResult *res, void *data)
                item->ret_cb(item->handler, r, item->data);
 
 out:
+       lb_unref(item->handler);
+       /* Decreate the item->param's refernece counter now. */
        g_variant_unref(item->param);
        free(item->funcname);
        free(item);
@@ -222,6 +214,10 @@ static gboolean cmd_consumer(gpointer user_data)
                /*!
                 * \NOTE:
                 * Item will be deleted in the "done_cb"
+                *
+                * item->param be release by the g_dbus_proxy_call
+                * so to use it again from the done_cb function,
+                * increate the reference counter of the item->param
                 */
                g_dbus_proxy_call(s_info.proxy,
                        item->funcname,
@@ -245,13 +241,12 @@ static void method_fault_package(GDBusMethodInvocation *inv, GVariant *param)
        const char *pkgname;
        const char *filename;
        const char *function;
-       int ret;
 
        g_variant_get(param, "(&s&s&s)", &pkgname, &filename, &function);
 
-       ret = lb_invoke_fault_handler("deactivated", pkgname, filename, function);
+       lb_invoke_fault_handler("deactivated", pkgname, filename, function);
 
-       g_dbus_method_invocation_return_value(inv, g_variant_new("(i)", ret));
+       g_dbus_method_invocation_return_value(inv, g_variant_new("(i)", 0));
 }
 
 static void method_pd_updated(GDBusMethodInvocation *inv, GVariant *param)
@@ -273,6 +268,17 @@ static void method_pd_updated(GDBusMethodInvocation *inv, GVariant *param)
                goto out;
        }
 
+       if (handler->deleted != NOT_DELETED) {
+               /*!
+                * \note
+                * This handler is already deleted by the user.
+                * So don't try to notice anything about this anymore.
+                * Just ignore all events.
+                */
+               ret = 0;
+               goto out;
+       }
+
        DbgPrint("PD is updated [%dx%d]\n", pd_w, pd_h);
        lb_set_pdsize(handler, pd_w, pd_h);
 
@@ -311,6 +317,17 @@ static void method_lb_updated(GDBusMethodInvocation *inv, GVariant *param)
                goto out;
        }
 
+       if (handler->deleted != NOT_DELETED) {
+               /*!
+                * \note
+                * Already deleted by the user.
+                * Don't try to notice anything with this, Just ignore all events
+                * Beacuse the user doesn't wants know about this anymore
+                */
+               ret = 0;
+               goto out;
+       }
+
        lb_set_priority(handler, priority);
        lb_set_size(handler, lb_w, lb_h);
 
@@ -385,6 +402,29 @@ static void method_created(GDBusMethodInvocation *inv, GVariant *param)
                }
        } else {
                lb_set_filename(handler, filename);
+
+               if (handler->deleted != NOT_DELETED) {
+                       /*!
+                        * \note
+                        * before get this created event,
+                        * user delete this already.
+                        * So user doesn't wants to know about this anymore
+                        * just ignore created events
+                        */
+
+                       if (handler->deleted == DELETE_ALL)
+                               lb_send_delete(handler);
+
+                       /*!
+                        * \note
+                        * This will make the method_delete function could not 
+                        * find the handler object if the handler->deleted == DELETE_ALL
+                        * So the method_delete function will return -ENOENT
+                        */
+                       lb_unref(handler);
+                       ret = 0;
+                       goto out;
+               }
        }
 
        lb_set_size(handler, lb_w, lb_h);
@@ -423,6 +463,11 @@ static void method_deleted(GDBusMethodInvocation *inv, GVariant *param)
 
        handler = lb_find_livebox(pkgname, filename);
        if (!handler) {
+               /*!
+                * \note
+                * This can be happens only if the user delete a livebox
+                * right after create it before receive created event.
+                */
                ret = -ENOENT;
                goto out;
        }
@@ -430,7 +475,7 @@ static void method_deleted(GDBusMethodInvocation *inv, GVariant *param)
        lb_invoke_event_handler(handler, "lb,deleted");
 
        /* Just try to delete it, if a user didn't remove it from the live box list */
-       livebox_del(handler, 0);
+       lb_unref(handler);
 
        ret = 0;
 out:
@@ -504,11 +549,8 @@ static inline void register_dbus_object(void)
        GDBusConnection *conn;
 
        conn = g_dbus_proxy_get_connection(s_info.proxy);
-       if (!conn) {
-               g_object_unref(s_info.proxy);
-               s_info.proxy = NULL;
-               return;
-       }
+       if (!conn)
+               goto errout;
 
        err = NULL;
        s_info.node_info = g_dbus_node_info_new_for_xml(s_info.xml_data, &err);
@@ -517,7 +559,7 @@ static inline void register_dbus_object(void)
                        ErrPrint("error - %s\n", err->message);
                        g_error_free(err);
                }
-               return;
+               goto errout;
        }
 
        err = NULL;
@@ -533,12 +575,16 @@ static inline void register_dbus_object(void)
                        g_error_free(err);
                }
 
-               g_object_unref(s_info.proxy);
-               s_info.proxy = NULL;
-               return;
+               goto errout;
        }
 
        DbgPrint("Registered: %d\n", s_info.reg_id);
+       return;
+
+errout:
+       g_object_unref(s_info.proxy);
+       s_info.proxy = NULL;
+       return;
 }
 
 static void got_proxy_cb(GObject *obj, GAsyncResult *res, gpointer user_data)
@@ -572,13 +618,14 @@ static void got_proxy_cb(GObject *obj, GAsyncResult *res, gpointer user_data)
 
 int dbus_sync_command(const char *funcname, GVariant *param)
 {
+       GVariant *result;
        GError *err;
        int ret;
 
        err = NULL;
-       param = g_dbus_proxy_call_sync(s_info.proxy, funcname, param,
+       result = g_dbus_proxy_call_sync(s_info.proxy, funcname, param,
                                        G_DBUS_CALL_FLAGS_NO_AUTO_START, -1, NULL, &err);
-       if (!param) {
+       if (!result) {
                if (err) {
                        ErrPrint("funcname: %s, Error: %s\n", funcname, err->message);
                        g_error_free(err);
@@ -587,8 +634,8 @@ int dbus_sync_command(const char *funcname, GVariant *param)
                return -EIO;
        }
 
-       g_variant_get(param, "(i)", &ret);
-       g_variant_unref(param);
+       g_variant_get(result, "(i)", &ret);
+       g_variant_unref(result);
 
        return ret;
 }
@@ -610,6 +657,8 @@ int dbus_push_command(struct livebox *handler, const char *funcname, GVariant *p
                return -ENOMEM;
        }
 
+       lb_ref(handler);
+
        item->param = param;
        item->handler = handler;
        item->ret_cb = ret_cb;
index f989341..7bbe001 100644 (file)
@@ -43,38 +43,26 @@ struct fault_info {
        void *user_data;
 };
 
-EAPI int livebox_init(void)
-{
-#if defined(FLOG)
-       char filename[BUFSIZ];
-       snprintf(filename, sizeof(filename), "/tmp/%d.box.log", getpid());
-       __file_log_fp = fopen(filename, "w+t");
-       if (!__file_log_fp)
-               __file_log_fp = fdopen(1, "w+t");
-#endif
-
-       dbus_init();
-       return 0;
-}
-
-EAPI int livebox_fini(void)
-{
-       dbus_fini();
-       return 0;
-}
-
 static void event_ret_cb(struct livebox *handler, int ret, void *data)
 {
+       if (handler->deleted != NOT_DELETED)
+               return;
+
        if (ret < 0) {
                lb_invoke_event_handler(handler, "event,ignored");
        } else {
        }
 }
 
-static void period_cb(struct livebox *handler, int ret, void *data)
+static void period_ret_cb(struct livebox *handler, int ret, void *data)
 {
        double *period;
 
+       if (handler->deleted != NOT_DELETED) {
+               free(data);
+               return;
+       }
+
        period = (double *)data;
 
        if (ret < 0) {
@@ -88,15 +76,130 @@ static void period_cb(struct livebox *handler, int ret, void *data)
        free(data);
 }
 
-static void ret_cb(struct livebox *handler, int ret, void *data)
+static void del_ret_cb(struct livebox *handler, int ret, void *data)
 {
+       DbgPrint("Delete request returns %d\n", ret);
+       /*
+       lb_invoke_event_handler(handler, "lb,deleted");
+       livebox_del(handler, 0);
+       */
+}
+
+static void new_ret_cb(struct livebox *handler, int ret, void *data)
+{
+       if (handler->deleted != NOT_DELETED)
+               return;
+
        if (ret < 0) {
+               /*!
+                * \note
+                * It means the current instance is not created,
+                * so user has to know about this.
+                * notice it to user using "deleted" event.
+                */
                lb_invoke_event_handler(handler, "lb,deleted");
-               livebox_del(handler, 0);
+               lb_unref(handler);
+       }
+       /* lb,created will be receive from the master via dbus */
+}
+
+static void pd_created_cb(struct livebox *handler, int ret, void *data)
+{
+       if (handler->deleted != NOT_DELETED)
+               return;
+
+       if (ret != 0) {
+               lb_invoke_event_handler(handler, "pd,create,failed");
+               return;
+       }
+
+       ret = fb_create_buffer(handler->pd_fb);
+       if (ret < 0)
+               ErrPrint("Failed to create a PD buffer\n");
+
+       lb_invoke_event_handler(handler, "pd,created");
+}
+
+static void activated_cb(struct livebox *handler, int ret, void *data)
+{
+       char *pkgname = data;
+
+       if (ret == 0)
+               lb_invoke_fault_handler("activated", pkgname, NULL, NULL);
+       else if (ret == -EINVAL)
+               lb_invoke_fault_handler("invalid,request", pkgname, NULL, NULL);
+       else
+               lb_invoke_fault_handler("activation,failed", pkgname, NULL, NULL);
+
+       free(pkgname);
+}
+
+static void pd_destroy_cb(struct livebox *handler, int ret, void *data)
+{
+       if (handler->deleted != NOT_DELETED)
+               return;
+
+       DbgPrint("destroy_pd returns %d\n", ret);
+       fb_destroy_buffer(handler->pd_fb);
+       lb_invoke_event_handler(handler, "pd,deleted");
+}
+
+static void pinup_done_cb(struct livebox *handler, int ret, void *data)
+{
+       if (handler->deleted != NOT_DELETED)
+               return;
+
+       if (ret != 0) {
+               ErrPrint("Pinup is not changed: %s\n", strerror(ret));
+               lb_invoke_event_handler(handler, "pinup,failed");
        } else {
+               handler->is_pinned_up = (int)data;
+               lb_invoke_event_handler(handler, "pinup,changed");
        }
 }
 
+static inline int send_mouse_event(struct livebox *handler, const char *event, double x, double y)
+{
+       GVariant *param;
+       double timestamp;
+       int ret;
+
+       DbgPrint("Send event [%s] with %lfx%lf\n", event, x, y);
+
+       timestamp = util_get_timestamp();
+       param = g_variant_new("(ssiiddd)", handler->pkgname, handler->filename,
+                                               handler->pd_w, handler->pd_h,
+                                               timestamp, x, y);
+       if (!param)
+               return -EFAULT;
+
+       ret = dbus_push_command(handler, event, param, event_ret_cb, NULL);
+       if (ret < 0)
+               g_variant_unref(param);
+
+       return ret;
+}
+
+EAPI int livebox_init(void)
+{
+#if defined(FLOG)
+       char filename[BUFSIZ];
+       snprintf(filename, sizeof(filename), "/tmp/%d.box.log", getpid());
+       __file_log_fp = fopen(filename, "w+t");
+       if (!__file_log_fp)
+               __file_log_fp = fdopen(1, "w+t");
+#endif
+
+       dbus_init();
+       return 0;
+}
+
+EAPI int livebox_fini(void)
+{
+       dbus_fini();
+       return 0;
+}
+
 EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const char *cluster, const char *category, double period)
 {
        struct livebox *handler;
@@ -156,6 +259,7 @@ EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const
 
        handler->timestamp = util_get_timestamp();
        handler->period = period;
+       lb_ref(handler);
 
        s_info.livebox_list = dlist_append(s_info.livebox_list, handler);
 
@@ -169,7 +273,7 @@ EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const
                return NULL;
        }
 
-       ret = dbus_push_command(handler, "new", param, ret_cb, NULL);
+       ret = dbus_push_command(handler, "new", param, new_ret_cb, NULL);
        if (ret < 0) {
                free(handler->category);
                free(handler->cluster);
@@ -185,6 +289,9 @@ EAPI struct livebox *livebox_add(const char *pkgname, const char *content, const
 
 EAPI double livebox_period(struct livebox *handler)
 {
+       if (!handler || handler->deleted != NOT_DELETED)
+               return 0.0f;
+
        return handler->period;
 }
 
@@ -194,6 +301,9 @@ EAPI int livebox_set_period(struct livebox *handler, double period)
        int ret;
        double *period_heap;
 
+       if (!handler || handler->deleted != NOT_DELETED)
+               return -EINVAL;
+
        if (handler->period == period)
                return 0;
 
@@ -208,7 +318,7 @@ EAPI int livebox_set_period(struct livebox *handler, double period)
        }
 
        *period_heap = period;
-       ret = dbus_push_command(handler, "set_period", param, period_cb, (void *)period_heap);
+       ret = dbus_push_command(handler, "set_period", param, period_ret_cb, (void *)period_heap);
        if (ret < 0) {
                g_variant_unref(param);
                free(period_heap);
@@ -220,45 +330,26 @@ EAPI int livebox_set_period(struct livebox *handler, double period)
 
 EAPI int livebox_del(struct livebox *handler, int server)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
-       if (server) {
-               GVariant *param;
-               int ret;
-
-               param = g_variant_new("(ss)", handler->pkgname, handler->filename);
-               if (!param)
-                       return -EFAULT;
-
-               ret = dbus_push_command(handler, "delete", param, ret_cb, NULL);
-               if (ret < 0) {
-                       g_variant_unref(param);
-                       return ret;
-               }
+       handler->deleted = server ? DELETE_ALL : DELETE_THIS;
 
+       if (!handler->filename) {
+               /*!
+                * \note
+                * The filename is not determined yet.
+                * It means a user didn't receive created event yet.
+                * Then just stop to delete procedure from here.
+                * Because the "created" event handler will release this.
+                */
                return 0;
        }
 
-       dlist_remove_data(s_info.livebox_list, handler);
-
-       free(handler->cluster);
-       free(handler->category);
-       free(handler->filename);
-       free(handler->pkgname);
-
-       if (handler->lb_fb) {
-               fb_destroy_buffer(handler->lb_fb);
-               fb_destroy(handler->lb_fb);
-               handler->lb_fb = NULL;
-       }
-
-       if (handler->pd_fb) {
-               fb_destroy_buffer(handler->pd_fb);
-               fb_destroy(handler->pd_fb);
-               handler->pd_fb = NULL;
-       }
+       if (server)
+               return lb_send_delete(handler);
 
+       lb_unref(handler);
        return 0;
 }
 
@@ -345,7 +436,7 @@ EAPI int livebox_resize(struct livebox *handler, int w, int h)
        GVariant *param;
        int ret;
 
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        param = g_variant_new("(ssii)", handler->pkgname, handler->filename, w, h);
@@ -365,7 +456,7 @@ EAPI int livebox_click(struct livebox *handler, double x, double y)
        double timestamp;
        int ret;
 
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (handler->auto_launch)
@@ -384,29 +475,9 @@ EAPI int livebox_click(struct livebox *handler, double x, double y)
        return ret;
 }
 
-static inline int send_mouse_event(struct livebox *handler, const char *event, double x, double y)
-{
-       GVariant *param;
-       double timestamp;
-       int ret;
-
-       timestamp = util_get_timestamp();
-       param = g_variant_new("(ssiiddd)", handler->pkgname, handler->filename,
-                                               handler->pd_w, handler->pd_h,
-                                               timestamp, x, y);
-       if (!param)
-               return -EFAULT;
-
-       ret = dbus_push_command(handler, event, param, event_ret_cb, NULL);
-       if (ret < 0)
-               g_variant_unref(param);
-
-       return ret;
-}
-
 EAPI int livebox_has_pd(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return !!handler->pd_fb;
@@ -414,46 +485,18 @@ EAPI int livebox_has_pd(struct livebox *handler)
 
 EAPI int livebox_pd_is_created(struct livebox *handler)
 {
-       if (!handler || !handler->pd_fb)
+       if (!handler || !handler->pd_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return fb_is_created(handler->pd_fb);
 }
 
-static void pd_created_cb(struct livebox *handler, int ret, void *data)
-{
-       if (ret != 0) {
-               lb_invoke_event_handler(handler, "pd,create,failed");
-               return;
-       }
-
-       ret = fb_create_buffer(handler->pd_fb);
-       if (ret < 0)
-               ErrPrint("Failed to create a PD buffer\n");
-
-       lb_invoke_event_handler(handler, "pd,created");
-}
-
-static void activated_cb(struct livebox *handler, int ret, void *data)
-{
-       char *pkgname = data;
-
-       if (ret == 0)
-               lb_invoke_fault_handler("activated", pkgname, NULL, NULL);
-       else if (ret == -EINVAL)
-               lb_invoke_fault_handler("invalid,request", pkgname, NULL, NULL);
-       else
-               lb_invoke_fault_handler("activation,failed", pkgname, NULL, NULL);
-
-       free(pkgname);
-}
-
 EAPI int livebox_create_pd(struct livebox *handler)
 {
        GVariant *param;
        int ret;
 
-       if (!handler || !handler->pd_fb)
+       if (!handler || !handler->pd_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (fb_is_created(handler->pd_fb) == 1)
@@ -489,19 +532,12 @@ EAPI int livebox_activate(const char *pkgname)
        return ret;
 }
 
-static void pd_destroy_cb(struct livebox *handler, int ret, void *data)
-{
-       DbgPrint("destroy_pd returns %d\n", ret);
-       fb_destroy_buffer(handler->pd_fb);
-       lb_invoke_event_handler(handler, "pd,deleted");
-}
-
 EAPI int livebox_destroy_pd(struct livebox *handler)
 {
        GVariant *param;
        int ret;
 
-       if (!handler || !handler->pd_fb)
+       if (!handler || !handler->pd_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (fb_is_created(handler->pd_fb) != 1)
@@ -520,7 +556,7 @@ EAPI int livebox_destroy_pd(struct livebox *handler)
 
 EAPI int livebox_pd_mouse_down(struct livebox *handler, double x, double y)
 {
-       if (!handler || !handler->pd_fb)
+       if (!handler || !handler->pd_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return send_mouse_event(handler, "pd_mouse_down", x, y);
@@ -528,7 +564,7 @@ EAPI int livebox_pd_mouse_down(struct livebox *handler, double x, double y)
 
 EAPI int livebox_pd_mouse_up(struct livebox *handler, double x, double y)
 {
-       if (!handler || !handler->pd_fb)
+       if (!handler || !handler->pd_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return send_mouse_event(handler, "pd_mouse_up", x, y);
@@ -536,7 +572,7 @@ EAPI int livebox_pd_mouse_up(struct livebox *handler, double x, double y)
 
 EAPI int livebox_pd_mouse_move(struct livebox *handler, double x, double y)
 {
-       if (!handler || !handler->pd_fb)
+       if (!handler || !handler->pd_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return send_mouse_event(handler, "pd_mouse_move", x, y);
@@ -544,7 +580,7 @@ EAPI int livebox_pd_mouse_move(struct livebox *handler, double x, double y)
 
 EAPI int livebox_livebox_mouse_down(struct livebox *handler, double x, double y)
 {
-       if (!handler || !handler->lb_fb)
+       if (!handler || !handler->lb_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return send_mouse_event(handler, "lb_mouse_down", x, y);
@@ -552,7 +588,7 @@ EAPI int livebox_livebox_mouse_down(struct livebox *handler, double x, double y)
 
 EAPI int livebox_livebox_mouse_up(struct livebox *handler, double x, double y)
 {
-       if (!handler || !handler->lb_fb)
+       if (!handler || !handler->lb_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return send_mouse_event(handler, "lb_mouse_up", x, y);
@@ -560,7 +596,7 @@ EAPI int livebox_livebox_mouse_up(struct livebox *handler, double x, double y)
 
 EAPI int livebox_livebox_mouse_move(struct livebox *handler, double x, double y)
 {
-       if (!handler || !handler->lb_fb)
+       if (!handler || !handler->lb_fb || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return send_mouse_event(handler, "lb_mouse_move", x, y);
@@ -568,7 +604,7 @@ EAPI int livebox_livebox_mouse_move(struct livebox *handler, double x, double y)
 
 EAPI const char *livebox_filename(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return NULL;
 
        return handler->filename;
@@ -579,7 +615,7 @@ EAPI int livebox_get_pdsize(struct livebox *handler, int *w, int *h)
        int _w;
        int _h;
 
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (!w)
@@ -597,7 +633,7 @@ EAPI int livebox_get_size(struct livebox *handler, int *w, int *h)
        int _w;
        int _h;
 
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (!w)
@@ -615,7 +651,7 @@ EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const c
        GVariant *param;
        int ret;
 
-       if (!handler || !cluster || !category)
+       if (!handler || !cluster || !category || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        param = g_variant_new("(ssss)", handler->pkgname, handler->filename, cluster, category);
@@ -631,7 +667,7 @@ EAPI int livebox_set_group(struct livebox *handler, const char *cluster, const c
 
 EAPI int livebox_get_group(struct livebox *handler, char ** const cluster, char ** const category)
 {
-       if (!handler || !cluster || !category)
+       if (!handler || !cluster || !category || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        *cluster = handler->cluster;
@@ -644,7 +680,7 @@ EAPI int livebox_get_supported_sizes(struct livebox *handler, int *cnt, int *w,
        register int i;
        register int j;
 
-       if (!handler || !cnt)
+       if (!handler || !cnt || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        for (j = i = 0; i < NR_OF_SIZE_LIST; i++) {
@@ -666,7 +702,7 @@ EAPI int livebox_get_supported_sizes(struct livebox *handler, int *cnt, int *w,
 
 EAPI const char *livebox_pkgname(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return NULL;
 
        return handler->pkgname;
@@ -674,7 +710,7 @@ EAPI const char *livebox_pkgname(struct livebox *handler)
 
 EAPI double livebox_priority(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return 0.0f;
 
        return handler->priority;
@@ -682,17 +718,19 @@ EAPI double livebox_priority(struct livebox *handler)
 
 EAPI int livebox_delete_cluster(const char *cluster)
 {
+       DbgPrint("Not implemented yet\n");
        return -ENOSYS;
 }
 
 EAPI int livebox_delete_category(const char *cluster, const char *category)
 {
+       DbgPrint("Not implemented yet\n");
        return -ENOSYS;
 }
 
 EAPI int livebox_is_file(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return handler->data_type == FILEDATA;
@@ -700,7 +738,7 @@ EAPI int livebox_is_file(struct livebox *handler)
 
 EAPI int livebox_is_text(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return handler->text_lb;
@@ -708,7 +746,7 @@ EAPI int livebox_is_text(struct livebox *handler)
 
 EAPI int livebox_pd_is_text(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return handler->text_pd;
@@ -716,7 +754,7 @@ EAPI int livebox_pd_is_text(struct livebox *handler)
 
 EAPI int livebox_pd_set_text_handler(struct livebox *handler, struct livebox_script_operators *ops)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        memcpy(&handler->pd_ops, ops, sizeof(*ops));
@@ -725,7 +763,7 @@ EAPI int livebox_pd_set_text_handler(struct livebox *handler, struct livebox_scr
 
 EAPI int livebox_set_text_handler(struct livebox *handler, struct livebox_script_operators *ops)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        memcpy(&handler->ops, ops, sizeof(*ops));
@@ -734,7 +772,7 @@ EAPI int livebox_set_text_handler(struct livebox *handler, struct livebox_script
 
 EAPI void *livebox_fb(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return NULL;
 
        if (handler->data_type == FBDATA)
@@ -745,7 +783,7 @@ EAPI void *livebox_fb(struct livebox *handler)
 
 EAPI void *livebox_pdfb(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return NULL;
 
        return fb_buffer(handler->pd_fb);
@@ -753,7 +791,7 @@ EAPI void *livebox_pdfb(struct livebox *handler)
 
 EAPI int livebox_pdfb_bufsz(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return fb_size(handler->pd_fb);
@@ -761,7 +799,7 @@ EAPI int livebox_pdfb_bufsz(struct livebox *handler)
 
 EAPI int livebox_lbfb_bufsz(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return fb_size(handler->lb_fb);
@@ -769,29 +807,18 @@ EAPI int livebox_lbfb_bufsz(struct livebox *handler)
 
 EAPI int livebox_is_user(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        return handler->is_user;
 }
 
-static void pinup_done_cb(struct livebox *handler, int ret, void *data)
-{
-       if (ret != 0) {
-               ErrPrint("Pinup is not changed: %s\n", strerror(ret));
-               lb_invoke_event_handler(handler, "pinup,failed");
-       } else {
-               handler->is_pinned_up = (int)data;
-               lb_invoke_event_handler(handler, "pinup,changed");
-       }
-}
-
 EAPI int livebox_set_pinup(struct livebox *handler, int flag)
 {
        GVariant *param;
        int ret;
 
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (handler->is_pinned_up == flag)
@@ -810,17 +837,23 @@ EAPI int livebox_set_pinup(struct livebox *handler, int flag)
 
 EAPI int livebox_pinup(struct livebox *handler)
 {
+       if (!handler || handler->deleted != NOT_DELETED)
+               return -EINVAL;
+
        return handler->is_pinned_up;
 }
 
 EAPI int livebox_has_pinup(struct livebox *handler)
 {
+       if (!handler || handler->deleted != NOT_DELETED)
+               return -EINVAL;
+
        return handler->pinup_supported;
 }
 
 EAPI int livebox_set_data(struct livebox *handler, void *data)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        DbgPrint("%p carry data %p\n", handler, data);
@@ -830,7 +863,7 @@ EAPI int livebox_set_data(struct livebox *handler, void *data)
 
 EAPI void *livebox_get_data(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return NULL;
 
        DbgPrint("Get carried data of %p\n", handler);
@@ -852,7 +885,7 @@ EAPI int livebox_is_exists(const char *pkgname)
 
 EAPI const char *livebox_content(struct livebox *handler)
 {
-       if (!handler)
+       if (!handler || handler->deleted != NOT_DELETED)
                return NULL;
 
        return handler->content;
@@ -863,7 +896,7 @@ EAPI int livebox_text_emit_signal(struct livebox *handler, const char *emission,
        GVariant *param;
        int ret;
 
-       if (!handler->text_lb && !handler->text_pd)
+       if (!handler || (!handler->text_lb && !handler->text_pd) || handler->deleted != NOT_DELETED)
                return -EINVAL;
 
        if (!emission)
@@ -912,21 +945,19 @@ int lb_set_group(struct livebox *handler, const char *cluster, const char *categ
        return 0;
 }
 
-int lb_set_size(struct livebox *handler, int w, int h)
+void lb_set_size(struct livebox *handler, int w, int h)
 {
        handler->lb_w = w;
        handler->lb_h = h;
-       return 0;
 }
 
-int lb_set_pdsize(struct livebox *handler, int w, int h)
+void lb_set_pdsize(struct livebox *handler, int w, int h)
 {
        handler->pd_w = w;
        handler->pd_h = h;
-       return 0;
 }
 
-int lb_invoke_fault_handler(const char *event, const char *pkgname, const char *file, const char *func)
+void lb_invoke_fault_handler(const char *event, const char *pkgname, const char *file, const char *func)
 {
        struct dlist *l;
        struct dlist *n;
@@ -936,11 +967,9 @@ int lb_invoke_fault_handler(const char *event, const char *pkgname, const char *
                if (info->handler(event, pkgname, file, func, info->user_data) == EXIT_FAILURE)
                        s_info.fault_list = dlist_remove(s_info.fault_list, l);
        }
-
-       return 0;
 }
 
-int lb_invoke_event_handler(struct livebox *handler, const char *event)
+void lb_invoke_event_handler(struct livebox *handler, const char *event)
 {
        struct dlist *l;
        struct dlist *n;
@@ -950,8 +979,6 @@ int lb_invoke_event_handler(struct livebox *handler, const char *event)
                if (info->handler(handler, event, info->user_data) == EXIT_FAILURE)
                        s_info.event_list = dlist_remove(s_info.event_list, l);
        }
-
-       return 0;
 }
 
 struct livebox *lb_find_livebox(const char *pkgname, const char *filename)
@@ -1033,10 +1060,9 @@ void lb_set_size_list(struct livebox *handler, int size_list)
        handler->size_list = size_list;
 }
 
-int lb_set_auto_launch(struct livebox *handler, int auto_launch)
+void lb_set_auto_launch(struct livebox *handler, int auto_launch)
 {
        handler->auto_launch = auto_launch;
-       return 0;
 }
 
 void lb_set_priority(struct livebox *handler, double priority)
@@ -1058,7 +1084,6 @@ void lb_update_lb_fb(struct livebox *handler, int w, int h)
 {
        int ow;
        int oh;
-       char *filename;
        const char *tmp;
 
        if (!handler)
@@ -1079,21 +1104,14 @@ void lb_update_lb_fb(struct livebox *handler, int w, int h)
                return;
        }
 
-       filename = strdup(tmp);
-       if (!filename) {
-               ErrPrint("Error: %s\n", strerror(errno));
-               return;
-       }
-
        lb_set_size(handler, w, h);
-       lb_set_lb_fb(handler, filename);
+       lb_set_lb_fb(handler, tmp);
 }
 
 void lb_update_pd_fb(struct livebox *handler, int w, int h)
 {
        int ow;
        int oh;
-       char *filename;
        const char *tmp;
        int ret;
 
@@ -1115,16 +1133,9 @@ void lb_update_pd_fb(struct livebox *handler, int w, int h)
                return;
        }
 
-       filename = strdup(tmp);
-       if (!filename) {
-               ErrPrint("Error: %s\n", strerror(errno));
-               return;
-       }
-
+       lb_set_pd_fb(handler, tmp);
        DbgPrint("Create new buffer [%dx%d]\n", w, h);
        lb_set_pdsize(handler, w, h);
-       lb_set_pd_fb(handler, filename);
-       free(filename);
 
        ret = fb_create_buffer(handler->pd_fb);
        if (ret < 0) {
@@ -1230,4 +1241,53 @@ void lb_set_period(struct livebox *handler, double period)
        handler->period = period;
 }
 
+void lb_ref(struct livebox *handler)
+{
+       handler->refcnt++;
+}
+
+void lb_unref(struct livebox *handler)
+{
+       handler->refcnt--;
+       if (handler->refcnt > 0)
+               return;
+
+       dlist_remove_data(s_info.livebox_list, handler);
+
+       free(handler->cluster);
+       free(handler->category);
+       free(handler->filename);
+       free(handler->pkgname);
+
+       if (handler->lb_fb) {
+               fb_destroy_buffer(handler->lb_fb);
+               fb_destroy(handler->lb_fb);
+               handler->lb_fb = NULL;
+       }
+
+       if (handler->pd_fb) {
+               fb_destroy_buffer(handler->pd_fb);
+               fb_destroy(handler->pd_fb);
+               handler->pd_fb = NULL;
+       }
+}
+
+int lb_send_delete(struct livebox *handler)
+{
+       GVariant *param;
+       int ret;
+
+       param = g_variant_new("(ss)", handler->pkgname, handler->filename);
+       if (!param)
+               return -EFAULT;
+
+       ret = dbus_push_command(handler, "delete", param, del_ret_cb, NULL);
+       if (ret < 0) {
+               g_variant_unref(param);
+               return ret;
+       }
+
+       return 0;
+}
+
 /* End of a file */