support eventsystem_keep_last_event_data api 20/77420/8 accepted/tizen/3.0/common/20161114.105411 accepted/tizen/3.0/ivi/20161011.044016 accepted/tizen/3.0/mobile/20161015.033021 accepted/tizen/3.0/tv/20161016.004446 accepted/tizen/3.0/wearable/20161015.082649 accepted/tizen/common/20160809.184022 accepted/tizen/ivi/20160809.232625 accepted/tizen/mobile/20160809.232404 accepted/tizen/tv/20160809.232515 accepted/tizen/wearable/20160809.232720 submit/tizen/20160809.011327 submit/tizen/20160809.051427 submit/tizen_3.0_common/20161104.104000 submit/tizen_3.0_ivi/20161010.000002 submit/tizen_3.0_mobile/20161015.000002 submit/tizen_3.0_tv/20161015.000002 submit/tizen_3.0_wearable/20161015.000002
authorJiwoong Im <jiwoong.im@samsung.com>
Wed, 29 Jun 2016 13:49:55 +0000 (22:49 +0900)
committerJiwoong Im <jiwoong.im@samsung.com>
Fri, 5 Aug 2016 07:38:11 +0000 (16:38 +0900)
Change-Id: I3cdad951b79f69ae08d25859a53f4ef4659dfecb
Signed-off-by: Jiwoong Im <jiwoong.im@samsung.com>
src/esd_main.c

index 89b9ebd..cad7621 100644 (file)
 #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER)
 #define ROOT_USER 0
 
