Add a callback for proxy to show notification from zone 72/75572/7
authorSungbae Yoo <sungbae.yoo@samsung.com>
Tue, 21 Jun 2016 07:07:14 +0000 (16:07 +0900)
committerJaemin Ryu <jm77.ryu@samsung.com>
Thu, 23 Jun 2016 06:09:20 +0000 (15:09 +0900)
Signed-off-by: Sungbae Yoo <sungbae.yoo@samsung.com>
Change-Id: Ib91d0ea99de3c2b3e27a7d1ca98efad3e7fbb4a9

packaging/device-policy-manager.spec
server/zone.cpp
server/zone/zone.cpp
zone/kaskit/src/main.c
zone/module/CMakeLists.txt
zone/module/data/zone_indicator_icon.png [moved from zone/module/data/zone-indicator.png with 100% similarity]
zone/module/data/zone_noti_list_sub_icon.png [new file with mode: 0755]

index 4dc369e..1944a41 100755 (executable)
@@ -338,7 +338,8 @@ mv /etc/pam.d/systemd-user.keep /etc/pam.d/systemd-user
 %attr(700,root,root) %{_sbindir}/zone-volume-manager
 %attr(700,root,root) %dir %{TZ_SYS_ETC}/dpm/zone
 %attr(600,root,root) %config %{TZ_SYS_ETC}/dpm/zone/owner.xml
