Add installer plugin and tool for create a NI
authorpius.lee <pius.lee@samsung.com>
Thu, 10 Nov 2016 11:26:43 +0000 (20:26 +0900)
committerpius.lee <pius.lee@samsung.com>
Fri, 11 Nov 2016 11:08:33 +0000 (20:08 +0900)
nitool : native image maker for system dlls and apps
libui-application.so : native image creating plugin for app installer

Fix bug on getting trusted platform dll.

Change-Id: Ie0b18c9fcca2fa0b814d4056d87c2e5d67e4e0e4

28 files changed:
NativeLauncher/CMakeLists.txt
NativeLauncher/inc/launcher.h [deleted file]
NativeLauncher/inc/utils.h
NativeLauncher/installer-plugin/common.cc [new file with mode: 0644]
NativeLauncher/installer-plugin/common.h [new file with mode: 0644]
NativeLauncher/installer-plugin/nitool.cc [new file with mode: 0644]
NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h [new file with mode: 0644]
NativeLauncher/installer-plugin/ui-application.cc [new file with mode: 0644]
NativeLauncher/launcher/dotnet/dotnet_launcher.cc [new file with mode: 0644]
NativeLauncher/launcher/dotnet/dotnet_launcher.h [new file with mode: 0644]
NativeLauncher/launcher/launcher.cc [new file with mode: 0644]
NativeLauncher/launcher/launcher.h [new file with mode: 0644]
NativeLauncher/launcher/main.cc [new file with mode: 0644]
NativeLauncher/launcher/mono/mono_launcher.cc [new file with mode: 0644]
NativeLauncher/launcher/mono/mono_launcher.h [new file with mode: 0644]
NativeLauncher/launcher/waiter/waiter.cc [new file with mode: 0644]
NativeLauncher/launcher/waiter/waiter.h [new file with mode: 0644]
NativeLauncher/src/dotnet/dotnet_launcher.cc [deleted file]
NativeLauncher/src/dotnet/dotnet_launcher.h [deleted file]
NativeLauncher/src/launcher.cc [deleted file]
NativeLauncher/src/main.cc [deleted file]
NativeLauncher/src/mono/mono_launcher.cc [deleted file]
NativeLauncher/src/mono/mono_launcher.h [deleted file]
NativeLauncher/src/utils.cc [deleted file]
NativeLauncher/src/waiter/waiter.cc [deleted file]
NativeLauncher/src/waiter/waiter.h [deleted file]
NativeLauncher/util/utils.cc [new file with mode: 0644]
packaging/dotnet-launcher.spec

index 0647e2a53d7124551e925f53e2cf536eae03518f..cd273e1faae39df64472c9501d8f9d8632c92b3d 100644 (file)
@@ -1,5 +1,5 @@
 CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
-PROJECT("dotnet-launcher")
+PROJECT("dotnet-tools")
 
 MESSAGE("CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}")
 
@@ -7,7 +7,7 @@ IF(DEFINED NO_TIZEN)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DNO_TIZEN")
 ELSE(DEFINED NO_TIZEN)
        INCLUDE(FindPkgConfig)
-       PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul dlog ecore bundle dlog launchpad)
+       PKG_CHECK_MODULES(${PROJECT_NAME} REQUIRED aul pkgmgr-info pkgmgr-installer dlog ecore bundle dlog launchpad)
 ENDIF(DEFINED NO_TIZEN)
 
 FOREACH(flag ${${PROJECT_NAME}_CFLAGS})
@@ -34,6 +34,10 @@ IF(DEFINED RUNTIME_DIR)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DRUNTIME_DIR=${RUNTIME_DIR}")
 ENDIF(DEFINED RUNTIME_DIR)
 
+IF(DEFINED CROSSGEN_PATH)
+       SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DCROSSGEN_PATH=${CROSSGEN_PATH}")
+ENDIF(DEFINED CROSSGEN_PATH)
+
 IF(DEFINED VERSION)
        SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DVERSION=${VERSION}")
 ENDIF(DEFINED VERSION)
@@ -41,7 +45,7 @@ ENDIF(DEFINED VERSION)
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -pthread -std=c++11 -Wl,--no-as-needed -ggdb")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
 #SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
-SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
+#SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
 SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64")
 #SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -DLAUNCHING_TIME_MEASURE")
@@ -51,19 +55,20 @@ SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g")
 SET(CMAKE_CXX_FLAGS_RELEASE "-O2")
 SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
 
-INCLUDE_DIRECTORIES(inc)
+#SET(${PROJECT_NAME}_LDFLAGS ${${PROJECT_NAME}_LDFLAGS} "-pie")
 
-SET(DOTNET_LAUNCHER "dotnet-launcher")
-SET(MONO_LAUNCHER "mono-launcher")
+INCLUDE_DIRECTORIES(inc launcher util)
 
+SET(DOTNET_LAUNCHER "dotnet-launcher")
 SET(${DOTNET_LAUNCHER}_SOURCE_FILES
-       src/main.cc
-       src/utils.cc
-       src/launcher.cc
-       src/dotnet/dotnet_launcher.cc
-       src/mono/mono_launcher.cc
+       launcher/main.cc
+       util/utils.cc
+       launcher/launcher.cc
+       launcher/dotnet/dotnet_launcher.cc
+       launcher/mono/mono_launcher.cc
 )
-ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_SOURCE_FILES})
+ADD_EXECUTABLE(${DOTNET_LAUNCHER} ${${DOTNET_LAUNCHER}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER}       PROPERTIES COMPILE_FLAGS "-fPIE")
 
 IF(NOT DEFINED NO_TIZEN)
        TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} aul)
@@ -72,11 +77,33 @@ TARGET_LINK_LIBRARIES(${DOTNET_LAUNCHER} ${${PROJECT_NAME}_LDFLAGS} "-pie -ldl -
 
 SET_TARGET_PROPERTIES(${DOTNET_LAUNCHER}
        PROPERTIES SKIP_BUILD_RPATH TRUE
-       ) # remove rpath option that is automatically generated by cmake.
+) # remove rpath option that is automatically generated by cmake.
+
+SET(NITOOL "nitool")
+SET(${NITOOL}_SOURCE_FILES
+       util/utils.cc
+       installer-plugin/common.cc
+       installer-plugin/nitool.cc
+)
+ADD_EXECUTABLE(${NITOOL} ${${NITOOL}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${NITOOL}        PROPERTIES COMPILE_FLAGS "-fPIE")
+TARGET_LINK_LIBRARIES(${NITOOL} ${${PROJECT_NAME}_LDFLAGS} "-pie")
+
+SET(INSTALLER_PLUGIN "ui-application")
+SET(${INSTALLER_PLUGIN}_SOURCE_FILES
+       util/utils.cc
+       installer-plugin/common.cc
+       installer-plugin/ui-application.cc
+)
+ADD_LIBRARY(${INSTALLER_PLUGIN} SHARED ${${INSTALLER_PLUGIN}_SOURCE_FILES})
+SET_TARGET_PROPERTIES(${INSTALLER_PLUGIN}      PROPERTIES COMPILE_FLAGS "-fPIC")
+TARGET_LINK_LIBRARIES(${INSTALLER_PLUGIN} ${${PROJECT_NAME}_LDFLAGS})
 
 IF(NOT DEFINED NO_TIZEN)
        INSTALL(TARGETS ${DOTNET_LAUNCHER} DESTINATION ${BINDIR})
+       INSTALL(TARGETS ${NITOOL} DESTINATION ${BINDIR})
+       INSTALL(TARGETS ${INSTALLER_PLUGIN} DESTINATION ${INSTALL_PLUGIN_DIR})
        INSTALL(FILES dotnet.loader DESTINATION ${LOADERDIR})
        INSTALL(FILES dotnet.launcher DESTINATION ${LOADERDIR})
-        INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR})
+       INSTALL(FILES dotnet.debugger DESTINATION ${LOADERDIR})
 ENDIF(NOT DEFINED NO_TIZEN)
diff --git a/NativeLauncher/inc/launcher.h b/NativeLauncher/inc/launcher.h
deleted file mode 100644 (file)
index 399bef5..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __LAUNCHER_INTERFACE_H__
-#define __LAUNCHER_INTERFACE_H__
-
-#include <string>
-#include <functional>
-
-namespace tizen {
-namespace runtime {
-
-class LauncherInterface
-{
-  public:
-    virtual int Initialize(bool standalone) = 0;
-    virtual void Dispose() = 0;
-    virtual int RunManagedLauncher() = 0;
-    virtual int Launch(const char* root, const char* path, int argc, char* argv[]) = 0;
-};
-
-struct AppInfo
-{
-  std::string root;
-  std::string path;
-  std::string id;
-  std::string pkg;
-  std::string type;
-};
-
-class LaunchpadAdapter
-{
-  public:
-    virtual void LoaderMain(int argc, char* argv[]) = 0;
-    std::function<void()> OnCreate = nullptr;
-    std::function<void(const AppInfo&, int, char**)> OnLaunch = nullptr;
-    std::function<void(const AppInfo&, int, char**)> OnTerminate = nullptr;
-};
-
-extern LaunchpadAdapter& Launchpad;
-
-}  // namespace runtime
-}  // namespace tizen
-
-#endif  // __LAUNCHER_INTERFACE_H__
index 145a43dbfe9003a69672343bf94f62c0d5e36455..ed993faab857d4ec30a1ac771194da370ea0477d 100644 (file)
@@ -3,11 +3,16 @@
 
 #include <string>
 #include <vector>
+#include <functional>
 
 #ifndef PATH_SEPARATOR
 #define PATH_SEPARATOR '/'
 #endif
 
+bool ICompare(const std::string& a, const std::string& b);
+bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length);
+bool IsManagedAssembly(const std::string& filename);
+bool IsNativeImage(const std::string& filename);
 std::string ReadSelfPath ();
 std::string ConcatPath (const std::string& path1, const std::string& path2);
 void AppendPath (std::string& path1, const std::string& path2);
@@ -18,4 +23,7 @@ void AssembliesInDirectory(const std::vector<std::string>& directories, std::str
 bool FileNotExist(const std::string& path);
 std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter);
 
+typedef std::function<void (const char*)> FileReader;
+void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth);
+
 #endif  // __UTILS_H__