+#define SYS_EVENT_NAME_PREFIX "tizen.system.event"
+#define SYS_EVENT_OBJ_PATH "/tizen/system/event"
+#define REQUEST_LAST_DATA "request_last_data"
+
 static GHashTable *event_launch_table; /* table of events for launch_on_event*/
 
 static const char *event_launch_support_list[] = {
@@ -68,6 +72,16 @@ typedef struct __earlier_table_item {
 static bool g_is_bootcompleted = false;
 #endif
 
+static GHashTable *user_last_event_table; /* table of user events for last data */
+
+struct __last_event_item {
+       char *key;
+       char *app_id;
+       char *event_name;
+       char *own_name;
+       uid_t uid;
+};
+
 static GHashTable *trusted_busname_table; /* table of dbus bus-names for trusted user-event */
 
 typedef struct __trusted_busname_item {
@@ -152,6 +166,17 @@ static void __esd_finish_cynara(void)
        r_cynara = NULL;
 }
 
+static void free_saved_event(struct __last_event_item *item)
+{
+       if (!item)
+               return;
+
+       free(item->event_name);
+       free(item->own_name);
+       free(item->app_id);
+       free(item);
+}
+
 #ifdef APPFW_EVENT_SYSTEM_EARLIER_FEATURE
 static int __esd_check_earlier_support(const char *event_name)
 {
@@ -1136,6 +1161,16 @@ static const gchar introspection_xml[] =
 "                      <arg type='s' name='earlier_data' direction='out'/>"
 "              </method>"
 #endif
+"              <method name='KeepLastData'>"
+"                      <arg type='s' name='eventname' direction='in'/>"
+"                      <arg type='s' name='own_name' direction='in'/>"
+"                      <arg type='i' name='ret' direction='out'/>"
+"              </method>"
+"              <method name='CheckLastData'>"
+"                      <arg type='s' name='eventname' direction='in'/>"
+"                      <arg type='s' name='own_name' direction='in'/>"
+"                      <arg type='i' name='ret' direction='out'/>"
+"              </method>"
 "      </interface>"
 "</node>";
 
@@ -1473,6 +1508,157 @@ static void get_earlier_data_method_call(GVariant *parameters, GDBusMethodInvoca
 }
 #endif
 
+static void keep_last_data_method_call(GDBusConnection *connection,
+               const gchar *sender, GVariant *parameters,
+               GDBusMethodInvocation *invocation)
+{
+       GVariant *param;
+       int result = ES_R_OK;
+       char *event_name;
+       char *own_name;
+       char *key;
+       char app_id[128];
+       int sender_pid;
+       uid_t sender_uid;
+       struct __last_event_item *item;
+
+       g_variant_get(parameters, "(&s&s)", &event_name, &own_name);
+
+       if (!event_name || !own_name) {
+               result = ES_R_ERROR;
+               _E("invalid event_name and own_name");
+               goto out;
+       }
+
+       sender_pid = __get_sender_pid(connection, sender);
+       sender_uid = (uid_t)__get_sender_uid(connection, sender);
+       if (__esd_get_appid_by_pid(sender_pid, sender_uid, app_id,
+                               sizeof(app_id)) < 0) {
+               _E("failed to get appid by pid");
+               result = ES_R_ERROR;
+               goto out;
+       }
+
+       key = (char *)malloc(sizeof(event_name) + 10);
+       if (!key) {
+               result = ES_R_ENOMEM;
+               _E("out of memory");
+               goto out;
+       }
+
+       snprintf(key, sizeof(event_name) + 10, "%s_%d", event_name, sender_uid);
+       item = (struct __last_event_item *)g_hash_table_lookup(user_last_event_table,
+                       key);
+       if (!item) {
+               item = calloc(1, sizeof(*item));
+               if (!item) {
+                       result = ES_R_ERROR;
+                       goto out;
+               }
+               item->key = key;
+               item->event_name = strdup(event_name);
+               item->own_name = strdup(own_name);
+               item->uid = sender_uid;
+               item->app_id = strdup(app_id);
+               g_hash_table_insert(user_last_event_table,
+                               item->key, item);
+       } else {
+               free(item->own_name);
+               item->own_name = strdup(own_name);
+       }
+
+out:
+       param = g_variant_new("(i)", result);
+
+       g_dbus_method_invocation_return_value(invocation, param);
+}
+
+static void check_last_data_method_call(GDBusConnection *connection,
+               const gchar *sender, GVariant *parameters,
+               GDBusMethodInvocation *invocation)
+{
+       GVariant *param;
+       int result = ES_R_OK;
+       char *event_name;
+       char *own_name;
+       char *key;
+       char app_id[128];
+       int sender_pid;
+       uid_t sender_uid;
+       struct __last_event_item *item;
+
+       g_variant_get(parameters, "(&s&s)", &event_name, &own_name);
+
+       if (!event_name || !own_name) {
+               result = ES_R_ERROR;
+               _E("invalid event_name and own_name");
+               goto out;
+       }
+
+       sender_pid = __get_sender_pid(connection, sender);
+       sender_uid = (uid_t)__get_sender_uid(connection, sender);
+       if (__esd_get_appid_by_pid(sender_pid, sender_uid, app_id,
+                               sizeof(app_id)) < 0) {
+               result = ES_R_ERROR;
+               _E("failed to get appid by pid");
+               goto out;
+       }
+
+       key = (char *)malloc(sizeof(event_name) + 10);
+       if (!key) {
+               result = ES_R_ENOMEM;
+               _E("out of memory");
+               goto out;
+       }
+
+       snprintf(key, sizeof(event_name) + 10, "%s_%d", event_name, sender_uid);
+       item = (struct __last_event_item *)g_hash_table_lookup(user_last_event_table,
+                       key);
+       free(key);
+       if (item) {
+               GVariant *gv;
+               bundle *b;
+               bundle_raw *raw;
+               int len;
+               int ret;
+               GError *error = NULL;
+
+               b = bundle_create();
+               if (!b) {
+                       result = ES_R_ERROR;
+                       goto out;
+               }
+               bundle_add_str(b, EVT_KEY_KEPT_EVENT_NAME, event_name);
+               bundle_add_str(b, EVT_KEY_KEPT_OWN_NAME, own_name);
+               if (__esd_check_certificate_match(item->uid, item->app_id,
+                               sender_uid, app_id) == ES_R_OK)
+                       bundle_add_str(b, EVT_KEY_KEPT_IS_TRUSTED, "true");
+               else
+                       bundle_add_str(b, EVT_KEY_KEPT_IS_TRUSTED, "false");
+
+               bundle_encode(b, &raw, &len);
+               gv  = g_variant_new("(us)", len, raw);
+               ret = g_dbus_connection_emit_signal(connection,
+                               item->own_name,
+                               SYS_EVENT_OBJ_PATH,
+                               SYS_EVENT_NAME_PREFIX,
+                               REQUEST_LAST_DATA,
+                               gv,
+                               &error);
+               if (ret == FALSE) {
+                       _E("Unable to emit signal: %s", error->message);
+                       g_error_free(error);
+               }
+               bundle_free_encoded_rawdata(&raw);
+               bundle_free(b);
+       }
+
+out:
+       param = g_variant_new("(i)", result);
+
+       g_dbus_method_invocation_return_value(invocation, param);
+}
+
 static void handle_method_call(GDBusConnection *connection,
        const gchar *sender, const gchar *object_path,
        const gchar *interface_name, const gchar *method_name,
@@ -1493,6 +1679,10 @@ static void handle_method_call(GDBusConnection *connection,
        } else if (g_strcmp0(method_name, "GetEarlierData") == 0) {
                get_earlier_data_method_call(parameters, invocation);
 #endif
+       } else if (g_strcmp0(method_name, "KeepLastData") == 0) {
+               keep_last_data_method_call(connection, sender, parameters, invocation);
+       } else if (g_strcmp0(method_name, "CheckLastData") == 0) {
+               check_last_data_method_call(connection, sender, parameters, invocation);
        }
 }
 
@@ -1570,6 +1760,8 @@ static int __esd_before_loop(void)
        earlier_item *item;
 
        earlier_event_table = g_hash_table_new(g_str_hash, g_str_equal);
+       user_last_event_table = g_hash_table_new_full(g_str_hash,
+                       g_str_equal, NULL, (GDestroyNotify)free_saved_event);
 
        _I("register events for earlier_data");
        size = sizeof(earlier_event_list)/sizeof(*earlier_event_list);
@@ -1993,6 +2185,8 @@ static void __esd_finalize(void)
                }
                g_hash_table_unref(earlier_event_table);
        }
+
+       g_hash_table_destroy(user_last_event_table);
 #endif
 
        if (event_launch_table) {