-%attr(644,root,root) /opt/data/dpm/zone-indicator.png
+%attr(644,root,root) %{TZ_SYS_DATA}/dpm/zone_indicator_icon.png
+%attr(644,root,root) %{TZ_SYS_DATA}/dpm/zone_noti_list_sub_icon.png
 %config /etc/pam.d/*
 
 %endif
index 2ea5ecf..0614d95 100755 (executable)
@@ -106,7 +106,7 @@ int ZonePolicy::createZone(const std::string& name, const std::string& setupWizA
 
 int ZonePolicy::removeZone(const std::string& name)
 {
-    if (getZoneState(name) < 0) {
+    if (getZoneState(name) == 0) {
         return -1;
     }
 
index a753da5..d1ae9d6 100644 (file)
@@ -19,6 +19,7 @@
 #include <sys/inotify.h>
 
 #include <notification.h>
+#include <notification_internal.h>
 #include <tzplatform_config.h>
 
 #include "zone/zone.hxx"
 #define ZONE_UID_MIN       60001
 #define ZONE_UID_MAX       65000
 
+#define DEFAULT_ZONE_OWNER "owner"
+
 #define ZONE_LAUNCHER_APP  "org.tizen.kaskit"
+#define NOTIFICATION_SUB_ICON_PATH  DATA_PATH "/zone_noti_list_sub_icon.png"
 
 namespace DevicePolicyManager {
 
@@ -71,6 +75,10 @@ const std::string APP_SMACKLABEL = "User::Pkg::";
 
 const std::string ZONE_GROUP = "users";
 
+std::vector<std::string> createdZoneList;
+std::unordered_map<std::string, int> notiProxyCallbackMap;
+std::unordered_map<int, notification_h> notiHandleMap;
+
 template <typename... Args>
 inline void execute(const std::string& path, Args&&... args)
 {
@@ -255,7 +263,7 @@ int packageEventHandler(uid_t target_uid, int req_id,
     }
 
     try {
-        runtime::User owner("owner"), pkgUser(target_uid);
+        runtime::User owner(DEFAULT_ZONE_OWNER), pkgUser(target_uid);
 
         if (type == "install" || type == "update") {
             PackageInfo pkg(pkgid, pkgUser.getUid());
@@ -282,6 +290,22 @@ int packageEventHandler(uid_t target_uid, int req_id,
     return 0;
 }
 
+void initializeCreatedZoneList() {
+    try {
+        runtime::Path manifestDir(ZONE_MANIFEST_DIR);
+        runtime::DirectoryIterator iter(manifestDir), end;
+
+        while (iter != end) {
+            const std::string& path = iter->getPath();
+            size_t namePos = path.rfind('/') + 1;
+            size_t extPos = path.rfind(".xml");
+            const std::string& name(path.substr(namePos, extPos - namePos));
+            createdZoneList.push_back(name);
+            ++iter;
+        }
+    } catch (runtime::Exception& e) {}
+}
+
 #define NT_TITLE     NOTIFICATION_TEXT_TYPE_TITLE
 #define NT_CONTENT   NOTIFICATION_TEXT_TYPE_CONTENT
 #define NT_ICON      NOTIFICATION_IMAGE_TYPE_ICON
@@ -290,7 +314,7 @@ int packageEventHandler(uid_t target_uid, int req_id,
 #define NT_EVENT     NOTIFICATION_LY_ONGOING_EVENT
 #define NT_APP       NOTIFICATION_DISPLAY_APP_INDICATOR
 
-#define NT_ICON_PATH "/opt/data/dpm/zone-indicator.png"
+#define NT_ICON_PATH DATA_PATH "/zone_indicator_icon.png"
 #define NT_TEXT      "Container Mode"
 #define NT_APPINFO   "Zone Application"
 
@@ -301,6 +325,7 @@ void zoneProcessCallback(GDBusConnection *connection,
                             const gchar *interface, const gchar *signalName,
                             GVariant *params, gpointer userData)
 {
+    static runtime::User owner(DEFAULT_ZONE_OWNER);
     int pid, status;
 
     notification_h noti = reinterpret_cast<notification_h>(userData);
@@ -320,7 +345,9 @@ void zoneProcessCallback(GDBusConnection *connection,
     if ((st.st_uid >= ZONE_UID_MIN) && (st.st_uid < ZONE_UID_MAX)) {
         notification_set_text(noti, NT_CONTENT, NT_APPINFO, NULL, NT_NONE);
 
-        notification_post(noti);
+        notification_post_for_uid(noti, owner.getUid());
+    } else {
+        notification_delete_for_uid(noti, owner.getUid());
     }
 }
 
@@ -387,6 +414,149 @@ void zoneProcessMonitor()
                                         NULL);
 }
 
+void notiProxyInsert(const runtime::User& owner, const runtime::User& user, int privId, notification_h noti)
+{
+    notification_h newNoti;
+    app_control_h appControl;
+    char zoneLauncherUri[PATH_MAX];
+    char* appId, *pkgId;
+
+    notification_clone(noti, &newNoti);
+
+    notification_get_pkgname(noti, &pkgId);
+    PackageInfo pkg(pkgId, user.getUid());
+    notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON, pkg.getIcon().c_str());
+    notification_set_image(newNoti, NOTIFICATION_IMAGE_TYPE_ICON_SUB, NOTIFICATION_SUB_ICON_PATH);
+
+    notification_get_launch_option(newNoti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)&appControl);
+    if (appControl != NULL) {
+        app_control_get_app_id(appControl, &appId);
+        snprintf(zoneLauncherUri, PATH_MAX, "zone://launch/%s/%s", user.getName().c_str(), appId);
+        app_control_set_app_id(appControl, ZONE_LAUNCHER_APP);
+        app_control_set_uri(appControl, zoneLauncherUri);
+        notification_set_launch_option(newNoti, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, appControl);
+    }
+
+    notification_post_for_uid(newNoti, owner.getUid());
+    notiHandleMap.insert(std::make_pair(privId, newNoti));
+}
+
+void notiProxyDelete(const runtime::User& owner, int privId)
+{
+    std::unordered_map<int, notification_h>::iterator it;
+
+    it = notiHandleMap.find(privId);
+    if (it == notiHandleMap.end()) {
+        return;
+    }
+    notification_delete_for_uid(it->second, owner.getUid());
+    notification_free(it->second);
+    notiHandleMap.erase(it);
+}
+
+void notiProxyUpdate(const runtime::User& owner, const runtime::User& user, int privId, notification_h noti) {
+    std::unordered_map<int, notification_h>::iterator it;
+    double progress;
+    char *str;
+
+    it = notiHandleMap.find(privId);
+    if (it == notiHandleMap.end()) {
+        return;
+    }
+
+    notification_image_type_e imageTypes[] = {
+        NOTIFICATION_IMAGE_TYPE_ICON,
+        NOTIFICATION_IMAGE_TYPE_ICON_FOR_INDICATOR,
+        NOTIFICATION_IMAGE_TYPE_ICON_FOR_LOCK,
+        NOTIFICATION_IMAGE_TYPE_THUMBNAIL,
+        NOTIFICATION_IMAGE_TYPE_THUMBNAIL_FOR_LOCK,
+        NOTIFICATION_IMAGE_TYPE_ICON_SUB,
+        NOTIFICATION_IMAGE_TYPE_BACKGROUND,
+        NOTIFICATION_IMAGE_TYPE_LIST_1,
+        NOTIFICATION_IMAGE_TYPE_LIST_2,
+        NOTIFICATION_IMAGE_TYPE_LIST_3,
+        NOTIFICATION_IMAGE_TYPE_LIST_4,
+        NOTIFICATION_IMAGE_TYPE_LIST_5,
+        NOTIFICATION_IMAGE_TYPE_BUTTON_1,
+        NOTIFICATION_IMAGE_TYPE_BUTTON_2,
+        NOTIFICATION_IMAGE_TYPE_BUTTON_3,
+        NOTIFICATION_IMAGE_TYPE_BUTTON_4,
+        NOTIFICATION_IMAGE_TYPE_BUTTON_5,
+        NOTIFICATION_IMAGE_TYPE_BUTTON_6
+    };
+
+    for (notification_image_type_e type : imageTypes) {
+        notification_get_image(noti, type, &str);
+        notification_set_image(it->second, type, str);
+    }
+
+    notification_text_type_e textTypes[] = {
+        NOTIFICATION_TEXT_TYPE_TITLE,
+        NOTIFICATION_TEXT_TYPE_CONTENT,
+        NOTIFICATION_TEXT_TYPE_CONTENT_FOR_DISPLAY_OPTION_IS_OFF,
+        NOTIFICATION_TEXT_TYPE_EVENT_COUNT,
+        NOTIFICATION_TEXT_TYPE_INFO_1,
+        NOTIFICATION_TEXT_TYPE_INFO_SUB_1,
+        NOTIFICATION_TEXT_TYPE_INFO_2,
+        NOTIFICATION_TEXT_TYPE_INFO_SUB_2,
+        NOTIFICATION_TEXT_TYPE_INFO_3,
+        NOTIFICATION_TEXT_TYPE_INFO_SUB_3,
+        NOTIFICATION_TEXT_TYPE_GROUP_TITLE,
+        NOTIFICATION_TEXT_TYPE_GROUP_CONTENT,
+        NOTIFICATION_TEXT_TYPE_GROUP_CONTENT_FOR_DISPLAY_OPTION_IS_OFF,
+        NOTIFICATION_TEXT_TYPE_BUTTON_1,
+        NOTIFICATION_TEXT_TYPE_BUTTON_2,
+        NOTIFICATION_TEXT_TYPE_BUTTON_3,
+        NOTIFICATION_TEXT_TYPE_BUTTON_4,
+        NOTIFICATION_TEXT_TYPE_BUTTON_5,
+        NOTIFICATION_TEXT_TYPE_BUTTON_6,
+    };
+
+    for (notification_text_type_e type : textTypes) {
+        notification_get_text(noti, type, &str);
+        notification_set_text(it->second, type, str, NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
+    }
+
+    notification_get_size(noti, &progress);
+    notification_set_size(it->second, progress);
+
+    notification_get_progress(noti, &progress);
+    notification_set_progress(it->second, progress);
+
+    notification_update_for_uid(it->second, owner.getUid());
+}
+
+void notiProxyCallback(void *data, notification_type_e type, notification_op *op_list, int num_op)
+{
+    static runtime::User owner(DEFAULT_ZONE_OWNER);
+    runtime::User user(*reinterpret_cast<std::string*>(data));
+
+    // TODO : should remove noti in the zone when related-zone is removed
+    //        This will be imlemented when notification bug is fixed
+
+    for (int i = 0; i < num_op; i++) {
+        notification_h noti = NULL;
+        int opType, privId;
+
+        notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_TYPE, &opType);
+        notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_PRIV_ID, &privId);
+
+        switch (opType) {
+        case NOTIFICATION_OP_INSERT:
+            notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_NOTI, &noti);
+            notiProxyInsert(owner, user, privId, noti);
+            break;
+        case NOTIFICATION_OP_DELETE:
+            notiProxyDelete(owner, privId);
+            break;
+        case NOTIFICATION_OP_UPDATE:
+            notification_op_get_data(op_list + i, NOTIFICATION_OP_DATA_NOTI, &noti);
+            notiProxyUpdate(owner, user, privId, noti);
+            break;
+        }
+    }
+}
+
 } // namespace
 
 ZoneManager::ZoneManager(PolicyControlContext& ctx)
@@ -406,6 +576,17 @@ ZoneManager::ZoneManager(PolicyControlContext& ctx)
     packageManager.setEventCallback(packageEventHandler, this);
 
     zoneProcessMonitor();
+
+    initializeCreatedZoneList();
+    for (std::string& name : createdZoneList) {
+        if (name == DEFAULT_ZONE_OWNER) {
+            continue;
+        }
+
+        runtime::User zone(name);
+        int noti = notification_register_detailed_changed_cb_for_uid(notiProxyCallback, &name, zone.getUid());
+        notiProxyCallbackMap.insert(std::make_pair(name, noti));
+    }
 }
 
 ZoneManager::~ZoneManager()
@@ -460,6 +641,9 @@ int ZoneManager::createZone(const std::string& name, const std::string& manifest
             //unlock the user
             setZoneState(user.getUid(), 1);
 
+            auto it = createdZoneList.insert(createdZoneList.begin(), name);
+            int noti = notification_register_detailed_changed_cb_for_uid(notiProxyCallback, &(*it), user.getUid());
+            notiProxyCallbackMap.insert(std::make_pair(name, noti));
             context.notify("ZoneManager::created", name, std::string());
 
             // Running launch app and add a shorcut
@@ -514,6 +698,11 @@ int ZoneManager::removeZone(const std::string& name)
             //remove zone user
             user.remove();
 
+            for (std::vector<std::string>::iterator it = createdZoneList.begin();
+                 it != createdZoneList.end(); it++) {
+                createdZoneList.erase(it);
+            }
+            notiProxyCallbackMap.erase(name);
             context.notify("ZoneManager::removed", name, std::string());
         } catch (runtime::Exception& e) {
             ERROR(e.what());
@@ -557,7 +746,7 @@ int ZoneManager::getZoneState(const std::string& name)
 {
     runtime::File manifest(ZONE_MANIFEST_DIR + name + ".xml");
     if (!manifest.exists()) {
-        return -1;
+        return 0;
     }
 
     try {
@@ -576,7 +765,7 @@ int ZoneManager::getZoneState(const std::string& name)
         }
     } catch (runtime::Exception& e) {
         ERROR(e.what());
-        return -1;
+        return 0;
     }
 
     return 0;
@@ -585,22 +774,12 @@ int ZoneManager::getZoneState(const std::string& name)
 std::vector<std::string> ZoneManager::getZoneList(int state)
 {
     std::vector<std::string> list;
-    try {
-        runtime::Path manifestDir(ZONE_MANIFEST_DIR);
-        runtime::DirectoryIterator iter(manifestDir), end;
 
-        while (iter != end) {
-            const std::string& path = iter->getPath();
-            size_t namePos = path.rfind('/') + 1;
-            size_t extPos = path.rfind(".xml");
-            const std::string& name(path.substr(namePos, extPos - namePos));
-            if (getZoneState(name) & state) {
-                list.push_back(name);
-            }
-            ++iter;
+    for (const std::string& name : createdZoneList) {
+        if (getZoneState(name) & state) {
+            list.push_back(name);
         }
-    } catch (runtime::Exception& e) {}
-
+    }
     return list;
 }
 
index 8a1fd9f..77dfbf9 100644 (file)
@@ -153,7 +153,7 @@ static void __add_shortcut(const char *zone_name)
 {
        char new_uri[PATH_MAX];
 
-       snprintf(new_uri, sizeof(new_uri), "zone://launch/%s", zone_name);
+       snprintf(new_uri, sizeof(new_uri), "zone://home/%s", zone_name);
        shortcut_add_to_home(zone_name, LAUNCH_BY_URI, new_uri, "", 0, __shortcut_result_cb, NULL);
 }
 
@@ -172,6 +172,14 @@ static void __show_launcher(const char *zone_name)
        ecore_thread_run(__create_icon_thread, NULL, NULL, NULL);
 }
 
+static void __launch_zone_app(const char *zone_name, const char *app_id)
+{
+       zone_app_proxy_create(__zone_mgr, zone_name, &__zone_app);
+       zone_package_proxy_create(__zone_mgr, zone_name, &__zone_pkg);
+       zone_app_proxy_launch(__zone_app, app_id);
+       ui_app_exit();
+}
+
 static bool __app_create(void *data)
 {
        zone_manager_create(&__zone_mgr);
@@ -183,33 +191,42 @@ static bool __app_create(void *data)
 
 static void __app_control(app_control_h app_control, void *data)
 {
-       char* zone_uri, *zone_name = "";
+       char* zone_uri, *tmp, *zone_name, *app_id;
         int ret = 0;
 
         ret = app_control_get_uri(app_control, &zone_uri);
         if (ret != APP_CONTROL_ERROR_NONE) {
                dlog_print(DLOG_ERROR, LOG_TAG, "No URI");
                 ui_app_exit();
+                return;
         }
 
        if (strncmp(zone_uri, "zone://", sizeof("zone://") - 1) != 0) {
                dlog_print(DLOG_ERROR, LOG_TAG, "Mismatched URI");
+                free(zone_uri);
                 ui_app_exit();
+                return;
        }
 
-       zone_uri = zone_uri + sizeof("zone://") - 1;
+       tmp = zone_uri + sizeof("zone://") - 1;
 
-       if (strncmp(zone_uri, "setup/", sizeof("setup/") - 1) == 0) {
-               zone_name = zone_uri + sizeof("setup/") - 1;
+       if (strncmp(tmp, "setup/", sizeof("setup/") - 1) == 0) {
+               zone_name = tmp + sizeof("setup/") - 1;
                __add_shortcut(zone_name);
                __show_launcher(zone_name);
-       } else if (strncmp(zone_uri, "launch/", sizeof("launch/") - 1) == 0) {
-               zone_name = zone_uri + sizeof("launch/") - 1;
+       } else if (strncmp(tmp, "home/", sizeof("home/") - 1) == 0) {
+               zone_name = tmp + sizeof("home/") - 1;
                __show_launcher(zone_name);
+       } else if (strncmp(tmp, "launch/", sizeof("launch/") - 1) == 0) {
+               zone_name = tmp + sizeof("launch/") - 1;
+               app_id = strchr(zone_name, '/');
+               *(app_id++) = '\0';
+               __launch_zone_app(zone_name, app_id);
        } else {
                dlog_print(DLOG_ERROR, LOG_TAG, "Invalid URI");
                 ui_app_exit();
        }
+        free(zone_uri);
 }
 
 static void __app_pause(void *data)
index 18aba37..d7ef612 100644 (file)
@@ -47,5 +47,6 @@ TARGET_COMPILE_DEFINITIONS(${ZONE_PAM_NAME} PRIVATE
 
 INSTALL(TARGETS ${ZONE_PAM_NAME} DESTINATION ${LIB_INSTALL_DIR}/security)
 INSTALL(FILES data/DefaultZoneManifest.xml DESTINATION ${CONF_INSTALL_DIR}/zone RENAME owner.xml)
-INSTALL(FILES data/zone-indicator.png DESTINATION /opt/data/dpm)
+INSTALL(FILES data/zone_indicator_icon.png DESTINATION /opt/data/dpm)
+INSTALL(FILES data/zone_noti_list_sub_icon.png DESTINATION /opt/data/dpm)
 INSTALL(FILES pam.d/systemd-user-zone DESTINATION ${PAMD_INSTALL_DIR})
diff --git a/zone/module/data/zone_noti_list_sub_icon.png b/zone/module/data/zone_noti_list_sub_icon.png
new file mode 100755 (executable)
index 0000000..ad08f64
Binary files /dev/null and b/zone/module/data/zone_noti_list_sub_icon.png differ