diff --git a/NativeLauncher/installer-plugin/common.cc b/NativeLauncher/installer-plugin/common.cc
new file mode 100644 (file)
index 0000000..70b963f
--- /dev/null
@@ -0,0 +1,292 @@
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+#include <aul.h>
+
+#include "log.h"
+#include "utils.h"
+#include "pkgmgr_parser_plugin_interface.h"
+
+#include <wait.h>
+#include <dirent.h>
+#include <sys/stat.h>
+
+#include <algorithm>
+#include <string>
+
+#include "common.h"
+
+#ifdef  LOG_TAG
+#undef  LOG_TAG
+#endif
+#define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
+
+#ifndef DEVICE_API_DIR
+#error "DEVICE_API_DIR is missed"
+#endif
+
+#ifndef RUNTIME_DIR
+#error "RUNTIME_DIR is missed"
+#endif
+
+#ifndef CROSSGEN_PATH
+#error "CROSSGEN_PATH is missed"
+#endif
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+static const char* DeviceAPIDir = __STR(DEVICE_API_DIR);
+static const char* RuntimeDir = __STR(RUNTIME_DIR);
+static const char* CrossgenPath = __STR(CROSSGEN_PATH);
+static const char* JITPath = __STR(RUNTIME_DIR)"/libclrjit.so";
+#undef __STR
+#undef __XSTR
+
+static void crossgen(const char* dll_path, const char* app_path);
+static void smack_(const char* dll_path);
+
+void create_ni_platform()
+{
+  std::string corlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.dll");
+  std::string nicorlib = ConcatPath(RuntimeDir, "System.Private.CoreLib.ni.dll");
+
+  if (FileNotExist(nicorlib))
+  {
+    crossgen(corlib.c_str(), nullptr);
+    smack_(nicorlib.c_str());
+  }
+
+  const char* platform_dirs[] = {RuntimeDir, DeviceAPIDir};
+  const char* ignores[] = {corlib.c_str()};
+
+  create_ni_under_dirs(platform_dirs, 2, ignores, 1, [](const char* ni){
+      smack_(ni);
+  });
+}
+
+static void smack_(const char* dll_path)
+{
+  static const char* CHKSMACK = "/usr/bin/chsmack";
+  pid_t pid = fork();
+  if (pid == -1)
+  {
+    return;
+  }
+
+  if (pid > 0)
+  {
+    int status;
+    waitpid(pid, &status, 0);
+    if (WIFEXITED(status))
+    {
+      return;
+    }
+  }
+  else
+  {
+    const char* args[] = {
+      CHKSMACK,
+      "-a", "_",
+      dll_path,
+      nullptr
+    };
+    for (const char* arg : args)
+    {
+      printf("%s ", arg);
+    }
+    printf("\n");
+
+    execv(CHKSMACK, const_cast<char*const*>(args));
+
+    exit(0);
+  }
+}
+
+static void crossgen(const char* dll_path, const char* app_path)
+{
+  //pid_t parent = getpid();
+  pid_t pid = fork();
+  if (pid == -1)
+  {
+    return;
+  }
+
+  if (pid > 0)
+  {
+    int status;
+    waitpid(pid, &status, 0);
+    if (WIFEXITED(status))
+    {
+      return;
+    }
+  }
+  else
+  {
+    std::vector<std::string> tpaDir = {
+      RuntimeDir, DeviceAPIDir
+    };
+    std::string tpa;
+    AssembliesInDirectory(tpaDir, tpa);
+
+    std::vector<const char*> argv =
+    {
+      CrossgenPath,
+      "/Trusted_Platform_Assemblies", tpa.c_str(),
+      "/JITPath", JITPath,
+      "/FragileNonVersionable"
+    };
+    if (app_path != nullptr)
+    {
+      argv.push_back("/App_Paths");
+      argv.push_back(app_path);
+    }
+    argv.push_back(dll_path);
+    argv.push_back(nullptr);
+
+    /*
+    for (const char* arg : argv)
+    {
+      printf("%s ", arg);
+    }
+    printf("\n");
+    */
+    printf("+ %s\n", dll_path);
+
+    execv(CrossgenPath, const_cast<char* const*>(argv.data()));
+    exit(0);
+  }
+}
+
+static int get_root_path(const char *pkgid, std::string& root_path)
+{
+  int ret = 0;
+  char *path = 0;
+
+  uid_t uid = 0;
+
+  if (pkgmgr_installer_info_get_target_uid(&uid) < 0)
+  {
+    _ERR("Failed to get UID");
+    return -1;
+  }
+
+  _INFO("user id is %d", uid);
+
+  pkgmgrinfo_pkginfo_h handle;
+  if (uid == 0)
+  {
+    ret = pkgmgrinfo_pkginfo_get_pkginfo(pkgid, &handle);
+    if (ret != PMINFO_R_OK)
+      return -1;
+  }
+  else
+  {
+    ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
+    if (ret != PMINFO_R_OK)
+      return -1;
+  }
+
+  ret = pkgmgrinfo_pkginfo_get_root_path(handle, &path);
+  if (ret != PMINFO_R_OK) {
+    pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+    return -1;
+  }
+  root_path = path;
+  pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+
+  return 0;
+}
+
+static bool NIExist(const std::string& path, std::string& ni)
+{
+  static const char* possible_exts[] = {
+    ".ni.dll", ".NI.dll", ".NI.DLL", ".ni.DLL"
+  };
+  std::string fname = path.substr(0, path.size() - 4);
+
+  struct stat sb;
+
+  for (const char* ext : possible_exts)
+  {
+    std::string f = fname + ext;
+    if (stat(f.c_str(), &sb) == 0)
+    {
+      ni = f;
+      return true;
+    }
+  }
+
+  return false;
+}
+
+void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb)
+{
+  std::string app_paths;
+  for (int i=0; i<count; i++)
+  {
+    app_paths += root_paths[i];
+    app_paths += ':';
+  }
+  if (app_paths.back() == ':')
+    app_paths.pop_back();
+
+  auto convert = [&app_paths, ignores, igcount, &cb](const char* path)
+  {
+    for (int i=0; i<igcount; i++)
+    {
+      if (strcmp(path, ignores[i]) == 0)
+        return;
+    }
+    std::string ni;
+    if (IsManagedAssembly(path) && !IsNativeImage(path) && !NIExist(path, ni))
+    {
+      crossgen(path, app_paths.c_str());
+      if (NIExist(path, ni))
+      {
+        if (cb != nullptr)
+        {
+          cb(ni.c_str());
+        }
+      }
+    }
+  };
+
+  for (int i=0; i<count; i++)
+  {
+    ScanFilesInDir(root_paths[i], convert, -1);
+  }
+}
+void create_ni_under_dirs(const char* root_paths[], int count, after_create cb)
+{
+  create_ni_under_dirs(root_paths, count, nullptr, 0, cb);
+}
+void create_ni_under_dirs(const char* root_paths[], int count)
+{
+  create_ni_under_dirs(root_paths, count, nullptr);
+}
+
+int create_ni_under_pkg_root(const char* pkg_name)
+{
+  std::string pkgroot;
+  if (get_root_path(pkg_name, pkgroot) < 0)
+  {
+    return 1;
+  }
+
+  //printf("pkgroot : %s\n", pkgroot.c_str());
+
+  std::string bindir = ConcatPath(pkgroot, "bin");
+  std::string libdir = ConcatPath(pkgroot, "lib");
+  
+  //printf("bindir : %s\n", bindir.c_str());
+  //printf("libdir : %s\n", libdir.c_str());
+  _INFO("bindir : %s", bindir.c_str());
+  _INFO("libdir : %s", libdir.c_str());
+
+  const char* paths[] = {
+    bindir.c_str(),
+    libdir.c_str()
+  };
+  create_ni_under_dirs(paths, 2);
+
+  return 0;
+}
diff --git a/NativeLauncher/installer-plugin/common.h b/NativeLauncher/installer-plugin/common.h
new file mode 100644 (file)
index 0000000..39f4381
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef __INSTALLER_PLUGIN_COMMON_H__
+#define __INSTALLER_PLUGIN_COMMON_H__
+
+#include <functional>
+
+typedef std::function<void (const char*)> after_create;
+void create_ni_under_dirs(const char* root_paths[], int count, const char* ignores[], int igcount, after_create cb);
+void create_ni_under_dirs(const char* root_paths[], int count, after_create cb);
+void create_ni_under_dirs(const char* root_paths[], int count);
+int create_ni_under_pkg_root(const char* pkg_name);
+void create_ni_platform();
+
+#endif  // __INSTALLER_PLUGIN_COMMON_H__
diff --git a/NativeLauncher/installer-plugin/nitool.cc b/NativeLauncher/installer-plugin/nitool.cc
new file mode 100644 (file)
index 0000000..1fd4c8f
--- /dev/null
@@ -0,0 +1,93 @@
+#include "common.h"
+
+#include <cstdio>
+#include <cstring>
+
+#include <algorithm>
+
+std::vector<const char*> get_cmd_args(char** begin, char** end)
+{
+  for (char** itr = end-1; itr != begin-1; --itr)
+  {
+    if (itr != end && strncmp(*itr, "--", 2) == 0)
+    {
+      itr++;
+      int len = end - itr;
+      return std::vector<const char*>(len, *itr);
+    }
+  }
+  return std::vector<const char*>(end-begin-1, *(begin+1));
+}
+
+bool cmd_option_exists(char** begin, char** end, const std::string& option)
+{
+  return std::find(begin, end, option) != end;
+}
+
+static void help(const char *argv0)
+{
+  const char* helpdesc = 
+    "Usage: %s [args] <root paths or pkg name>\n"
+    "      --help       - Display this screen\n"
+    "      --system     - Create NI under System DLLs\n"
+    "      --pkg        - Create NI for package\n"
+    "\n"
+    "Example:\n"
+    "Create native image for dlls and exes under platform directories\n"
+    "%s --system\n"
+    "Create native image under the package's bin and lib directory\n"
+    "%s --pkg org.tizen.FormsGallery\n\n";
+  printf(helpdesc, argv0, argv0, argv0);
+}
+
+int main(int argc, char* argv[])
+{
+  bool pkg_mode = false;
+
+  if (cmd_option_exists(argv, argv+argc, "--help"))
+  {
+    help(argv[0]);
+    return 0;
+  }
+
+  if (cmd_option_exists(argv, argv+argc, "--system"))
+  {
+    create_ni_platform();
+    return 0;
+  }
+
+  if (cmd_option_exists(argv, argv+argc, "--pkg"))
+  {
+    pkg_mode = true;
+  }
+
+  std::vector<const char*> args = get_cmd_args(argv, argv+argc);
+
+  if (args.size() < 1)
+  {
+    if (pkg_mode)
+      fprintf(stderr, "Package name is missed\n");
+    else
+      fprintf(stderr, "DLL path is missed\n");
+    help(argv[0]);
+    return 1;
+  }
+
+  if (pkg_mode)
+  {
+    for (const char* pkg : args)
+    {
+      if (create_ni_under_pkg_root(pkg) != 0)
+      {
+        fprintf(stderr, "Failed to get root path from [%s]\n", pkg);
+        return 1;
+      }
+    }
+  }
+  else
+  {
+    create_ni_under_dirs(args.data(), args.size());
+  }
+
+  return 0;
+}
diff --git a/NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h b/NativeLauncher/installer-plugin/pkgmgr_parser_plugin_interface.h
new file mode 100644 (file)
index 0000000..0f2d4a8
--- /dev/null
@@ -0,0 +1,21 @@
+#ifndef __PKGMGR_PARSER_PLUGIN_INTERFACE__
+#define __PKGMGR_PARSER_PLUGIN_INTERFACE__
+
+extern "C"
+{
+  typedef struct _xmlDoc xmlDoc;
+  typedef xmlDoc* xmlDocPtr;
+  int PKGMGR_PARSER_PLUGIN_PRE_INSTALL   (const char *pkgid);
+  int PKGMGR_PARSER_PLUGIN_PRE_UPGRADE   (const char *pkgid);
+  int PKGMGR_PARSER_PLUGIN_PRE_UNINSTALL (const char *pkgid);
+
+  int PKGMGR_PARSER_PLUGIN_INSTALL   (xmlDocPtr doc, const char* pkgid);
+  int PKGMGR_PARSER_PLUGIN_UPGRADE   (xmlDocPtr doc, const char* pkgid);
+  int PKGMGR_PARSER_PLUGIN_UNINSTALL (xmlDocPtr doc, const char* pkgid);
+
+  int PKGMGR_PARSER_PLUGIN_POST_INSTALL   (const char *pkgid);
+  int PKGMGR_PARSER_PLUGIN_POST_UPGRADE   (const char *pkgid);
+  int PKGMGR_PARSER_PLUGIN_POST_UNINSTALL (const char *pkgid);
+}
+
+#endif  // __PKGMGR_PARSER_PLUGIN_INTERFACE__
diff --git a/NativeLauncher/installer-plugin/ui-application.cc b/NativeLauncher/installer-plugin/ui-application.cc
new file mode 100644 (file)
index 0000000..c0196e3
--- /dev/null
@@ -0,0 +1,96 @@
+#include "common.h"
+#include "log.h"
+
+#ifdef  LOG_TAG
+#undef  LOG_TAG
+#endif
+#define LOG_TAG "NETCORE_INSTALLER_PLUGIN"
+
+#include <cstring>
+#include <pkgmgr-info.h>
+#include <pkgmgr_installer_info.h>
+
+/*
+ * forked crossgen from installer is not working.
+ * because crossgen's capability is not enough.
+ * following command is needed
+ *
+ * setcap cap_dac_override=eip /opt/usr/share/dotnet.tizen/framework/crossgen
+ *
+ */
+
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_INSTALL   (const char *pkgid)
+{
+  _INFO("pkg : %s", pkgid);
+
+  uid_t uid = 0;
+
+  if (pkgmgr_installer_info_get_target_uid(&uid) < 0)
+  {
+    _ERR("Failed to get UID");
+    return 0;
+  }
+
+  pkgmgrinfo_pkginfo_h handle;
+  int ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, uid, &handle);
+  if (ret != PMINFO_R_OK)
+  {
+    _ERR("Failed to get pkg info");
+    return 0;
+  }
+
+  _INFO("success to get pkg info");
+
+  bool dotnet_exist = false;
+
+  auto dotnet_app_counter = [] (pkgmgrinfo_appinfo_h handle, void *user_data) -> int
+  {
+    char* appid = nullptr;
+    char* type = nullptr;
+    bool* dotnet = static_cast<bool*>(user_data);
+
+    if (pkgmgrinfo_appinfo_get_appid(handle, &appid) != PMINFO_R_OK)
+    {
+      _ERR("Failed to get app id");
+      return 0;
+    }
+
+    _INFO("App id : %s", appid);
+
+    if (pkgmgrinfo_appinfo_get_apptype(handle, &type) != PMINFO_R_OK)
+    {
+      _ERR("Failed to get app type : %s", appid);
+      return 0;
+    }
+
+    _INFO("App type : %s", type);
+
+    if (strcmp(type, "dotnet") == 0)
+    {
+      *dotnet = true;
+    }
+
+    return 0;
+  };
+
+  if (pkgmgrinfo_appinfo_get_usr_list(handle, PMINFO_ALL_APP, dotnet_app_counter, &dotnet_exist, uid) != PMINFO_R_OK)
+  {
+    _ERR("Failed to get list of app in pkg : %s", pkgid);
+    return -1;
+  }
+
+  _INFO("Finish to get pkg list");
+
+  pkgmgrinfo_pkginfo_destroy_pkginfo(handle);
+  if (dotnet_exist)
+  {
+    _INFO("dotnet app is exist");
+    return create_ni_under_pkg_root(pkgid) == 0 ? 0 : -1;
+  }
+
+  return 0;
+}
+extern "C" int PKGMGR_PARSER_PLUGIN_POST_UPGRADE   (const char *pkgid)
+{
+  return PKGMGR_PARSER_PLUGIN_POST_INSTALL(pkgid);
+}
diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.cc b/NativeLauncher/launcher/dotnet/dotnet_launcher.cc
new file mode 100644 (file)
index 0000000..1bfbdec
--- /dev/null
@@ -0,0 +1,300 @@
+
+#include <dlfcn.h>
+
+#include <string>
+#include <fstream>
+#include <vector>
+
+#include "utils.h"
+#include "log.h"
+#include "launcher.h"
+#include "dotnet_launcher.h"
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+CoreRuntime::CoreRuntime() :
+  InitializeClr(nullptr),
+  ExecuteAssembly(nullptr),
+  Shutdown(nullptr),
+  CreateDelegate(nullptr),
+  coreclrLib(nullptr),
+  hostHandle(nullptr),
+  domainId(-1),
+  PreparedFunction(nullptr),
+  LaunchFunction(nullptr)
+{
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef DEVICE_API_DIR
+  DeviceAPIDirectory = __STR(DEVICE_API_DIR);
+#endif
+#ifdef RUNTIME_DIR
+  RuntimeDirectory = __STR(RUNTIME_DIR);
+#endif
+#ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
+  LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
+#endif
+
+#undef __STR
+#undef __XSTR
+
+  _DBG("Constructor called!!");
+}
+
+CoreRuntime::~CoreRuntime()
+{
+  Dispose();
+}
+
+int CoreRuntime::Initialize(bool standalone)
+{
+
+  if (standalone)
+  {
+    const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
+    const char *_runtime_directory = getenv("RuntimeDirectory");
+    const char *_launcher_assembly = getenv("LauncherAssembly");
+    if (_deviceapi_directory != nullptr)
+      DeviceAPIDirectory = _deviceapi_directory;
+    if (_runtime_directory != nullptr)
+      RuntimeDirectory = _runtime_directory;
+    if (_launcher_assembly != nullptr)
+      LauncherAssembly = _launcher_assembly;
+  }
+
+  if (DeviceAPIDirectory.empty())
+  {
+    _ERR("Empty Device API Directory");
+    return 1;
+  }
+  else
+  {
+    DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
+  }
+  if (RuntimeDirectory.empty())
+  {
+    _ERR("Empty Runtime Directory");
+    return 1;
+  }
+  else
+  {
+    RuntimeDirectory = AbsolutePath(RuntimeDirectory);
+  }
+  if (LauncherAssembly.empty())
+  {
+    _ERR("Empty Launcher Assembly");
+    return 1;
+  }
+  else
+  {
+    LauncherAssembly = AbsolutePath(LauncherAssembly);
+  }
+
+  std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
+
+  _DBG("libcoreclr : %s", libcoreclr.c_str());
+
+  coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
+  if (coreclrLib == nullptr)
+  {
+    char *err = dlerror();
+    _ERR("dlopen failed to open libcoreclr.so with error %s", err);
+    return 1;
+  }
+
+#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
+  do { variable = (type)dlsym(coreclrLib, name); \
+    if (variable == nullptr) { \
+      _ERR(name " is not found in the libcoreclr.so"); \
+      return 1; \
+    }} while(0)
+
+  CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
+  CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
+  CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
+  CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
+
+#undef CORELIB_RETURN_IF_NOSYM
+
+  _DBG("libcoreclr dlopen and dlsym success");
+
+  _DBG("this addr : %x", this);
+  _DBG("coreclr_initialize : %x", InitializeClr);
+
+  return 0;
+}
+
+bool CoreRuntime::InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths)
+{
+  std::vector<std::string> platformDirectories = {
+    RuntimeDirectory, DeviceAPIDirectory
+  };
+
+  std::string trusted_assemblies;
+  AssembliesInDirectory(platformDirectories, trusted_assemblies);
+
+  const char *propertyKeys[] =
+  {
+    "TRUSTED_PLATFORM_ASSEMBLIES",
+    "APP_PATHS",
+    "APP_NI_PATHS",
+    "NATIVE_DLL_SEARCH_DIRECTORIES",
+    "AppDomainCompatSwitch"
+  };
+
+  const char *propertyValues[] =
+  {
+    trusted_assemblies.c_str(),
+    assembly_probe_paths,
+    assembly_probe_paths,
+    pinvoke_probe_paths,
+    "UseLatestBehaviorWhenTFMNotSpecified"
+  };
+
+  std::string selfPath = ReadSelfPath();
+
+  int st = InitializeClr(
+      selfPath.c_str(),
+      "dotnet-launcher",
+      sizeof(propertyKeys) / sizeof(propertyKeys[0]),
+      propertyKeys,
+      propertyValues,
+      &hostHandle,
+      &domainId);
+
+  if (st < 0)
+  {
+    _ERR("initialize core clr fail! (0x%08x)", st);
+    return false;
+  }
+
+  _DBG("Initialize core clr success");
+  return true;
+}
+
+int CoreRuntime::RunManagedLauncher()
+{
+  if (FileNotExist(LauncherAssembly))
+  {
+    _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
+    return 1;
+  }
+
+  std::string launcherDir = Basename(LauncherAssembly);
+  std::vector<std::string> searchDirectories = {
+    RuntimeDirectory, DeviceAPIDirectory
+  };
+
+  std::string trusted_directories = JoinStrings(searchDirectories, ":");
+
+  _DBG("coreclr_dir : %s", RuntimeDirectory.c_str());
+  _DBG("native_so_search_dir : %s", trusted_directories.c_str());
+  _DBG("launcher_assembly : %s", LauncherAssembly.c_str());
+  _DBG("launcher_dir : %s", launcherDir.c_str());
+
+  if (!InitializeCoreClr(launcherDir.c_str(), launcherDir.c_str()))
+  {
+    _ERR("Failed to initialize coreclr");
+    return 1;
+  }
+
+  void *preparedFunctionDelegate;
+  int st = CreateDelegate(hostHandle, domainId,
+      "Tizen.Runtime.Coreclr",
+      "Tizen.Runtime.Coreclr.AssemblyManager",
+      "Prepared", &preparedFunctionDelegate);
+  if (st < 0)
+  {
+    _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
+    return 1;
+  }
+  PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
+
+  if(PreparedFunction != nullptr)
+  {
+    PreparedFunction();
+  }
+
+  void *launchFunctionDelegate;
+  st = CreateDelegate(hostHandle, domainId,
+      "Tizen.Runtime.Coreclr",
+      "Tizen.Runtime.Coreclr.AssemblyManager",
+      "Launch", &launchFunctionDelegate);
+  if (st < 0)
+  {
+    _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
+    return 1;
+  }
+  LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
+
+  return 0;
+}
+
+void CoreRuntime::Dispose()
+{
+  if (hostHandle != nullptr)
+  {
+    int st = Shutdown(hostHandle, domainId);
+    if (st < 0)
+    {
+      _ERR("shutdown core clr fail! (0x%08x)", st);
+    }
+  }
+
+  if (dlclose(coreclrLib) != 0)
+  {
+    _ERR("libcoreclr.so close failed");
+  }
+  coreclrLib = nullptr;
+
+  _DBG("Dotnet runtime disposed");
+}
+
+int CoreRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
+{
+  if (path == nullptr)
+  {
+    _ERR("executable path is null");
+    return 1;
+  }
+
+  if (FileNotExist(path))
+  {
+    _ERR("File not exist : %s", path);
+    return 1;
+  }
+
+  bool success = false;
+  if (LaunchFunction != nullptr)
+  {
+    success = LaunchFunction(root, path, argc, argv);
+    if (!success)
+    {
+      _ERR("Failed to launch Application %s", path);
+    }
+    return success ? 0 : 1;
+  }
+  else
+  {
+    std::string appRoot = root;
+    std::string appBin = ConcatPath(appRoot, "bin");
+    std::string appLib = ConcatPath(appRoot, "lib");
+    std::string probePath = appBin + ":" + appLib;
+
+    int st = InitializeCoreClr(probePath.c_str(), probePath.c_str());
+    unsigned int ret = 0;
+    st = ExecuteAssembly(hostHandle, domainId, argc, (const char**)argv, path, &ret);
+    if (st < 0)
+    {
+      _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
+    }
+    return ret;
+  }
+}
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/launcher/dotnet/dotnet_launcher.h b/NativeLauncher/launcher/dotnet/dotnet_launcher.h
new file mode 100644 (file)
index 0000000..fa72e11
--- /dev/null
@@ -0,0 +1,70 @@
+#include "launcher.h"
+
+extern "C"
+{
+  typedef int (*coreclr_initialize_ptr)(
+      const char* exePath,
+      const char* appDomainFriendlyName,
+      int propertyCount,
+      const char** propertyKeys,
+      const char** propertyValues,
+      void** hostHandle,
+      unsigned int* domainId);
+
+  typedef int (*coreclr_execute_assembly_ptr)(
+      void* hostHandle,
+      unsigned int domainId,
+      int argc,
+      const char** argv,
+      const char* managedAssemblyPath,
+      unsigned int* exitCode);
+
+  typedef int (*coreclr_shutdown_ptr)(
+      void* hostHandle,
+      unsigned int domainId);
+
+  typedef int (*coreclr_create_delegate_ptr)(
+      void* hostHandle,
+      unsigned int domainId,
+      const char* entryPointAssemblyName,
+      const char* entryPointTypeName,
+      const char* entryPointMethodName,
+      void** delegate);
+}
+
+namespace tizen {
+namespace runtime {
+namespace dotnetcore {
+
+typedef void (*PreparedFunctionPtr)();
+typedef bool (*LaunchFunctionPtr)(const char* root, const char* path, int argc, char* argv[]);
+
+class CoreRuntime : public tizen::runtime::LauncherInterface
+{
+  public:
+    CoreRuntime();
+    ~CoreRuntime();
+    int Initialize(bool standalone) override;
+    void Dispose() override;
+    int RunManagedLauncher() override;
+    int Launch(const char* root, const char* path, int argc, char* argv[]) override;
+
+  private:
+    bool InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths);
+    coreclr_initialize_ptr InitializeClr;
+    coreclr_execute_assembly_ptr ExecuteAssembly;
+    coreclr_shutdown_ptr Shutdown;
+    coreclr_create_delegate_ptr CreateDelegate;
+    std::string DeviceAPIDirectory;
+    std::string RuntimeDirectory;
+    std::string LauncherAssembly;
+    void* coreclrLib;
+    void* hostHandle;
+    unsigned int domainId;
+    PreparedFunctionPtr PreparedFunction;
+    LaunchFunctionPtr LaunchFunction;
+};
+
+}  // dotnetcore
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/launcher/launcher.cc b/NativeLauncher/launcher/launcher.cc
new file mode 100644 (file)
index 0000000..9efd49e
--- /dev/null
@@ -0,0 +1,171 @@
+#include "launcher.h"
+#include "log.h"
+
+#include <launchpad.h>
+#include <aul.h>
+
+#include <Ecore.h>
+
+#include <map>
+#include <vector>
+#include <functional>
+
+#include <unistd.h>
+
+
+namespace tizen {
+namespace runtime {
+
+struct FdHandler
+{
+  Ecore_Fd_Handler *handler;
+  loader_receiver_cb receiver;
+};
+
+class LaunchpadAdapterImpl : public LaunchpadAdapter
+{
+  public:
+    LaunchpadAdapterImpl() : isLaunched(false) { }
+    void LoaderMain(int argc, char* argv[]) override;
+
+    std::map<int, FdHandler> Handlers;
+
+  private:
+    AppInfo appinfo;
+    loader_lifecycle_callback_s callbacks;
+    loader_adapter_s adapter;
+    LauncherInterface* launcher;
+    bool isLaunched;
+    std::string launchPath;
+};
+
+LaunchpadAdapterImpl LaunchpadImpl;
+LaunchpadAdapter& Launchpad = LaunchpadImpl;
+
+#define WITH_SELF(data) \
+  LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
+  if (self == nullptr) \
+  { \
+    _ERR("No LaunchpadImplData"); \
+  } else
+
+static Eina_Bool Fd_Handler(void *data, Ecore_Fd_Handler* handler)
+{
+  WITH_SELF(data)
+  {
+    int fd = ecore_main_fd_handler_fd_get(handler);
+    if (fd == -1)
+    {
+      _ERR("Failed to get the Ecore FD");
+      exit(-1);
+    }
+
+    if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
+    {
+      if (self->Handlers.find(fd) != self->Handlers.end())
+      {
+        self->Handlers[fd].receiver(fd);
+      }
+    }
+    else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
+    {
+      _ERR("Ecore FD Handler Have Error");
+      close(fd);
+      exit(-1);
+    }
+  }
+
+  return ECORE_CALLBACK_CANCEL;
+}
+
+static void Fd_Add(void *data, int fd, loader_receiver_cb receiver)
+{
+  Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
+      static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
+      Fd_Handler, data, nullptr, nullptr);
+  if (handler == nullptr)
+  {
+    _ERR("Failed to add a FD handler to ecore main loop");
+    close(fd);
+    exit(-1);
+  }
+  WITH_SELF(data)
+  {
+    self->Handlers[fd] = {handler, receiver};
+  }
+}
+
+static void Fd_Remove(void *data, int fd)
+{
+  WITH_SELF(data)
+  {
+    if (self->Handlers.find(fd) != self->Handlers.end())
+    {
+      Ecore_Fd_Handler* handler = self->Handlers[fd].handler;
+      ecore_main_fd_handler_del(handler);
+      self->Handlers.erase(fd);
+    }
+  }
+}
+
+void LaunchpadAdapterImpl::LoaderMain(int argc, char* argv[])
+{
+
+  callbacks.create = [](bundle *extra, int type, void *user_data)
+  {
+    ecore_init();
+    WITH_SELF(user_data)
+    {
+      if (self->OnCreate != nullptr)
+        self->OnCreate();
+    }
+  };
+  callbacks.launch = [](int argc, char** argv, const char* app_path,
+      const char* appid, const char* pkgid,
+      const char* pkg_type, void* user_data) -> int
+  {
+    WITH_SELF(user_data)
+    {
+      self->appinfo.root = std::string(aul_get_app_root_path());
+      self->appinfo.path = app_path;
+      self->appinfo.id = appid;
+      self->appinfo.pkg = pkgid;
+      self->appinfo.type = pkg_type;
+      if (self->OnLaunch != nullptr)
+        self->OnLaunch(self->appinfo, argc, argv);
+    }
+
+    return 0;
+  };
+  callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
+  {
+    _DBG("Terminate!!");
+    WITH_SELF(user_data)
+    {
+      if (self->OnTerminate != nullptr)
+        self->OnTerminate(self->appinfo, argc, argv);
+    }
+    return 0;
+  };
+
+  adapter.loop_begin = [](void *data)
+  {
+    ecore_main_loop_begin();
+  };
+
+  adapter.loop_quit = [](void *data)
+  {
+    ecore_main_loop_quit();
+  };
+  adapter.add_fd = Fd_Add;
+  adapter.remove_fd = Fd_Remove;
+
+  _DBG("launchpad_loader_main is start");
+  int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
+  _DBG("launchpad_loader_main is finished with [%d]", r);
+}
+
+#undef WITH_SELF
+
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/launcher/launcher.h b/NativeLauncher/launcher/launcher.h
new file mode 100644 (file)
index 0000000..399bef5
--- /dev/null
@@ -0,0 +1,42 @@
+#ifndef __LAUNCHER_INTERFACE_H__
+#define __LAUNCHER_INTERFACE_H__
+
+#include <string>
+#include <functional>
+
+namespace tizen {
+namespace runtime {
+
+class LauncherInterface
+{
+  public:
+    virtual int Initialize(bool standalone) = 0;
+    virtual void Dispose() = 0;
+    virtual int RunManagedLauncher() = 0;
+    virtual int Launch(const char* root, const char* path, int argc, char* argv[]) = 0;
+};
+
+struct AppInfo
+{
+  std::string root;
+  std::string path;
+  std::string id;
+  std::string pkg;
+  std::string type;
+};
+
+class LaunchpadAdapter
+{
+  public:
+    virtual void LoaderMain(int argc, char* argv[]) = 0;
+    std::function<void()> OnCreate = nullptr;
+    std::function<void(const AppInfo&, int, char**)> OnLaunch = nullptr;
+    std::function<void(const AppInfo&, int, char**)> OnTerminate = nullptr;
+};
+
+extern LaunchpadAdapter& Launchpad;
+
+}  // namespace runtime
+}  // namespace tizen
+
+#endif  // __LAUNCHER_INTERFACE_H__
diff --git a/NativeLauncher/launcher/main.cc b/NativeLauncher/launcher/main.cc
new file mode 100644 (file)
index 0000000..c43c299
--- /dev/null
@@ -0,0 +1,154 @@
+#include "dotnet/dotnet_launcher.h"
+#include "mono/mono_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <cstdio>
+#include <vector>
+#include <memory>
+
+#include <Ecore.h>
+#include <Eina.h>
+#include <aul.h>
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifndef VERSION
+#define LAUNCHER_VERSION_STR "-Unknown-"
+#else
+#define LAUNCHER_VERSION_STR __STR(VERSION)
+#endif
+
+static std::string VersionOption("--version");
+static std::string StandaloneOption("--standalone");
+
+int main(int argc, char *argv[])
+{
+  int i;
+  bool standalone = false;
+  const char* standalonePath = nullptr;
+
+  std::vector<char*> vargs;
+
+  for (i=0; i<argc; i++)
+  {
+    if (VersionOption.compare(argv[i]) == 0)
+    {
+      printf("Dotnet launcher Version %s\n", LAUNCHER_VERSION_STR);
+      return 0;
+    }
+    else if (StandaloneOption.compare(argv[i]) == 0)
+    {
+      standalone = true;
+
+      if (i > argc-1)
+      {
+        fprintf(stderr, "Assembly path must be after \"--standalone\" option\n");
+        return 1;
+      }
+      i++;
+      standalonePath = argv[i];
+    }
+    else
+    {
+      vargs.push_back(argv[i]);
+    }
+  }
+
+  using tizen::runtime::LauncherInterface;
+  using tizen::runtime::Launchpad;
+  using tizen::runtime::AppInfo;
+  std::unique_ptr<LauncherInterface> runtime;
+
+  bool useMono = !FileNotExist("/etc/.use_mono");
+
+  if (!useMono)
+  {
+    using tizen::runtime::dotnetcore::CoreRuntime;
+    std::unique_ptr<LauncherInterface> coreRuntime(new CoreRuntime());
+    runtime = std::move(coreRuntime);
+
+    _DBG("##### CoreCLR Launcher ######");
+  }
+  else
+  {
+    using tizen::runtime::mono::MonoRuntime;
+    std::unique_ptr<LauncherInterface> monoRuntime(new MonoRuntime());
+    runtime = std::move(monoRuntime);
+
+    _DBG("##### Mono Launcher ######");
+  }
+
+  if (standalone)
+  {
+    _DBG("##### Run it standalone #########");
+    const char* appid = getenv("AUL_APPID");
+    _DBG("AUL_APPID : %s", appid);
+    std::string approot;
+    if (appid != nullptr)
+    {
+      const char* approot_path = aul_get_app_root_path();
+      if (approot_path != nullptr)
+      {
+        approot = std::string(approot_path);
+      }
+    }
+    if (approot.empty())
+    {
+      approot = Basename(standalonePath);
+    }
+    if (runtime->Initialize(true) != 0)
+    {
+      _ERR("Failed to initialize");
+      return 1;
+    }
+
+    int args_len = vargs.size();
+    char** args = &vargs[0];
+    if (runtime->Launch(approot.c_str(), standalonePath, args_len, args))
+    {
+        _ERR("Failed to launch");
+        return 0;
+    }
+  }
+  else
+  {
+    Launchpad.OnCreate = [&runtime]()
+    {
+      if (runtime->Initialize(false) != 0)
+      {
+        _ERR("Failed to initialized");
+      }
+      else
+      {
+        auto idle_task = [](void *data) -> Eina_Bool
+        {
+          LauncherInterface* runtime = static_cast<LauncherInterface*>(data);
+          if (runtime->RunManagedLauncher() != 0)
+          {
+            _ERR("Failed to run managed launcher");
+          }
+          return ECORE_CALLBACK_CANCEL;
+        };
+        ecore_idler_add(idle_task, runtime.get());
+      }
+    };
+
+    Launchpad.OnTerminate = [&runtime](const AppInfo& info, int argc, char** argv)
+    {
+      _DBG("terminated with app path : %s", info.path.c_str());
+      _DBG("appid : %s", info.id.c_str());
+      _DBG("pkg : %s", info.pkg.c_str());
+      _DBG("type : %s", info.type.c_str());
+
+      if (runtime->Launch(info.root.c_str(), info.path.c_str(), argc, argv))
+      {
+        _ERR("Failed to launch");
+      }
+    };
+    Launchpad.LoaderMain(argc, argv);
+  }
+
+  return 0;
+}
diff --git a/NativeLauncher/launcher/mono/mono_launcher.cc b/NativeLauncher/launcher/mono/mono_launcher.cc
new file mode 100644 (file)
index 0000000..e0d0156
--- /dev/null
@@ -0,0 +1,248 @@
+
+#include "mono_launcher.h"
+#include "utils.h"
+#include "log.h"
+
+#include <dlfcn.h>
+#include <string>
+
+namespace tizen {
+namespace runtime {
+namespace mono {
+
+static const char* DOMAIN_NAME = "tizen_mono_domain";
+static const char* LIBMONO = "/usr/lib/libmono-2.0.so.1";
+
+MonoRuntime::MonoRuntime() :
+  monolib(nullptr),
+  domain(nullptr),
+  launch(nullptr)
+{
+
+#define __XSTR(x) #x
+#define __STR(x) __XSTR(x)
+
+#ifdef MONO_LAUNCHER_ASSEMBLY_PATH
+  launcherAssemblyPath = __STR(MONO_LAUNCHER_ASSEMBLY_PATH);
+#endif
+
+#ifdef DEVICE_API_DIR
+  deviceAPIDirectory = __STR(DEVICE_API_DIR);
+#endif
+#ifdef RUNTIME_DIR
+  runtimeDirectory = __STR(RUNTIME_DIR);
+#endif
+
+#undef __STR
+#undef __XSTR
+}
+
+MonoRuntime::~MonoRuntime()
+{
+  Dispose();
+}
+
+int MonoRuntime::Initialize(bool standalone)
+{
+  if (standalone)
+  {
+    const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
+    const char *_runtime_directory = getenv("RuntimeDirectory");
+    const char *_launcher_assembly = getenv("LauncherAssembly");
+    if (_deviceapi_directory != nullptr)
+      deviceAPIDirectory = _deviceapi_directory;
+    if (_runtime_directory != nullptr)
+      runtimeDirectory = _runtime_directory;
+    if (_launcher_assembly != nullptr)
+      launcherAssemblyPath = _launcher_assembly;
+  }
+
+  if (FileNotExist(LIBMONO))
+  {
+    _DBG("mono is not exist in %s", LIBMONO);
+    return 1;
+  }
+
+  monolib = dlopen(LIBMONO, RTLD_LAZY);
+#define MONOLIB_RETURN_IF_NOSYM(type, variable, name) \
+  do { \
+    variable = (type)dlsym(monolib, name); \
+    if (variable == nullptr) { \
+      _ERR(name " is not found in libmono"); \
+      return 1; \
+    }} while(0)
+
+  MONOLIB_RETURN_IF_NOSYM(mono_set_dirs_ptr, SetDirs, "mono_set_dirs");
+  MONOLIB_RETURN_IF_NOSYM(mono_set_assemblies_path_ptr, SetAssembliesPath, "mono_set_assemblies_path");
+  MONOLIB_RETURN_IF_NOSYM(mono_jit_init_ptr, JitInit, "mono_jit_init");
+  MONOLIB_RETURN_IF_NOSYM(mono_domain_assembly_open_ptr, DomainAssemblyOpen, "mono_domain_assembly_open");
+  MONOLIB_RETURN_IF_NOSYM(mono_assembly_get_image_ptr, AssemblyGetImage, "mono_assembly_get_image");
+  MONOLIB_RETURN_IF_NOSYM(mono_class_from_name_ptr, ClassFromName, "mono_class_from_name");
+  MONOLIB_RETURN_IF_NOSYM(mono_runtime_invoke_ptr, RuntimeInvoke, "mono_runtime_invoke");
+  MONOLIB_RETURN_IF_NOSYM(mono_class_get_method_from_name_ptr, ClassGetMethodFromName, "mono_class_get_method_from_name");
+  MONOLIB_RETURN_IF_NOSYM(mono_object_to_string_ptr, ObjectToString, "mono_object_to_string");
+  MONOLIB_RETURN_IF_NOSYM(mono_string_to_utf8_ptr, StringToUtf8, "mono_string_to_utf8");
+  MONOLIB_RETURN_IF_NOSYM(mono_string_new_ptr, NewString, "mono_string_new");
+  MONOLIB_RETURN_IF_NOSYM(mono_get_string_class_ptr, GetStringClass, "mono_get_string_class");
+  MONOLIB_RETURN_IF_NOSYM(mono_array_new_ptr, ArrayNew, "mono_array_new");
+  MONOLIB_RETURN_IF_NOSYM(mono_array_addr_with_size_ptr, ArrayAddrWithSize, "mono_array_addr_with_size");
+  MONOLIB_RETURN_IF_NOSYM(mono_jit_cleanup_ptr, DomainCleanup, "mono_jit_cleanup");
+  MONOLIB_RETURN_IF_NOSYM(mono_jit_exec_ptr, AssemblyExec, "mono_jit_exec");
+
+#undef MONOLIB_RETURN_IF_NOSYM
+
+  _DBG("libmono dlopen and dlsym success");
+
+  return 0;
+}
+
+void MonoRuntime::Dispose()
+{
+  if (domain != nullptr)
+  {
+    DomainCleanup(domain);
+  }
+  if (monolib != nullptr && dlclose(monolib) != 0)
+  {
+    _ERR("libmono close failed");
+  }
+  monolib = nullptr;
+}
+
+int MonoRuntime::RunManagedLauncher()
+{
+  if (FileNotExist(launcherAssemblyPath.c_str()))
+  {
+    _ERR("Launcher Assembly is not exist in %s", launcherAssemblyPath.c_str());
+    return 1;
+  }
+
+//  _DBG("mono_set_dirs(\"%s\", nullptr);", runtimeDirectory.c_str());
+//  _DBG("mono_set_assemblies_path(\"%s\");", deviceAPIDirectory.c_str());
+
+//  SetDirs(runtimeDirectory.c_str(), nullptr);
+/*
+  std::string assembliesPath = runtimeDirectory+":"+deviceAPIDirectory;
+  _DBG("assembliesPath : %s", assembliesPath.c_str());
+  SetAssembliesPath(assembliesPath.c_str());
+  */
+  SetAssembliesPath(deviceAPIDirectory.c_str());
+
+  domain = JitInit(DOMAIN_NAME);
+  if (domain == nullptr)
+  {
+    _ERR("Failed to init mono jit");
+    return 1;
+  }
+
+  launcherAssembly = DomainAssemblyOpen(domain, launcherAssemblyPath.c_str());
+  if (launcherAssembly == nullptr)
+  {
+    _ERR("Failed to Load Launcher Assembly");
+    return 1;
+  }
+
+  monoImage = AssemblyGetImage(launcherAssembly);
+  if (monoImage == nullptr)
+  {
+    _ERR("Failed to get image from launcher assembly");
+    return 1;
+  }
+
+  assemblyManagerClass = ClassFromName(monoImage, "Tizen.Runtime.Mono", "AssemblyManager");
+  if (assemblyManagerClass == nullptr)
+  {
+    _ERR("Failed to get AssemblyManager class in namespace Tizen.Runtime.Mono from launcher image");
+    return 1;
+  }
+
+  prepareLaunch = ClassGetMethodFromName(assemblyManagerClass, "Prepared", 0);
+  if (prepareLaunch == nullptr)
+  {
+    _ERR("Failed to get Prepared() method from Tizen.Runtime.Mono.AssemblyManager");
+    return 1;
+  }
+  MonoObject* exception = nullptr;
+  RuntimeInvoke(prepareLaunch, nullptr, nullptr, &exception);
+  if (exception != nullptr)
+  {
+    MonoString * exceptionMsg = ObjectToString(exception, nullptr);
+    char* cstringMsg = StringToUtf8(exceptionMsg);
+    _ERR("Failed to invoke method in runtime");
+    _ERR("%s", cstringMsg);
+    free(cstringMsg);
+    return 1;
+  }
+
+  launch = ClassGetMethodFromName(assemblyManagerClass, "Launch", 4);
+
+  return 0;
+}
+
+#define ArrayAddr(array,type,index) ((type*)(void*) ArrayAddrWithSize (array, sizeof (type), index))
+#define ArraySet(array,type,index,value)       \
+       do {    \
+               type *__p = (type *) ArrayAddr ((array), type, (index));        \
+               *__p = (value); \
+       } while (0)
+
+int MonoRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
+{
+  if (domain == nullptr)
+  {
+    domain = JitInit(DOMAIN_NAME);
+    if (domain == nullptr)
+    {
+      _ERR("Failed to init mono jit");
+      return 1;
+    }
+  }
+  if (launch != nullptr)
+  {
+    MonoString *rootMonoString = NewString(domain, root);
+    MonoString *pathMonoString = NewString(domain, path);
+    MonoArray *argvMonoArray = ArrayNew(domain, GetStringClass(), argc);
+    for (int i=0; i<argc; i++)
+    {
+      MonoString *arg = NewString(domain, argv[i]);
+      ArraySet(argvMonoArray, MonoString*, i, arg);
+    }
+
+    void **args = new void*[argc+2];
+    args[0] = rootMonoString;
+    args[1] = pathMonoString;
+    args[2] = &argc;
+    args[3] = argvMonoArray;
+
+    MonoObject* exception = nullptr;
+    RuntimeInvoke(launch, nullptr, args, &exception);
+    if (exception != nullptr)
+    {
+      MonoString * exceptionMsg = ObjectToString(exception, nullptr);
+      char* cstringMsg = StringToUtf8(exceptionMsg);
+      _ERR("Failed to invoke launch method in runtime");
+      _ERR("%s", cstringMsg);
+      free(cstringMsg);
+      return 1;
+    }
+  }
+  else
+  {
+    std::string appBin = ConcatPath(root, "bin");
+    std::string appLib = ConcatPath(root, "lib");
+    std::string probePath = deviceAPIDirectory + ":" + appBin + ":" + appLib;
+    SetAssembliesPath(probePath.c_str());
+    MonoAssembly* app = DomainAssemblyOpen(domain, path);
+    if (app == nullptr)
+    {
+      _ERR("Failed to open assembly : %s", path);
+      return 1;
+    }
+    AssemblyExec(domain, app, argc, argv);
+  }
+  return 0;
+}
+
+}  // namespace dotnetcore
+}  // namespace runtime
+}  // namespace mono
diff --git a/NativeLauncher/launcher/mono/mono_launcher.h b/NativeLauncher/launcher/mono/mono_launcher.h
new file mode 100644 (file)
index 0000000..d705d9e
--- /dev/null
@@ -0,0 +1,82 @@
+#include "launcher.h"
+
+extern "C"
+{
+  typedef struct _MonoDomain MonoDomain;
+  typedef struct _NonoAssembly MonoAssembly;
+  typedef struct _MonoImage MonoImage;
+  typedef struct _MonoClass MonoClass;
+  typedef struct _MonoObject MonoObject; 
+  typedef struct _MonoMethod MonoMethod;
+  typedef struct _MonoString MonoString;
+  typedef struct _MonoArray MonoArray;
+
+  typedef void          (*mono_set_dirs_ptr)                   (const char *, const char *);
+  typedef void          (*mono_set_assemblies_path_ptr)        (const char*);
+  typedef MonoDomain*   (*mono_jit_init_ptr)                   (const char *); 
+  typedef void          (*mono_config_parse_ptr)               (const char *);
+  typedef MonoAssembly* (*mono_domain_assembly_open_ptr)       (MonoDomain *, const char *);
+  typedef MonoImage*    (*mono_assembly_get_image_ptr)         (MonoAssembly *);
+  typedef MonoClass*    (*mono_class_from_name_ptr)            (MonoImage *, const char *, const char *);
+  typedef MonoObject*   (*mono_runtime_invoke_ptr)             (MonoMethod *, void *, void **, MonoObject **);
+  typedef MonoMethod*   (*mono_class_get_method_from_name_ptr) (MonoClass *, const char *, int param_count);
+  typedef MonoString*   (*mono_string_new_ptr)                 (MonoDomain *, const char *);
+  typedef MonoString*   (*mono_object_to_string_ptr)           (MonoObject *, MonoObject **);
+  typedef char*         (*mono_string_to_utf8_ptr)             (MonoString *string_obj);
+
+  typedef MonoClass*    (*mono_get_string_class_ptr)           ();
+  typedef MonoArray*    (*mono_array_new_ptr)                  (MonoDomain *, MonoClass *, uintptr_t);
+  typedef char*         (*mono_array_addr_with_size_ptr)       (MonoArray *, int, uintptr_t); 
+  typedef void          (*mono_jit_cleanup_ptr)                (MonoDomain *domain);
+  typedef int           (*mono_jit_exec_ptr)                   (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
+}
+
+namespace tizen {
+namespace runtime {
+namespace mono {
+
+class MonoRuntime : public tizen::runtime::LauncherInterface
+{
+  public:
+    MonoRuntime();
+    ~MonoRuntime();
+    int Initialize(bool standalone) override;
+    void Dispose() override;
+    int RunManagedLauncher() override;
+    int Launch(const char* root, const char* path, int argc, char* argv[]) override;
+
+  private:
+    void* monolib;
+    mono_set_dirs_ptr SetDirs;
+    mono_set_assemblies_path_ptr SetAssembliesPath;
+    mono_jit_init_ptr JitInit;
+    mono_domain_assembly_open_ptr DomainAssemblyOpen;
+    mono_assembly_get_image_ptr AssemblyGetImage;
+    mono_class_from_name_ptr ClassFromName;
+    mono_runtime_invoke_ptr RuntimeInvoke;
+    mono_class_get_method_from_name_ptr ClassGetMethodFromName;
+    mono_object_to_string_ptr ObjectToString;
+    mono_string_to_utf8_ptr StringToUtf8;
+    mono_string_new_ptr NewString;
+    mono_get_string_class_ptr GetStringClass;
+    mono_array_new_ptr ArrayNew;
+    mono_array_addr_with_size_ptr ArrayAddrWithSize;
+    mono_jit_cleanup_ptr DomainCleanup;
+    mono_jit_exec_ptr AssemblyExec;
+
+    MonoDomain* domain;
+    MonoAssembly* launcherAssembly;
+    MonoImage* monoImage;
+    MonoClass* assemblyManagerClass;
+    MonoMethod* prepareLaunch;
+    MonoMethod* launch;
+
+    std::string launcherAssemblyPath;
+    std::string deviceAPIDirectory;
+    std::string runtimeDirectory;
+};
+
+
+}  // namespace mono
+}  // namespace runtime
+}  // namespace tizen
diff --git a/NativeLauncher/launcher/waiter/waiter.cc b/NativeLauncher/launcher/waiter/waiter.cc
new file mode 100644 (file)
index 0000000..6447d4a
--- /dev/null
@@ -0,0 +1,295 @@
+
+#include <poll.h>
+
+#ifndef NO_TIZEN
+#include <launchpad.h>
+#include <aul.h>
+#endif
+
+#include <memory>
+#include <vector>
+#include <map>
+#include <poll.h>
+
+#include <iostream>
+
+#include "waiter.h"
+#include "log.h"
+
+namespace dotnet {
+namespace runtime {
+
+struct FdHandler
+{
+  pollfd *info;
+  Receiver receiver;
+};
+
+static volatile bool Waiting_;
+static std::vector<pollfd> Fdlist_;
+static std::map<int, FdHandler> Handlers_;
+static Waiter::AppInfo AppInfo_;
+
+void Waiter::OnPrepared()
+{
+  if (!context.Prepare())
+  {
+    _DBG("Fail to Prepare...");
+  }
+}
+
+void Waiter::OnRequested(const AppInfo& info)
+{
+  // do some job on user id is still system
+
+  if (!context.Request())
+  {
+    _DBG("Fail to Request...");
+  }
+}
+
+void Waiter::OnExecuted(const char *path, const char *app_root, int argc, char *argv[])
+{
+  if (!context.Execute(path, app_root, argc, argv))
+  {
+    _DBG("Fail to Execute...");
+  }
+}
+
+void Waiter::OnWaiting()
+{
+  // Start the loop
+  Waiting_ = true;
+
+  _DBG("start polling...");
+  while (Waiting_)
+  {
+    if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
+      continue;
+
+    for (auto &p : Fdlist_)
+    {
+      if ( (p.revents | POLLIN) != 0 )
+        Handlers_[p.fd].receiver(p.fd);
+    }
+  }
+  _DBG("end polling...");
+}
+
+void Waiter::Stop()
+{
+  // Stop the loop
+
+  Waiting_ = false;
+}
+
+
+void Waiter::RegisterFd(int fd, Receiver receiver)
+{
+  // register fd should be caught in event loop
+
+  _DBG("Register fd %d", fd);
+
+  pollfd info;
+  info.fd = fd;
+  info.events = POLLIN;
+  info.revents = 0;
+
+  FdHandler handler;
+  Fdlist_.push_back(info);
+  handler.info = &Fdlist_.back(); 
+  handler.receiver = receiver;
+
+  Handlers_[fd] = handler;
+}
+
+void Waiter::DeregisterFd(int fd)
+{
+  // deregister fd should be caught in event loop
+  
+  pollfd *info = Handlers_[fd].info;
+  Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
+  Handlers_.erase(fd);
+}
+
+int Waiter::WaitToLaunching(int argc, char *argv[])
+{
+#ifndef NO_TIZEN
+  auto on_create = [](bundle *extra, int type, void *user_data)
+  {
+    _DBG("on_create..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->OnPrepared();
+  };
+
+  auto on_launch = [](int argc, char **argv, const char *app_path,
+      const char *appid, const char *pkgid,
+      const char *pkg_type, void *user_data) -> int
+  {
+    _DBG("on_launch..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+
+    _DBG ("app path : %s", app_path);
+    _DBG ("app id : %s", appid);
+    _DBG ("pkg id : %s", pkgid);
+    _DBG ("pkg type : %s", pkg_type);
+
+    AppInfo info = {
+      AppPath : app_path,
+      AppId : appid,
+      PkgId : pkgid,
+      PkgType : pkg_type
+    };
+
+    waiter->OnRequested(info);
+    return 0;
+  };
+
+  auto on_terminate = [](int argc, char **argv, void *user_data) -> int
+  {
+    _DBG("on_terminate..."); // XXX
+    
+    string app_root(aul_get_app_root_path());
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->OnExecuted(argv[0], app_root.c_str(), argc, argv);
+    return 0;
+  };
+
+  auto on_start_loop = [](void *user_data)
+  {
+    _DBG("on_start_loop..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->OnWaiting();
+  };
+
+  auto on_quit_loop = [](void *user_data)
+  {
+    _DBG("on_quit_loop..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->Stop();
+  };
+
+  auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
+  {
+    _DBG("on_add_fd..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->RegisterFd(fd, receiver);
+  };
+
+  auto on_remove_fd = [](void *user_data, int fd)
+  {
+    _DBG("on_remove_fd..."); // XXX
+    Waiter* waiter = static_cast<Waiter*>(user_data);
+    waiter->DeregisterFd(fd);
+  };
+
+  _DBG("launcher wait..."); // XXX
+  loader_lifecycle_callback_s callbacks = {
+    .create = on_create,
+    .launch = on_launch,
+    .terminate = on_terminate
+  };
+
+       loader_adapter_s adapter = {
+               .loop_begin = on_start_loop,
+               .loop_quit = on_quit_loop,
+               .add_fd = on_add_fd,
+               .remove_fd = on_remove_fd
+       };
+
+  return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
+#else
+  if (argc < 2)
+  {
+    _DBG("not enough args : %d", argc);
+    return -1;
+  }
+  _DBG("argv[1] = %s", argv[1]);
+  std::string app_path(argv[1]);
+  std::string app_root;
+  auto pos = app_path.find_last_of('/');
+  if (pos != std::string::npos)
+    app_root = app_path.substr(0, pos);
+  else
+    app_root = ".";
+
+  this->OnPrepared();
+  AppInfo info = {
+    AppPath : argv[1],
+    AppId : "",
+    PkgId : "",
+    PkgType : ""
+  };
+  this->OnRequested(info);
+  this->OnExecuted(app_path.c_str(), app_root.c_str(), argc, argv);
+#endif
+}
+
+void Waiter::SetContext(WaiterContext ctx)
+{
+  context = ctx;
+}
+
+WaiterContext::WaiterContext()
+{
+  Step = Status::Started;
+}
+
+bool WaiterContext::Prepare()
+{
+  if (Step == Status::Started && Prepared != nullptr && Prepared(Data) == 0)
+  {
+    Step = Status::Prepared;
+    return true;
+  }
+  return false;
+}
+
+bool WaiterContext::Request()
+{
+  if (Step == Status::Prepared && Requested != nullptr && Requested(Data) == 0)
+  {
+    Step = Status::Requested;
+    return true;
+  }
+  return false;
+}
+
+bool WaiterContext::Execute(const char *path, const char *app_root, int argc, char *argv[])
+{
+  if (Step == Status::Requested && Executed != nullptr &&
+      Executed(path, app_root, argc, argv, Data) == 0)
+  {
+    Step = Status::Executed;
+    return true;
+  }
+  return false;
+}
+
+}  // namespace runtime
+}  // namespace dotnet
+
+using dotnet::runtime::Waiter;
+using dotnet::runtime::WaiterContext;
+
+static Waiter waiter;
+
+void register_launching_callback(prepared_callback prepared,
+    requested_callback requested, executed_callback executed, void *data)
+{
+  WaiterContext context;
+  context.Prepared = prepared;
+  context.Requested = requested;
+  context.Executed = executed;
+  context.Data = data;
+
+  waiter.SetContext(context);
+}
+
+void wait_for_launching(int argc, char *argv[])
+{
+  _DBG("wait_for_launching...");
+
+  waiter.WaitToLaunching(argc, argv);
+}
+
diff --git a/NativeLauncher/launcher/waiter/waiter.h b/NativeLauncher/launcher/waiter/waiter.h
new file mode 100644 (file)
index 0000000..c4b98fb
--- /dev/null
@@ -0,0 +1,77 @@
+#include <string>
+#include <functional>
+
+#include <iostream>
+
+extern "C" {
+  typedef int (*prepared_callback)(void *data);
+  typedef int (*requested_callback)(void *data);
+  typedef int (*executed_callback)(const char* path, const char* app_root, int argc, char *argv[], void *data);
+
+  void register_launching_callback(prepared_callback prepared,
+      requested_callback requested, executed_callback executed, void *data);
+  void wait_for_launching(int argc, char *argv[]);
+}
+
+namespace dotnet {
+namespace runtime {
+
+using std::string;
+using Receiver = std::function<void(int)>;
+
+enum Status
+{
+  Started,
+  Prepared,
+  Requested,
+  Executed
+};
+
+class WaiterContext
+{
+  public:
+    prepared_callback Prepared;
+    requested_callback Requested;
+    executed_callback Executed;
+
+    void *Data;
+
+    WaiterContext();
+    bool Prepare();
+    bool Request();
+    bool Execute(const char *path, const char *app_root, int argc, char *argv[]);
+
+  private:
+    Status Step;
+};
+
+class Waiter
+{
+  public:
+    struct AppInfo
+    {
+      string AppPath;
+      string AppId;
+      string PkgId;
+      string PkgType;
+    };
+
+    int WaitToLaunching(int argc, char *argv[]);
+    void Stop();
+
+    void RegisterFd(int fd, Receiver receiver);
+    void DeregisterFd(int fd);
+    void SetContext(WaiterContext ctx);
+
+  protected:
+    void OnPrepared();
+    void OnRequested(const AppInfo&);
+    void OnWaiting();
+    void OnExecuted(const char *path, const char *app_root, int argc, char *argv[]);
+
+  private:
+    WaiterContext context;
+};
+
+}  // namespace runtime
+}  // namespace dotnet
diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.cc b/NativeLauncher/src/dotnet/dotnet_launcher.cc
deleted file mode 100644 (file)
index ce880a9..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-
-#include <dlfcn.h>
-
-#include <string>
-#include <fstream>
-#include <vector>
-
-#include "utils.h"
-#include "log.h"
-#include "launcher.h"
-#include "dotnet_launcher.h"
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-CoreRuntime::CoreRuntime() :
-  coreclrLib(nullptr),
-  hostHandle(nullptr),
-  domainId(-1),
-  PreparedFunction(nullptr),
-  LaunchFunction(nullptr),
-  InitializeClr(nullptr),
-  ExecuteAssembly(nullptr),
-  Shutdown(nullptr),
-  CreateDelegate(nullptr)
-{
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifdef DEVICE_API_DIR
-  DeviceAPIDirectory = __STR(DEVICE_API_DIR);
-#endif
-#ifdef RUNTIME_DIR
-  RuntimeDirectory = __STR(RUNTIME_DIR);
-#endif
-#ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
-  LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
-#endif
-
-#undef __STR
-#undef __XSTR
-
-  _DBG("Constructor called!!");
-}
-
-CoreRuntime::~CoreRuntime()
-{
-  Dispose();
-}
-
-int CoreRuntime::Initialize(bool standalone)
-{
-
-  if (standalone)
-  {
-    const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
-    const char *_runtime_directory = getenv("RuntimeDirectory");
-    const char *_launcher_assembly = getenv("LauncherAssembly");
-    if (_deviceapi_directory != nullptr)
-      DeviceAPIDirectory = _deviceapi_directory;
-    if (_runtime_directory != nullptr)
-      RuntimeDirectory = _runtime_directory;
-    if (_launcher_assembly != nullptr)
-      LauncherAssembly = _launcher_assembly;
-  }
-
-  if (DeviceAPIDirectory.empty())
-  {
-    _ERR("Empty Device API Directory");
-    return 1;
-  }
-  else
-  {
-    DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
-  }
-  if (RuntimeDirectory.empty())
-  {
-    _ERR("Empty Runtime Directory");
-    return 1;
-  }
-  else
-  {
-    RuntimeDirectory = AbsolutePath(RuntimeDirectory);
-  }
-  if (LauncherAssembly.empty())
-  {
-    _ERR("Empty Launcher Assembly");
-    return 1;
-  }
-  else
-  {
-    LauncherAssembly = AbsolutePath(LauncherAssembly);
-  }
-
-  std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
-
-  _DBG("libcoreclr : %s", libcoreclr.c_str());
-
-  coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
-  if (coreclrLib == nullptr)
-  {
-    char *err = dlerror();
-    _ERR("dlopen failed to open libcoreclr.so with error %s", err);
-    return 1;
-  }
-
-#define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
-  do { variable = (type)dlsym(coreclrLib, name); \
-    if (variable == nullptr) { \
-      _ERR(name " is not found in the libcoreclr.so"); \
-      return 1; \
-    }} while(0)
-
-  CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
-  CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
-  CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
-  CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
-
-#undef CORELIB_RETURN_IF_NOSYM
-
-  _DBG("libcoreclr dlopen and dlsym success");
-
-  _DBG("this addr : %x", this);
-  _DBG("coreclr_initialize : %x", InitializeClr);
-
-  return 0;
-}
-
-bool CoreRuntime::InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths)
-{
-  std::vector<std::string> platformDirectories = {
-    RuntimeDirectory, DeviceAPIDirectory
-  };
-
-  std::string trusted_assemblies;
-  AssembliesInDirectory(platformDirectories, trusted_assemblies);
-
-  const char *propertyKeys[] =
-  {
-    "TRUSTED_PLATFORM_ASSEMBLIES",
-    "APP_PATHS",
-    "APP_NI_PATHS",
-    "NATIVE_DLL_SEARCH_DIRECTORIES",
-    "AppDomainCompatSwitch"
-  };
-
-  const char *propertyValues[] =
-  {
-    trusted_assemblies.c_str(),
-    assembly_probe_paths,
-    assembly_probe_paths,
-    pinvoke_probe_paths,
-    "UseLatestBehaviorWhenTFMNotSpecified"
-  };
-
-  std::string selfPath = ReadSelfPath();
-
-  int st = InitializeClr(
-      selfPath.c_str(),
-      "dotnet-launcher",
-      sizeof(propertyKeys) / sizeof(propertyKeys[0]),
-      propertyKeys,
-      propertyValues,
-      &hostHandle,
-      &domainId);
-
-  if (st < 0)
-  {
-    _ERR("initialize core clr fail! (0x%08x)", st);
-    return false;
-  }
-
-  _DBG("Initialize core clr success");
-  return true;
-}
-
-int CoreRuntime::RunManagedLauncher()
-{
-  if (FileNotExist(LauncherAssembly))
-  {
-    _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
-    return 1;
-  }
-
-  std::string launcherDir = Basename(LauncherAssembly);
-  std::vector<std::string> searchDirectories = {
-    RuntimeDirectory, DeviceAPIDirectory
-  };
-
-  std::string trusted_directories = JoinStrings(searchDirectories, ":");
-
-  _DBG("coreclr_dir : %s", RuntimeDirectory.c_str());
-  _DBG("native_so_search_dir : %s", trusted_directories.c_str());
-  _DBG("launcher_assembly : %s", LauncherAssembly.c_str());
-  _DBG("launcher_dir : %s", launcherDir.c_str());
-
-  if (!InitializeCoreClr(launcherDir.c_str(), launcherDir.c_str()))
-  {
-    _ERR("Failed to initialize coreclr");
-    return 1;
-  }
-
-  void *preparedFunctionDelegate;
-  int st = CreateDelegate(hostHandle, domainId,
-      "Tizen.Runtime.Coreclr",
-      "Tizen.Runtime.Coreclr.AssemblyManager",
-      "Prepared", &preparedFunctionDelegate);
-  if (st < 0)
-  {
-    _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
-    return 1;
-  }
-  PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
-
-  if(PreparedFunction != nullptr)
-  {
-    PreparedFunction();
-  }
-
-  void *launchFunctionDelegate;
-  st = CreateDelegate(hostHandle, domainId,
-      "Tizen.Runtime.Coreclr",
-      "Tizen.Runtime.Coreclr.AssemblyManager",
-      "Launch", &launchFunctionDelegate);
-  if (st < 0)
-  {
-    _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
-    return 1;
-  }
-  LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
-
-  return 0;
-}
-
-void CoreRuntime::Dispose()
-{
-  if (hostHandle != nullptr)
-  {
-    int st = Shutdown(hostHandle, domainId);
-    if (st < 0)
-    {
-      _ERR("shutdown core clr fail! (0x%08x)", st);
-    }
-  }
-
-  if (dlclose(coreclrLib) != 0)
-  {
-    _ERR("libcoreclr.so close failed");
-  }
-  coreclrLib = nullptr;
-
-  _DBG("Dotnet runtime disposed");
-}
-
-int CoreRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
-{
-  if (path == nullptr)
-  {
-    _ERR("executable path is null");
-    return 1;
-  }
-
-  if (FileNotExist(path))
-  {
-    _ERR("File not exist : %s", path);
-    return 1;
-  }
-
-  bool success = false;
-  if (LaunchFunction != nullptr)
-  {
-    success = LaunchFunction(root, path, argc, argv);
-    if (!success)
-    {
-      _ERR("Failed to launch Application %s", path);
-    }
-    return success ? 0 : 1;
-  }
-  else
-  {
-    std::string appRoot = root;
-    std::string appBin = ConcatPath(appRoot, "bin");
-    std::string appLib = ConcatPath(appRoot, "lib");
-    std::string probePath = appBin + ":" + appLib;
-
-    int st = InitializeCoreClr(probePath.c_str(), probePath.c_str());
-    unsigned int ret = 0;
-    st = ExecuteAssembly(hostHandle, domainId, argc, (const char**)argv, path, &ret);
-    if (st < 0)
-    {
-      _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
-    }
-    return ret;
-  }
-}
-
-}  // namespace dotnetcore
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/src/dotnet/dotnet_launcher.h b/NativeLauncher/src/dotnet/dotnet_launcher.h
deleted file mode 100644 (file)
index fa72e11..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "launcher.h"
-
-extern "C"
-{
-  typedef int (*coreclr_initialize_ptr)(
-      const char* exePath,
-      const char* appDomainFriendlyName,
-      int propertyCount,
-      const char** propertyKeys,
-      const char** propertyValues,
-      void** hostHandle,
-      unsigned int* domainId);
-
-  typedef int (*coreclr_execute_assembly_ptr)(
-      void* hostHandle,
-      unsigned int domainId,
-      int argc,
-      const char** argv,
-      const char* managedAssemblyPath,
-      unsigned int* exitCode);
-
-  typedef int (*coreclr_shutdown_ptr)(
-      void* hostHandle,
-      unsigned int domainId);
-
-  typedef int (*coreclr_create_delegate_ptr)(
-      void* hostHandle,
-      unsigned int domainId,
-      const char* entryPointAssemblyName,
-      const char* entryPointTypeName,
-      const char* entryPointMethodName,
-      void** delegate);
-}
-
-namespace tizen {
-namespace runtime {
-namespace dotnetcore {
-
-typedef void (*PreparedFunctionPtr)();
-typedef bool (*LaunchFunctionPtr)(const char* root, const char* path, int argc, char* argv[]);
-
-class CoreRuntime : public tizen::runtime::LauncherInterface
-{
-  public:
-    CoreRuntime();
-    ~CoreRuntime();
-    int Initialize(bool standalone) override;
-    void Dispose() override;
-    int RunManagedLauncher() override;
-    int Launch(const char* root, const char* path, int argc, char* argv[]) override;
-
-  private:
-    bool InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths);
-    coreclr_initialize_ptr InitializeClr;
-    coreclr_execute_assembly_ptr ExecuteAssembly;
-    coreclr_shutdown_ptr Shutdown;
-    coreclr_create_delegate_ptr CreateDelegate;
-    std::string DeviceAPIDirectory;
-    std::string RuntimeDirectory;
-    std::string LauncherAssembly;
-    void* coreclrLib;
-    void* hostHandle;
-    unsigned int domainId;
-    PreparedFunctionPtr PreparedFunction;
-    LaunchFunctionPtr LaunchFunction;
-};
-
-}  // dotnetcore
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/src/launcher.cc b/NativeLauncher/src/launcher.cc
deleted file mode 100644 (file)
index 9efd49e..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-#include "launcher.h"
-#include "log.h"
-
-#include <launchpad.h>
-#include <aul.h>
-
-#include <Ecore.h>
-
-#include <map>
-#include <vector>
-#include <functional>
-
-#include <unistd.h>
-
-
-namespace tizen {
-namespace runtime {
-
-struct FdHandler
-{
-  Ecore_Fd_Handler *handler;
-  loader_receiver_cb receiver;
-};
-
-class LaunchpadAdapterImpl : public LaunchpadAdapter
-{
-  public:
-    LaunchpadAdapterImpl() : isLaunched(false) { }
-    void LoaderMain(int argc, char* argv[]) override;
-
-    std::map<int, FdHandler> Handlers;
-
-  private:
-    AppInfo appinfo;
-    loader_lifecycle_callback_s callbacks;
-    loader_adapter_s adapter;
-    LauncherInterface* launcher;
-    bool isLaunched;
-    std::string launchPath;
-};
-
-LaunchpadAdapterImpl LaunchpadImpl;
-LaunchpadAdapter& Launchpad = LaunchpadImpl;
-
-#define WITH_SELF(data) \
-  LaunchpadAdapterImpl* self = static_cast<LaunchpadAdapterImpl*>(data); \
-  if (self == nullptr) \
-  { \
-    _ERR("No LaunchpadImplData"); \
-  } else
-
-static Eina_Bool Fd_Handler(void *data, Ecore_Fd_Handler* handler)
-{
-  WITH_SELF(data)
-  {
-    int fd = ecore_main_fd_handler_fd_get(handler);
-    if (fd == -1)
-    {
-      _ERR("Failed to get the Ecore FD");
-      exit(-1);
-    }
-
-    if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
-    {
-      if (self->Handlers.find(fd) != self->Handlers.end())
-      {
-        self->Handlers[fd].receiver(fd);
-      }
-    }
-    else if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
-    {
-      _ERR("Ecore FD Handler Have Error");
-      close(fd);
-      exit(-1);
-    }
-  }
-
-  return ECORE_CALLBACK_CANCEL;
-}
-
-static void Fd_Add(void *data, int fd, loader_receiver_cb receiver)
-{
-  Ecore_Fd_Handler* handler = ecore_main_fd_handler_add(fd,
-      static_cast<Ecore_Fd_Handler_Flags>(ECORE_FD_READ | ECORE_FD_ERROR),
-      Fd_Handler, data, nullptr, nullptr);
-  if (handler == nullptr)
-  {
-    _ERR("Failed to add a FD handler to ecore main loop");
-    close(fd);
-    exit(-1);
-  }
-  WITH_SELF(data)
-  {
-    self->Handlers[fd] = {handler, receiver};
-  }
-}
-
-static void Fd_Remove(void *data, int fd)
-{
-  WITH_SELF(data)
-  {
-    if (self->Handlers.find(fd) != self->Handlers.end())
-    {
-      Ecore_Fd_Handler* handler = self->Handlers[fd].handler;
-      ecore_main_fd_handler_del(handler);
-      self->Handlers.erase(fd);
-    }
-  }
-}
-
-void LaunchpadAdapterImpl::LoaderMain(int argc, char* argv[])
-{
-
-  callbacks.create = [](bundle *extra, int type, void *user_data)
-  {
-    ecore_init();
-    WITH_SELF(user_data)
-    {
-      if (self->OnCreate != nullptr)
-        self->OnCreate();
-    }
-  };
-  callbacks.launch = [](int argc, char** argv, const char* app_path,
-      const char* appid, const char* pkgid,
-      const char* pkg_type, void* user_data) -> int
-  {
-    WITH_SELF(user_data)
-    {
-      self->appinfo.root = std::string(aul_get_app_root_path());
-      self->appinfo.path = app_path;
-      self->appinfo.id = appid;
-      self->appinfo.pkg = pkgid;
-      self->appinfo.type = pkg_type;
-      if (self->OnLaunch != nullptr)
-        self->OnLaunch(self->appinfo, argc, argv);
-    }
-
-    return 0;
-  };
-  callbacks.terminate = [](int argc, char **argv, void* user_data) -> int
-  {
-    _DBG("Terminate!!");
-    WITH_SELF(user_data)
-    {
-      if (self->OnTerminate != nullptr)
-        self->OnTerminate(self->appinfo, argc, argv);
-    }
-    return 0;
-  };
-
-  adapter.loop_begin = [](void *data)
-  {
-    ecore_main_loop_begin();
-  };
-
-  adapter.loop_quit = [](void *data)
-  {
-    ecore_main_loop_quit();
-  };
-  adapter.add_fd = Fd_Add;
-  adapter.remove_fd = Fd_Remove;
-
-  _DBG("launchpad_loader_main is start");
-  int r = launchpad_loader_main(argc, argv, &(this->callbacks), &(this->adapter), this);
-  _DBG("launchpad_loader_main is finished with [%d]", r);
-}
-
-#undef WITH_SELF
-
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/src/main.cc b/NativeLauncher/src/main.cc
deleted file mode 100644 (file)
index 18085b7..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-#include "dotnet/dotnet_launcher.h"
-#include "mono/mono_launcher.h"
-#include "utils.h"
-#include "log.h"
-
-#include <cstdio>
-#include <vector>
-#include <memory>
-
-#include <Ecore.h>
-#include <Eina.h>
-#include <aul.h>
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifndef VERSION
-#define LAUNCHER_VERSION_STR "-Unknown-"
-#else
-#define LAUNCHER_VERSION_STR __STR(VERSION)
-#endif
-
-static std::string VersionOption("--version");
-static std::string StandaloneOption("--standalone");
-
-int main(int argc, char *argv[])
-{
-  int i;
-  bool standalone = false;
-  const char* standalonePath = nullptr;
-
-  std::vector<char*> vargs;
-
-  for (i=0; i<argc; i++)
-  {
-    if (VersionOption.compare(argv[i]) == 0)
-    {
-      printf("Dotnet launcher Version %s\n", LAUNCHER_VERSION_STR);
-      return 0;
-    }
-    else if (StandaloneOption.compare(argv[i]) == 0)
-    {
-      standalone = true;
-
-      if (i > argc-1)
-      {
-        fprintf(stderr, "Assembly path must be after \"--standalone\" option\n");
-        return 1;
-      }
-      i++;
-      standalonePath = argv[i];
-    }
-    else
-    {
-      vargs.push_back(argv[i]);
-    }
-  }
-
-  using tizen::runtime::LauncherInterface;
-  using tizen::runtime::Launchpad;
-  using tizen::runtime::AppInfo;
-  std::unique_ptr<LauncherInterface> runtime;
-
-  bool useMono = !FileNotExist("/etc/.use_mono");
-
-  if (!useMono)
-  {
-    using tizen::runtime::dotnetcore::CoreRuntime;
-    std::unique_ptr<LauncherInterface> coreRuntime(new CoreRuntime());
-    runtime = std::move(coreRuntime);
-
-    _DBG("##### CoreCLR Launcher ######");
-  }
-  else
-  {
-    using tizen::runtime::mono::MonoRuntime;
-    std::unique_ptr<LauncherInterface> monoRuntime(new MonoRuntime());
-    runtime = std::move(monoRuntime);
-
-    _DBG("##### Mono Launcher ######");
-  }
-
-  if (standalone)
-  {
-    _DBG("##### Run it standalone #########");
-    const char* appid = getenv("AUL_APPID");
-    _DBG("AUL_APPID : %s", appid);
-    std::string approot;
-    if (appid != nullptr)
-    {
-      const char* approot_path = aul_get_app_root_path();
-      if (approot_path != nullptr)
-      {
-        approot = std::string(approot_path);
-      }
-    }
-    if (approot.empty())
-    {
-      approot = Basename(standalonePath);
-    }
-    if (runtime->Initialize(true) != 0)
-    {
-      _ERR("Failed to initialize");
-      return 1;
-    }
-
-    int args_len = vargs.size();
-    char** args = &vargs[0];
-    if (runtime->Launch(approot.c_str(), standalonePath, args_len, args))
-    {
-        _ERR("Failed to launch");
-        return 0;
-    }
-  }
-  else
-  {
-    Launchpad.OnCreate = [&runtime]
-    {
-      auto idle_task = [](void *data) -> Eina_Bool 
-      {
-        LauncherInterface* runtime = static_cast<LauncherInterface*>(data);
-        if (runtime->RunManagedLauncher() != 0)
-        {
-          _ERR("Failed to run managed launcher");
-        }
-        return ECORE_CALLBACK_CANCEL;
-      };
-      if (runtime->Initialize(false) != 0)
-      {
-        _ERR("Failed to initialized");
-        return 1;
-      }
-      ecore_idler_add(idle_task, runtime.get());
-    };
-
-    Launchpad.OnTerminate = [&runtime](const AppInfo& info, int argc, char** argv)
-    {
-      _DBG("terminated with app path : %s", info.path.c_str());
-      _DBG("appid : %s", info.id.c_str());
-      _DBG("pkg : %s", info.pkg.c_str());
-      _DBG("type : %s", info.type.c_str());
-
-      if (runtime->Launch(info.root.c_str(), info.path.c_str(), argc, argv))
-      {
-        _ERR("Failed to launch");
-      }
-    };
-    Launchpad.LoaderMain(argc, argv);
-  }
-
-  return 0;
-}
diff --git a/NativeLauncher/src/mono/mono_launcher.cc b/NativeLauncher/src/mono/mono_launcher.cc
deleted file mode 100644 (file)
index 8636447..0000000
+++ /dev/null
@@ -1,248 +0,0 @@
-
-#include "mono_launcher.h"
-#include "utils.h"
-#include "log.h"
-
-#include <dlfcn.h>
-#include <string>
-
-namespace tizen {
-namespace runtime {
-namespace mono {
-
-static const char* DOMAIN_NAME = "tizen_mono_domain";
-static const char* LIBMONO = "/usr/lib/libmono-2.0.so.1";
-
-MonoRuntime::MonoRuntime() :
-  monolib(nullptr),
-  domain(nullptr),
-  launch(nullptr)
-{
-
-#define __XSTR(x) #x
-#define __STR(x) __XSTR(x)
-
-#ifdef MONO_LAUNCHER_ASSEMBLY_PATH
-  launcherAssemblyPath = __STR(MONO_LAUNCHER_ASSEMBLY_PATH);
-#endif
-
-#ifdef DEVICE_API_DIR
-  deviceAPIDirectory = __STR(DEVICE_API_DIR);
-#endif
-#ifdef RUNTIME_DIR
-  runtimeDirectory = __STR(RUNTIME_DIR);
-#endif
-
-#undef __STR
-#undef __XSTR
-}
-
-MonoRuntime::~MonoRuntime()
-{
-  Dispose();
-}
-
-int MonoRuntime::Initialize(bool standalone)
-{
-  if (standalone)
-  {
-    const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
-    const char *_runtime_directory = getenv("RuntimeDirectory");
-    const char *_launcher_assembly = getenv("LauncherAssembly");
-    if (_deviceapi_directory != nullptr)
-      deviceAPIDirectory = _deviceapi_directory;
-    if (_runtime_directory != nullptr)
-      runtimeDirectory = _runtime_directory;
-    if (_launcher_assembly != nullptr)
-      launcherAssemblyPath = _launcher_assembly;
-  }
-
-  if (FileNotExist(LIBMONO))
-  {
-    _DBG("mono is not exist in %s", LIBMONO);
-    return 1;
-  }
-
-  monolib = dlopen(LIBMONO, RTLD_LAZY);
-#define MONOLIB_RETURN_IF_NOSYM(type, variable, name) \
-  do { \
-    variable = (type)dlsym(monolib, name); \
-    if (variable == nullptr) { \
-      _ERR(name " is not found in libmono"); \
-      return 1; \
-    }} while(0)
-
-  MONOLIB_RETURN_IF_NOSYM(mono_set_dirs_ptr, SetDirs, "mono_set_dirs");
-  MONOLIB_RETURN_IF_NOSYM(mono_set_assemblies_path_ptr, SetAssembliesPath, "mono_set_assemblies_path");
-  MONOLIB_RETURN_IF_NOSYM(mono_jit_init_ptr, JitInit, "mono_jit_init");
-  MONOLIB_RETURN_IF_NOSYM(mono_domain_assembly_open_ptr, DomainAssemblyOpen, "mono_domain_assembly_open");
-  MONOLIB_RETURN_IF_NOSYM(mono_assembly_get_image_ptr, AssemblyGetImage, "mono_assembly_get_image");
-  MONOLIB_RETURN_IF_NOSYM(mono_class_from_name_ptr, ClassFromName, "mono_class_from_name");
-  MONOLIB_RETURN_IF_NOSYM(mono_runtime_invoke_ptr, RuntimeInvoke, "mono_runtime_invoke");
-  MONOLIB_RETURN_IF_NOSYM(mono_class_get_method_from_name_ptr, ClassGetMethodFromName, "mono_class_get_method_from_name");
-  MONOLIB_RETURN_IF_NOSYM(mono_object_to_string_ptr, ObjectToString, "mono_object_to_string");
-  MONOLIB_RETURN_IF_NOSYM(mono_string_to_utf8_ptr, StringToUtf8, "mono_string_to_utf8");
-  MONOLIB_RETURN_IF_NOSYM(mono_string_new_ptr, NewString, "mono_string_new");
-  MONOLIB_RETURN_IF_NOSYM(mono_get_string_class_ptr, GetStringClass, "mono_get_string_class");
-  MONOLIB_RETURN_IF_NOSYM(mono_array_new_ptr, ArrayNew, "mono_array_new");
-  MONOLIB_RETURN_IF_NOSYM(mono_array_addr_with_size_ptr, ArrayAddrWithSize, "mono_array_addr_with_size");
-  MONOLIB_RETURN_IF_NOSYM(mono_jit_cleanup_ptr, DomainCleanup, "mono_jit_cleanup");
-  MONOLIB_RETURN_IF_NOSYM(mono_jit_exec_ptr, AssemblyExec, "mono_jit_exec");
-
-#undef MONOLIB_RETURN_IF_NOSYM
-
-  _DBG("libmono dlopen and dlsym success");
-
-  return 0;
-}
-
-void MonoRuntime::Dispose()
-{
-  if (domain != nullptr)
-  {
-    DomainCleanup(domain);
-  }
-  if (monolib != nullptr && dlclose(monolib) != 0)
-  {
-    _ERR("libmono close failed");
-  }
-  monolib = nullptr;
-}
-
-int MonoRuntime::RunManagedLauncher()
-{
-  if (FileNotExist(launcherAssemblyPath.c_str()))
-  {
-    _ERR("Launcher Assembly is not exist in %s", launcherAssemblyPath.c_str());
-    return 1;
-  }
-
-//  _DBG("mono_set_dirs(\"%s\", nullptr);", runtimeDirectory.c_str());
-//  _DBG("mono_set_assemblies_path(\"%s\");", deviceAPIDirectory.c_str());
-
-//  SetDirs(runtimeDirectory.c_str(), nullptr);
-/*
-  std::string assembliesPath = runtimeDirectory+":"+deviceAPIDirectory;
-  _DBG("assembliesPath : %s", assembliesPath.c_str());
-  SetAssembliesPath(assembliesPath.c_str());
-  */
-  SetAssembliesPath(deviceAPIDirectory.c_str());
-
-  domain = JitInit(DOMAIN_NAME);
-  if (domain == nullptr)
-  {
-    _ERR("Failed to init mono jit");
-    return 1;
-  }
-
-  launcherAssembly = DomainAssemblyOpen(domain, launcherAssemblyPath.c_str());
-  if (launcherAssembly == nullptr)
-  {
-    _ERR("Failed to Load Launcher Assembly");
-    return 1;
-  }
-
-  monoImage = AssemblyGetImage(launcherAssembly);
-  if (monoImage == nullptr)
-  {
-    _ERR("Failed to get image from launcher assembly");
-    return 1;
-  }
-
-  assemblyManagerClass = ClassFromName(monoImage, "Tizen.Runtime.Mono", "AssemblyManager");
-  if (assemblyManagerClass == nullptr)
-  {
-    _ERR("Failed to get AssemblyManager class in namespace Tizen.Runtime.Mono from launcher image");
-    return 1;
-  }
-
-  prepareLaunch = ClassGetMethodFromName(assemblyManagerClass, "Prepared", 0);
-  if (prepareLaunch == nullptr)
-  {
-    _ERR("Failed to get Prepared() method from Tizen.Runtime.Mono.AssemblyManager");
-    return 1;
-  }
-  MonoObject* exception = nullptr;
-  RuntimeInvoke(prepareLaunch, nullptr, nullptr, &exception);
-  if (exception != nullptr)
-  {
-    MonoString * exceptionMsg = ObjectToString(exception, nullptr);
-    char* cstringMsg = StringToUtf8(exceptionMsg);
-    _ERR("Failed to invoke method in runtime");
-    _ERR("%s", cstringMsg);
-    free(cstringMsg);
-    return 1;
-  }
-
-  launch = ClassGetMethodFromName(assemblyManagerClass, "Launch", 4);
-
-  return 0;
-}
-
-#define ArrayAddr(array,type,index) ((type*)(void*) ArrayAddrWithSize (array, sizeof (type), index))
-#define ArraySet(array,type,index,value)       \
-       do {    \
-               type *__p = (type *) ArrayAddr ((array), type, (index));        \
-               *__p = (value); \
-       } while (0)
-
-int MonoRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
-{
-  if (domain == nullptr)
-  {
-    domain = JitInit(DOMAIN_NAME);
-    if (domain == nullptr)
-    {
-      _ERR("Failed to init mono jit");
-      return 1;
-    }
-  }
-  if (launch != nullptr)
-  {
-    MonoString *rootMonoString = NewString(domain, root);
-    MonoString *pathMonoString = NewString(domain, path);
-    MonoArray *argvMonoArray = ArrayNew(domain, GetStringClass(), argc);
-    for (int i=0; i<argc; i++)
-    {
-      MonoString *arg = NewString(domain, argv[i]);
-      ArraySet(argvMonoArray, MonoString*, i, arg);
-    }
-
-    void **args = new void*[argc+2];
-    args[0] = rootMonoString;
-    args[1] = pathMonoString;
-    args[2] = &argc;
-    args[3] = argvMonoArray;
-
-    MonoObject* exception = nullptr;
-    RuntimeInvoke(launch, nullptr, args, &exception);
-    if (exception != nullptr)
-    {
-      MonoString * exceptionMsg = ObjectToString(exception, nullptr);
-      char* cstringMsg = StringToUtf8(exceptionMsg);
-      _ERR("Failed to invoke launch method in runtime");
-      _ERR("%s", cstringMsg);
-      free(cstringMsg);
-      return 1;
-    }
-  }
-  else
-  {
-    std::string appBin = ConcatPath(root, "bin");
-    std::string appLib = ConcatPath(root, "lib");
-    std::string probePath = deviceAPIDirectory + ":" + appBin + ":" + appLib;
-    SetAssembliesPath(probePath.c_str());
-    MonoAssembly* app = DomainAssemblyOpen(domain, path);
-    if (app == nullptr)
-    {
-      _ERR("Failed to open assembly : %s", path);
-      return 1;
-    }
-    int ret = AssemblyExec(domain, app, argc, argv);
-  }
-  return 0;
-}
-
-}  // namespace dotnetcore
-}  // namespace runtime
-}  // namespace mono
diff --git a/NativeLauncher/src/mono/mono_launcher.h b/NativeLauncher/src/mono/mono_launcher.h
deleted file mode 100644 (file)
index d705d9e..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-#include "launcher.h"
-
-extern "C"
-{
-  typedef struct _MonoDomain MonoDomain;
-  typedef struct _NonoAssembly MonoAssembly;
-  typedef struct _MonoImage MonoImage;
-  typedef struct _MonoClass MonoClass;
-  typedef struct _MonoObject MonoObject; 
-  typedef struct _MonoMethod MonoMethod;
-  typedef struct _MonoString MonoString;
-  typedef struct _MonoArray MonoArray;
-
-  typedef void          (*mono_set_dirs_ptr)                   (const char *, const char *);
-  typedef void          (*mono_set_assemblies_path_ptr)        (const char*);
-  typedef MonoDomain*   (*mono_jit_init_ptr)                   (const char *); 
-  typedef void          (*mono_config_parse_ptr)               (const char *);
-  typedef MonoAssembly* (*mono_domain_assembly_open_ptr)       (MonoDomain *, const char *);
-  typedef MonoImage*    (*mono_assembly_get_image_ptr)         (MonoAssembly *);
-  typedef MonoClass*    (*mono_class_from_name_ptr)            (MonoImage *, const char *, const char *);
-  typedef MonoObject*   (*mono_runtime_invoke_ptr)             (MonoMethod *, void *, void **, MonoObject **);
-  typedef MonoMethod*   (*mono_class_get_method_from_name_ptr) (MonoClass *, const char *, int param_count);
-  typedef MonoString*   (*mono_string_new_ptr)                 (MonoDomain *, const char *);
-  typedef MonoString*   (*mono_object_to_string_ptr)           (MonoObject *, MonoObject **);
-  typedef char*         (*mono_string_to_utf8_ptr)             (MonoString *string_obj);
-
-  typedef MonoClass*    (*mono_get_string_class_ptr)           ();
-  typedef MonoArray*    (*mono_array_new_ptr)                  (MonoDomain *, MonoClass *, uintptr_t);
-  typedef char*         (*mono_array_addr_with_size_ptr)       (MonoArray *, int, uintptr_t); 
-  typedef void          (*mono_jit_cleanup_ptr)                (MonoDomain *domain);
-  typedef int           (*mono_jit_exec_ptr)                   (MonoDomain *domain, MonoAssembly *assembly, int argc, char *argv[]);
-}
-
-namespace tizen {
-namespace runtime {
-namespace mono {
-
-class MonoRuntime : public tizen::runtime::LauncherInterface
-{
-  public:
-    MonoRuntime();
-    ~MonoRuntime();
-    int Initialize(bool standalone) override;
-    void Dispose() override;
-    int RunManagedLauncher() override;
-    int Launch(const char* root, const char* path, int argc, char* argv[]) override;
-
-  private:
-    void* monolib;
-    mono_set_dirs_ptr SetDirs;
-    mono_set_assemblies_path_ptr SetAssembliesPath;
-    mono_jit_init_ptr JitInit;
-    mono_domain_assembly_open_ptr DomainAssemblyOpen;
-    mono_assembly_get_image_ptr AssemblyGetImage;
-    mono_class_from_name_ptr ClassFromName;
-    mono_runtime_invoke_ptr RuntimeInvoke;
-    mono_class_get_method_from_name_ptr ClassGetMethodFromName;
-    mono_object_to_string_ptr ObjectToString;
-    mono_string_to_utf8_ptr StringToUtf8;
-    mono_string_new_ptr NewString;
-    mono_get_string_class_ptr GetStringClass;
-    mono_array_new_ptr ArrayNew;
-    mono_array_addr_with_size_ptr ArrayAddrWithSize;
-    mono_jit_cleanup_ptr DomainCleanup;
-    mono_jit_exec_ptr AssemblyExec;
-
-    MonoDomain* domain;
-    MonoAssembly* launcherAssembly;
-    MonoImage* monoImage;
-    MonoClass* assemblyManagerClass;
-    MonoMethod* prepareLaunch;
-    MonoMethod* launch;
-
-    std::string launcherAssemblyPath;
-    std::string deviceAPIDirectory;
-    std::string runtimeDirectory;
-};
-
-
-}  // namespace mono
-}  // namespace runtime
-}  // namespace tizen
diff --git a/NativeLauncher/src/utils.cc b/NativeLauncher/src/utils.cc
deleted file mode 100644 (file)
index 776fd9f..0000000
+++ /dev/null
@@ -1,211 +0,0 @@
-
-#include <dirent.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <limits.h>
-#include <strings.h>
-
-#include <cstdlib>
-#include <cstring>
-#include <algorithm>
-#include <set>
-#include <vector>
-#include <iterator>
-#include <sstream>
-
-#include "utils.h"
-
-std::string ReadSelfPath()
-{
-  char buff[PATH_MAX];
-  ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
-  if (len != -1) {
-    buff[len] = '\0';
-    return std::string(buff);
-  }
-
-  return "";
-}
-
-std::string ConcatPath(const std::string& path1, const std::string& path2)
-{
-  std::string path(path1);
-  if (path.back() == PATH_SEPARATOR)
-  {
-    path.append(path2);
-  }
-  else
-  {
-    path += PATH_SEPARATOR;
-    path.append(path2);
-  }
-
-  return path;
-}
-
-void AppendPath(std::string& path1, const std::string& path2)
-{
-  if (path1.back() == PATH_SEPARATOR)
-  {
-    path1.append(path2);
-  }
-  else
-  {
-    path1 += PATH_SEPARATOR;
-    path1.append(path2);
-  }
-}
-
-std::string AbsolutePath(const std::string& path)
-{
-  std::string absPath;
-
-  char realPath[PATH_MAX];
-  if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
-  {
-    absPath.assign(realPath);
-  }
-
-  return absPath;
-}
-
-std::string Basename(const std::string& path)
-{
-  auto pos = path.find_last_of(PATH_SEPARATOR);
-  if (pos != std::string::npos)
-  {
-    return path.substr(0, pos);
-  }
-  else
-  {
-    return std::string(".");
-  }
-  return path;
-}
-
-bool EndWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& filename)
-{
-  std::string::size_type len1 = str1.length();
-  std::string::size_type len2 = str2.length();
-  if (len2 > len1) return false;
-
-  int i = 0;
-  bool result = std::all_of(str1.cend() - len2, str1.end(),
-        [&i, &str2] (char x) {
-          return std::tolower(x) == std::tolower(str2[i++]);
-        });
-  if (result)
-  {
-    filename = str1.substr(0, len1 - len2);
-  }
-  return result;
-}
-
-bool FileNotExist(const std::string& path)
-{
-  struct stat sb;
-  return (stat(path.c_str(), &sb) != 0) || !S_ISREG(sb.st_mode);
-}
-
-static bool ExtCheckAndGetFileNameIfExist(const std::string&  dir, const std::string& ext, struct dirent* entry, std::string& filename)
-{
-  std::string fname(entry->d_name);
-  if (fname.length() < ext.length() ||
-      fname.compare(fname.length() - ext.length(), ext.length(), ext) != 0)
-  {
-    return false;
-  }
-  std::string fullname = ConcatPath(dir, entry->d_name);
-  switch (entry->d_type)
-  {
-    case DT_REG: break;
-    case DT_LNK:
-    case DT_UNKNOWN:
-      if (FileNotExist(fullname))
-      {
-        return false;
-      }
-    default:
-      return false;
-  }
-
-  filename = fullname;
-
-  return true;
-}
-
-std::string StripNIDLL(const std::string& path)
-{
-  std::string npath(path);
-  if (path.size() < 5) return npath;
-  if (strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
-  {
-    npath = path.substr(0, path.size()-4);
-  }else if (strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
-  {
-    npath = path.substr(0, path.size()-4);
-  }
-  if (strncasecmp(npath.c_str() + npath.size() - 3, ".ni", 3))
-  {
-    return npath.substr(0, npath.size()-3);
-  }
-  return npath;
-}
-
-std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter)
-{
-  switch (strings.size())
-  {
-    case 0:
-      return "";
-    case 1:
-      return strings[0];
-    default:
-      std::ostringstream os; 
-      std::copy(strings.begin(), strings.end()-1, std::ostream_iterator<std::string>(os, delimeter));
-      os << *strings.rbegin();
-      return os.str();
-  }
-}
-
-void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
-{
-  static const std::string tpaExtensions[] =
-  {".ni.dll", ".dll", ".ni.exe", ".exe"};
-
-  std::set<std::string> addedAssemblies;
-
-  DIR* dir = nullptr;
-  struct dirent* entry = nullptr;
-
-  for (auto directory : directories)
-  {
-    dir = opendir(directory.c_str());
-    if (dir == nullptr)
-    {
-      continue;
-    }
-
-    for (auto ext : tpaExtensions)
-    {
-      while ((entry = readdir(dir)) != nullptr)
-      {
-        std::string fullname;
-        if (ExtCheckAndGetFileNameIfExist(directory.c_str(), ext, entry, fullname))
-        {
-          std::string filename = StripNIDLL(fullname);
-          if (addedAssemblies.find(filename) == addedAssemblies.end())
-          {
-            addedAssemblies.insert(filename);
-            tpaList += fullname + ':';
-          }
-        }
-      }
-      rewinddir(dir);
-    }
-    closedir(dir);
-  }
-  if (tpaList.back() == ':')
-    tpaList.pop_back();
-
-}
diff --git a/NativeLauncher/src/waiter/waiter.cc b/NativeLauncher/src/waiter/waiter.cc
deleted file mode 100644 (file)
index 6447d4a..0000000
+++ /dev/null
@@ -1,295 +0,0 @@
-
-#include <poll.h>
-
-#ifndef NO_TIZEN
-#include <launchpad.h>
-#include <aul.h>
-#endif
-
-#include <memory>
-#include <vector>
-#include <map>
-#include <poll.h>
-
-#include <iostream>
-
-#include "waiter.h"
-#include "log.h"
-
-namespace dotnet {
-namespace runtime {
-
-struct FdHandler
-{
-  pollfd *info;
-  Receiver receiver;
-};
-
-static volatile bool Waiting_;
-static std::vector<pollfd> Fdlist_;
-static std::map<int, FdHandler> Handlers_;
-static Waiter::AppInfo AppInfo_;
-
-void Waiter::OnPrepared()
-{
-  if (!context.Prepare())
-  {
-    _DBG("Fail to Prepare...");
-  }
-}
-
-void Waiter::OnRequested(const AppInfo& info)
-{
-  // do some job on user id is still system
-
-  if (!context.Request())
-  {
-    _DBG("Fail to Request...");
-  }
-}
-
-void Waiter::OnExecuted(const char *path, const char *app_root, int argc, char *argv[])
-{
-  if (!context.Execute(path, app_root, argc, argv))
-  {
-    _DBG("Fail to Execute...");
-  }
-}
-
-void Waiter::OnWaiting()
-{
-  // Start the loop
-  Waiting_ = true;
-
-  _DBG("start polling...");
-  while (Waiting_)
-  {
-    if (poll(Fdlist_.data(), Fdlist_.size(), -1) < 0)
-      continue;
-
-    for (auto &p : Fdlist_)
-    {
-      if ( (p.revents | POLLIN) != 0 )
-        Handlers_[p.fd].receiver(p.fd);
-    }
-  }
-  _DBG("end polling...");
-}
-
-void Waiter::Stop()
-{
-  // Stop the loop
-
-  Waiting_ = false;
-}
-
-
-void Waiter::RegisterFd(int fd, Receiver receiver)
-{
-  // register fd should be caught in event loop
-
-  _DBG("Register fd %d", fd);
-
-  pollfd info;
-  info.fd = fd;
-  info.events = POLLIN;
-  info.revents = 0;
-
-  FdHandler handler;
-  Fdlist_.push_back(info);
-  handler.info = &Fdlist_.back(); 
-  handler.receiver = receiver;
-
-  Handlers_[fd] = handler;
-}
-
-void Waiter::DeregisterFd(int fd)
-{
-  // deregister fd should be caught in event loop
-  
-  pollfd *info = Handlers_[fd].info;
-  Fdlist_.erase(Fdlist_.begin() - (info - &Fdlist_.front()));
-  Handlers_.erase(fd);
-}
-
-int Waiter::WaitToLaunching(int argc, char *argv[])
-{
-#ifndef NO_TIZEN
-  auto on_create = [](bundle *extra, int type, void *user_data)
-  {
-    _DBG("on_create..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->OnPrepared();
-  };
-
-  auto on_launch = [](int argc, char **argv, const char *app_path,
-      const char *appid, const char *pkgid,
-      const char *pkg_type, void *user_data) -> int
-  {
-    _DBG("on_launch..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-
-    _DBG ("app path : %s", app_path);
-    _DBG ("app id : %s", appid);
-    _DBG ("pkg id : %s", pkgid);
-    _DBG ("pkg type : %s", pkg_type);
-
-    AppInfo info = {
-      AppPath : app_path,
-      AppId : appid,
-      PkgId : pkgid,
-      PkgType : pkg_type
-    };
-
-    waiter->OnRequested(info);
-    return 0;
-  };
-
-  auto on_terminate = [](int argc, char **argv, void *user_data) -> int
-  {
-    _DBG("on_terminate..."); // XXX
-    
-    string app_root(aul_get_app_root_path());
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->OnExecuted(argv[0], app_root.c_str(), argc, argv);
-    return 0;
-  };
-
-  auto on_start_loop = [](void *user_data)
-  {
-    _DBG("on_start_loop..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->OnWaiting();
-  };
-
-  auto on_quit_loop = [](void *user_data)
-  {
-    _DBG("on_quit_loop..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->Stop();
-  };
-
-  auto on_add_fd = [](void *user_data, int fd, loader_receiver_cb receiver)
-  {
-    _DBG("on_add_fd..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->RegisterFd(fd, receiver);
-  };
-
-  auto on_remove_fd = [](void *user_data, int fd)
-  {
-    _DBG("on_remove_fd..."); // XXX
-    Waiter* waiter = static_cast<Waiter*>(user_data);
-    waiter->DeregisterFd(fd);
-  };
-
-  _DBG("launcher wait..."); // XXX
-  loader_lifecycle_callback_s callbacks = {
-    .create = on_create,
-    .launch = on_launch,
-    .terminate = on_terminate
-  };
-
-       loader_adapter_s adapter = {
-               .loop_begin = on_start_loop,
-               .loop_quit = on_quit_loop,
-               .add_fd = on_add_fd,
-               .remove_fd = on_remove_fd
-       };
-
-  return launchpad_loader_main(argc, argv, &callbacks, &adapter, this);
-#else
-  if (argc < 2)
-  {
-    _DBG("not enough args : %d", argc);
-    return -1;
-  }
-  _DBG("argv[1] = %s", argv[1]);
-  std::string app_path(argv[1]);
-  std::string app_root;
-  auto pos = app_path.find_last_of('/');
-  if (pos != std::string::npos)
-    app_root = app_path.substr(0, pos);
-  else
-    app_root = ".";
-
-  this->OnPrepared();
-  AppInfo info = {
-    AppPath : argv[1],
-    AppId : "",
-    PkgId : "",
-    PkgType : ""
-  };
-  this->OnRequested(info);
-  this->OnExecuted(app_path.c_str(), app_root.c_str(), argc, argv);
-#endif
-}
-
-void Waiter::SetContext(WaiterContext ctx)
-{
-  context = ctx;
-}
-
-WaiterContext::WaiterContext()
-{
-  Step = Status::Started;
-}
-
-bool WaiterContext::Prepare()
-{
-  if (Step == Status::Started && Prepared != nullptr && Prepared(Data) == 0)
-  {
-    Step = Status::Prepared;
-    return true;
-  }
-  return false;
-}
-
-bool WaiterContext::Request()
-{
-  if (Step == Status::Prepared && Requested != nullptr && Requested(Data) == 0)
-  {
-    Step = Status::Requested;
-    return true;
-  }
-  return false;
-}
-
-bool WaiterContext::Execute(const char *path, const char *app_root, int argc, char *argv[])
-{
-  if (Step == Status::Requested && Executed != nullptr &&
-      Executed(path, app_root, argc, argv, Data) == 0)
-  {
-    Step = Status::Executed;
-    return true;
-  }
-  return false;
-}
-
-}  // namespace runtime
-}  // namespace dotnet
-
-using dotnet::runtime::Waiter;
-using dotnet::runtime::WaiterContext;
-
-static Waiter waiter;
-
-void register_launching_callback(prepared_callback prepared,
-    requested_callback requested, executed_callback executed, void *data)
-{
-  WaiterContext context;
-  context.Prepared = prepared;
-  context.Requested = requested;
-  context.Executed = executed;
-  context.Data = data;
-
-  waiter.SetContext(context);
-}
-
-void wait_for_launching(int argc, char *argv[])
-{
-  _DBG("wait_for_launching...");
-
-  waiter.WaitToLaunching(argc, argv);
-}
-
diff --git a/NativeLauncher/src/waiter/waiter.h b/NativeLauncher/src/waiter/waiter.h
deleted file mode 100644 (file)
index c4b98fb..0000000
+++ /dev/null
@@ -1,77 +0,0 @@
-#include <string>
-#include <functional>
-
-#include <iostream>
-
-extern "C" {
-  typedef int (*prepared_callback)(void *data);
-  typedef int (*requested_callback)(void *data);
-  typedef int (*executed_callback)(const char* path, const char* app_root, int argc, char *argv[], void *data);
-
-  void register_launching_callback(prepared_callback prepared,
-      requested_callback requested, executed_callback executed, void *data);
-  void wait_for_launching(int argc, char *argv[]);
-}
-
-namespace dotnet {
-namespace runtime {
-
-using std::string;
-using Receiver = std::function<void(int)>;
-
-enum Status
-{
-  Started,
-  Prepared,
-  Requested,
-  Executed
-};
-
-class WaiterContext
-{
-  public:
-    prepared_callback Prepared;
-    requested_callback Requested;
-    executed_callback Executed;
-
-    void *Data;
-
-    WaiterContext();
-    bool Prepare();
-    bool Request();
-    bool Execute(const char *path, const char *app_root, int argc, char *argv[]);
-
-  private:
-    Status Step;
-};
-
-class Waiter
-{
-  public:
-    struct AppInfo
-    {
-      string AppPath;
-      string AppId;
-      string PkgId;
-      string PkgType;
-    };
-
-    int WaitToLaunching(int argc, char *argv[]);
-    void Stop();
-
-    void RegisterFd(int fd, Receiver receiver);
-    void DeregisterFd(int fd);
-    void SetContext(WaiterContext ctx);
-
-  protected:
-    void OnPrepared();
-    void OnRequested(const AppInfo&);
-    void OnWaiting();
-    void OnExecuted(const char *path, const char *app_root, int argc, char *argv[]);
-
-  private:
-    WaiterContext context;
-};
-
-}  // namespace runtime
-}  // namespace dotnet
diff --git a/NativeLauncher/util/utils.cc b/NativeLauncher/util/utils.cc
new file mode 100644 (file)
index 0000000..2cc1026
--- /dev/null
@@ -0,0 +1,329 @@
+
+#include <dirent.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <limits.h>
+#include <strings.h>
+
+#include <cstdlib>
+#include <cstring>
+#include <algorithm>
+#include <unordered_map>
+#include <vector>
+#include <iterator>
+#include <sstream>
+
+#include "utils.h"
+
+bool ICompare(const std::string& a, const std::string& b)
+{
+  return a.length() == b.length() &&
+    std::equal(b.begin(), b.end(), a.begin(),
+        [](unsigned char a, unsigned char b)
+        { return std::tolower(a) == std::tolower(b); });
+}
+
+bool ICompare(const std::string& a, int a_offset, const std::string& b, int b_offset, int length)
+{
+  return static_cast<int>(a.length()) - length >= a_offset &&
+    static_cast<int>(b.length()) - length >= b_offset &&
+    std::equal(b.begin() + b_offset, b.begin() + b_offset + length, a.begin() + a_offset,
+        [](unsigned char a, unsigned char b)
+        { return std::tolower(a) == std::tolower(b); });
+}
+
+bool IsManagedAssembly(const std::string& filename)
+{
+  return ICompare(filename, filename.size()-4, ".dll", 0, 4) ||
+    ICompare(filename, filename.size()-4, ".exe", 0, 4);
+}
+
+bool IsNativeImage(const std::string& filename)
+{
+  return ICompare(filename, filename.size()-7, ".ni", 0, 3);
+}
+
+std::string ReadSelfPath()
+{
+  char buff[PATH_MAX];
+  ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
+  if (len != -1) {
+    buff[len] = '\0';
+    return std::string(buff);
+  }
+
+  return "";
+}
+
+std::string ConcatPath(const std::string& path1, const std::string& path2)
+{
+  std::string path(path1);
+  if (path.back() == PATH_SEPARATOR)
+  {
+    path.append(path2);
+  }
+  else
+  {
+    path += PATH_SEPARATOR;
+    path.append(path2);
+  }
+
+  return path;
+}
+
+void AppendPath(std::string& path1, const std::string& path2)
+{
+  if (path1.back() == PATH_SEPARATOR)
+  {
+    path1.append(path2);
+  }
+  else
+  {
+    path1 += PATH_SEPARATOR;
+    path1.append(path2);
+  }
+}
+
+std::string AbsolutePath(const std::string& path)
+{
+  std::string absPath;
+
+  char realPath[PATH_MAX];
+  if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
+  {
+    absPath.assign(realPath);
+  }
+
+  return absPath;
+}
+
+std::string Basename(const std::string& path)
+{
+  auto pos = path.find_last_of(PATH_SEPARATOR);
+  if (pos != std::string::npos)
+  {
+    return path.substr(0, pos);
+  }
+  else
+  {
+    return std::string(".");
+  }
+  return path;
+}
+
+bool EndWithIgnoreCase(const std::string& str1, const std::string& str2, std::string& filename)
+{
+  std::string::size_type len1 = str1.length();
+  std::string::size_type len2 = str2.length();
+  if (len2 > len1) return false;
+
+  int i = 0;
+  bool result = std::all_of(str1.cend() - len2, str1.end(),
+        [&i, &str2] (char x) {
+          return std::tolower(x) == std::tolower(str2[i++]);
+        });
+  if (result)
+  {
+    filename = str1.substr(0, len1 - len2);
+  }
+  return result;
+}
+
+bool FileNotExist(const std::string& path)
+{
+  struct stat sb;
+  return stat(path.c_str(), &sb) != 0;
+}
+
+static bool ExtCheckAndGetFileNameIfExist(const std::string&  dir, const std::string& ext, struct dirent* entry, std::string& filename)
+{
+  std::string fname(entry->d_name);
+  if (fname.length() < ext.length() ||
+      fname.compare(fname.length() - ext.length(), ext.length(), ext) != 0)
+  {
+    return false;
+  }
+  std::string fullname = ConcatPath(dir, entry->d_name);
+  switch (entry->d_type)
+  {
+    case DT_REG: break;
+    case DT_LNK:
+    case DT_UNKNOWN:
+      if (FileNotExist(fullname))
+      {
+        return false;
+      }
+    default:
+      return false;
+  }
+
+  filename = fullname;
+
+  return true;
+}
+
+std::string StripNIDLL(const std::string& path)
+{
+  std::string npath(path);
+  if (path.size() < 5) return npath;
+  if (strncasecmp(path.c_str() + path.size() - 4, ".dll", 4))
+  {
+    npath = path.substr(0, path.size()-4);
+  }else if (strncasecmp(path.c_str() + path.size() - 4, ".exe", 4))
+  {
+    npath = path.substr(0, path.size()-4);
+  }
+  if (strncasecmp(npath.c_str() + npath.size() - 3, ".ni", 3))
+  {
+    return npath.substr(0, npath.size()-3);
+  }
+  return npath;
+}
+
+std::string JoinStrings(const std::vector<std::string>& strings, const char* const delimeter)
+{
+  switch (strings.size())
+  {
+    case 0:
+      return "";
+    case 1:
+      return strings[0];
+    default:
+      std::ostringstream os; 
+      std::copy(strings.begin(), strings.end()-1, std::ostream_iterator<std::string>(os, delimeter));
+      os << *strings.rbegin();
+      return os.str();
+  }
+}
+
+struct AssemblyFile
+{
+  std::string noext;
+  std::string ext;
+};
+
+bool operator == (const AssemblyFile& lhs, const AssemblyFile& rhs)
+{
+  return lhs.noext == rhs.noext && lhs.ext == rhs.ext;
+}
+
+namespace std
+{
+  template<>
+  struct hash<AssemblyFile>
+  {
+    std::size_t operator () (const AssemblyFile& f) const
+    {
+      const std::size_t h1 = std::hash<std::string>{}(f.noext);
+      const std::size_t h2 = std::hash<std::string>{}(f.ext);
+
+      return h1 ^ (h2 << 1);
+    }
+  };
+}
+
+void AssembliesInDirectory(const std::vector<std::string>& directories, std::string& tpaList)
+{
+  std::unordered_map<AssemblyFile, bool> addedAssemblies;
+
+  auto reader = [&addedAssemblies] (const char* path)
+  {
+    std::string _path(path);
+
+    std::string::size_type dotp = _path.rfind('.');
+    std::string ext = dotp != std::string::npos ? _path.substr(dotp) : "";
+    std::string noext;
+    bool ni = false;
+
+    if (IsManagedAssembly(_path))
+    {
+      if (IsNativeImage(_path))
+      {
+        noext = _path.substr(0, _path.size()-7);
+        ni = true;
+      }
+      else
+      {
+        noext = _path.substr(0, _path.size()-4);
+      }
+
+      AssemblyFile f = {noext, ext};
+      addedAssemblies[f] = ni;
+    }
+  };
+
+  for (auto directory : directories)
+  {
+    ScanFilesInDir(directory.c_str(), reader, 1);
+  }
+
+  for (auto kv : addedAssemblies)
+  {
+    tpaList += kv.first.noext + (kv.second ? ".ni" : "") +  kv.first.ext + ':';
+  }
+
+  if (tpaList.back() == ':')
+    tpaList.pop_back();
+}
+
+void ScanFilesInDir(const char* directory, FileReader reader, unsigned int depth)
+{
+  DIR *dir;
+  struct dirent* entry;
+  bool isDir;
+
+  dir = opendir(directory);
+
+  if (dir == nullptr)
+  {
+    //_ERR("Can not open directory : %s", directory);
+    return;
+  }
+
+  std::vector<std::string> innerDirectories;
+
+  while ((entry = readdir(dir)) != nullptr)
+  {
+    isDir = false;
+    std::string path = ConcatPath(directory, entry->d_name);
+    switch (entry->d_type)
+    {
+      case DT_REG: break;
+      case DT_DIR:
+        isDir = true;
+        break;
+      case DT_LNK:
+      case DT_UNKNOWN:
+        struct stat sb;
+        if (stat(path.c_str(), &sb) == -1)
+        {
+          continue;
+        }
+
+        if (S_ISREG(sb.st_mode) || S_ISDIR(sb.st_mode))
+        {
+          break;
+        }
+      default:
+        continue;
+    }
+    if (!isDir)
+    {
+      reader(path.c_str()); 
+    }
+    else if (depth > 1 && strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
+    {
+      innerDirectories.push_back(path);
+    }
+  }
+
+  if (depth != 0)
+  {
+    for (auto& d : innerDirectories)
+    {
+      ScanFilesInDir(d.c_str(), reader, depth-1);
+    }
+  }
+
+  closedir(dir);
+}
index fa0bb60e88dfec52115ccf84f7c2382a2d030395..1050527ba6045d84bae717967d0d3a358338f068 100644 (file)
@@ -15,6 +15,8 @@ BuildRequires: pkgconfig(bundle)
 BuildRequires: pkgconfig(dlog)
 BuildRequires: pkgconfig(ecore)
 BuildRequires: pkgconfig(launchpad)
+BuildRequires: pkgconfig(pkgmgr-info)
+BuildRequires: pkgconfig(pkgmgr-installer)
 BuildRequires: aul-devel
 BuildRequires: mono-compiler
 BuildRequires: mono-devel 
@@ -33,6 +35,7 @@ Requires(preun): /usr/bin/systemctl
 %define _device_api_dir %{dotnet_assembly_path}
 %define _runtime_dir /opt/usr/share/dotnet/shared/Microsoft.NETCore.App/1.0.0
 %define _preload_dir /opt/usr/share/dotnet.tizen/preload
+%define _install_plugin_dir /usr/etc/package-manager/parserlib
 
 %description
 Launchpad plugin for launching dotnet apps
@@ -56,8 +59,10 @@ cmake \
        -DCMAKE_BUILD_TYPE=%{_buildmode} \
        -DDEVICE_API_DIR=%{_device_api_dir} \
        -DRUNTIME_DIR=%{_runtime_dir} \
+       -DCROSSGEN_PATH=%{_device_api_dir}/crossgen \
        -DCORECLR_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Coreclr.dll \
        -DMONO_LAUNCHER_ASSEMBLY_PATH=%{_bindir}/Tizen.Runtime.Mono.dll \
+       -DINSTALL_PLUGIN_DIR=%{_install_plugin_dir} \
        -DVERSION=%{version} \
        NativeLauncher
 
@@ -89,5 +94,7 @@ install -p -m 644 Tizen.Runtime/bin/Tizen.Runtime.Mono.dll %{buildroot}%{_bindir
 %{_loaderdir}/dotnet.launcher
 %{_loaderdir}/dotnet.debugger
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/dotnet-launcher
+%caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/nitool
+%caps(cap_mac_admin,cap_setgid=ei) %{_install_plugin_dir}/libui-application.so
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Coreclr.dll
 %caps(cap_mac_admin,cap_setgid=ei) %{_bindir}/Tizen.Runtime.Mono.dll