Upstream version 9.37.195.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / tools / linux / xwalk_launcher_main.cc
index e1843a6..66c77cf 100644 (file)
@@ -7,15 +7,21 @@
 #include <stdbool.h>
 #include <string.h>
 #include <stdio.h>
+#include <unistd.h>
 #include <pwd.h>
 #include <libgen.h>
 
 #include <glib.h>
 #include <gio/gio.h>
+#include <gio/gunixfdlist.h>
 
 #include "xwalk/application/tools/linux/dbus_connection.h"
-#include "xwalk/application/tools/linux/xwalk_tizen_user.h"
+#include "xwalk/application/tools/linux/xwalk_extension_process_launcher.h"
+#if defined(OS_TIZEN)
+#include "url/gurl.h"
 #include "xwalk/application/tools/linux/xwalk_launcher_tizen.h"
+#include "xwalk/application/tools/linux/xwalk_tizen_user.h"
+#endif
 
 static const char* xwalk_service_name = "org.crosswalkproject.Runtime1";
 static const char* xwalk_running_path = "/running1";
@@ -27,6 +33,25 @@ static const char* xwalk_running_app_iface =
 static char* application_object_path;
 
 static GMainLoop* mainloop;
+static GDBusConnection* g_connection;
+static GDBusObjectManager* g_running_apps_manager;
+static XWalkExtensionProcessLauncher* ep_launcher = NULL;
+
+static int g_argc;
+static char** g_argv;
+static gboolean query_running = FALSE;
+static gboolean fullscreen = FALSE;
+static gchar** cmd_appid_or_url;
+
+static GOptionEntry entries[] = {
+  { "running", 'r', 0, G_OPTION_ARG_NONE, &query_running,
+    "Check whether the application is running", NULL },
+  { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen,
+    "Run the application as fullscreen", NULL },
+  { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_appid_or_url,
+    "ID of the application to be launched or URL to open", NULL },
+  { NULL }
+};
 
 static void object_removed(GDBusObjectManager* manager, GDBusObject* object,
                            gpointer user_data) {
@@ -37,6 +62,7 @@ static void object_removed(GDBusObjectManager* manager, GDBusObject* object,
 
   fprintf(stderr, "Application '%s' disappeared, exiting.\n", path);
 
+  delete ep_launcher;
   g_main_loop_quit(mainloop);
 }
 
@@ -70,51 +96,90 @@ static void on_app_properties_changed(GDBusProxy* proxy,
   }
 }
 
-int main(int argc, char** argv) {
-  GError* error = NULL;
-  char* appid;
+static gboolean init_extension_process_channel(GDBusProxy* app_proxy) {
+  if (ep_launcher->is_started())
+    return FALSE;
+
+  // Get the client socket file descriptor from fd_list. The reply will
+  // contains an index to the list.
+  GUnixFDList* fd_list;
+  GVariant* res = g_dbus_proxy_call_with_unix_fd_list_sync(
+      app_proxy, "GetEPChannel", NULL, G_DBUS_CALL_FLAGS_NONE,
+      -1, NULL, &fd_list, NULL, NULL);
+  if (!res || g_variant_n_children(res) != 2)
+    return FALSE;
+
+  const gchar* channel_id =
+      g_variant_get_string(g_variant_get_child_value(res, 0), NULL);
+  if (!channel_id || !strlen(channel_id))
+    return FALSE;
+
+  gint32 client_fd_idx =
+      g_variant_get_handle(g_variant_get_child_value(res, 1));
+  int client_fd = g_unix_fd_list_get(fd_list, client_fd_idx, NULL);
+
+  ep_launcher->Launch(channel_id, client_fd);
+  return TRUE;
+}
 
-#if !GLIB_CHECK_VERSION(2, 36, 0)
-  // g_type_init() is deprecated on GLib since 2.36, Tizen has 2.32.
-  g_type_init();
-#endif
+static void on_app_signal(GDBusProxy* proxy,
+                          gchar* sender_name,
+                          gchar* signal_name,
+                          GVariant* parameters,
+                          gpointer user_data) {
+  if (!strcmp(signal_name, "EPChannelCreated")) {
+    init_extension_process_channel(proxy);
+  } else {
+    fprintf(stderr, "Unkown signal received: %s\n", signal_name);
+  }
+}
 
-  if (xwalk_tizen_set_home_for_user_app())
-    exit(1);
+static int query_application_running(const char* app_id) {
+  GList* objects = g_dbus_object_manager_get_objects(g_running_apps_manager);
+  GList* it;
+  bool is_running = FALSE;
+
+  for (it = objects; it; it = it->next) {
+    GDBusObject* object = reinterpret_cast<GDBusObject*>(it->data);
+    GDBusInterface* iface = g_dbus_object_get_interface(
+        object,
+        xwalk_running_app_iface);
+    if (!iface)
+      continue;
 
-  if (!strcmp(basename(argv[0]), "xwalk-launcher")) {
-    if (argc < 2) {
-      fprintf(stderr, "No AppID informed, nothing to do\n");
-      exit(1);
+    GDBusProxy* proxy = G_DBUS_PROXY(iface);
+    GVariant* id_variant;
+    id_variant = g_dbus_proxy_get_cached_property(proxy, "AppID");
+    if (!id_variant) {
+      g_object_unref(iface);
+      continue;
     }
 
-    appid = argv[1];
-  } else {
-    appid = strdup(basename(argv[0]));
-  }
+    const gchar* id;
+    g_variant_get(id_variant, "s", &id);
+    if (!strcmp(app_id, id)) {
+      is_running = TRUE;
+      break;
+    }
 
-  GDBusConnection* connection = get_session_bus_connection(&error);
-  if (!connection) {
-    fprintf(stderr, "Couldn't get the session bus connection: %s\n",
-            error->message);
-    exit(1);
+    g_object_unref(iface);
   }
+  const char* str = is_running ? "running" : "not running";
+  g_print("Application %s is %s.\n", app_id, str);
 
-  GDBusObjectManager* running_apps_om = g_dbus_object_manager_client_new_sync(
-      connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
-      xwalk_service_name, xwalk_running_path,
-      NULL, NULL, NULL, NULL, &error);
-  if (!running_apps_om) {
-    fprintf(stderr, "Service '%s' does could not be reached: %s\n",
-            xwalk_service_name, error->message);
-    exit(1);
-  }
+  g_list_free_full(objects, g_object_unref);
+  return is_running ? 0 : 1;
+}
 
-  g_signal_connect(running_apps_om, "object-removed",
+static void launch_application(const char* appid_or_url,
+                               gboolean fullscreen) {
+  ep_launcher = new XWalkExtensionProcessLauncher();
+  GError* error = NULL;
+  g_signal_connect(g_running_apps_manager, "object-removed",
                    G_CALLBACK(object_removed), NULL);
 
   GDBusProxy* running_proxy = g_dbus_proxy_new_sync(
-      connection,
+      g_connection,
       G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name,
       xwalk_running_path, xwalk_running_manager_iface, NULL, &error);
   if (!running_proxy) {
@@ -124,10 +189,11 @@ int main(int argc, char** argv) {
     exit(1);
   }
 
-  GVariant* result = g_dbus_proxy_call_sync(running_proxy, "Launch",
-                                            g_variant_new("(s)", appid),
-                                            G_DBUS_CALL_FLAGS_NONE,
-                                            -1, NULL, &error);
+  unsigned int launcher_pid = getpid();
+
+  GVariant* result  = g_dbus_proxy_call_sync(running_proxy, "Launch",
+      g_variant_new("(sub)", appid_or_url, launcher_pid, fullscreen),
+      G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
   if (!result) {
     fprintf(stderr, "Couldn't call 'Launch' method: %s\n", error->message);
     exit(1);
@@ -138,7 +204,7 @@ int main(int argc, char** argv) {
           application_object_path);
 
   GDBusProxy* app_proxy = g_dbus_proxy_new_sync(
-      connection,
+      g_connection,
       G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name,
       application_object_path, xwalk_running_app_iface, NULL, &error);
   if (!app_proxy) {
@@ -152,18 +218,93 @@ int main(int argc, char** argv) {
                    G_CALLBACK(on_app_properties_changed), NULL);
 
   mainloop = g_main_loop_new(NULL, FALSE);
+  g_signal_connect(app_proxy, "g-signal", G_CALLBACK(on_app_signal), NULL);
 
-#if defined(OS_TIZEN_MOBILE)
+#if defined(OS_TIZEN)
   char name[128];
-  snprintf(name, sizeof(name), "xwalk-%s", appid);
+  snprintf(name, sizeof(name), "xwalk-%s", appid_or_url);
 
-  if (xwalk_appcore_init(argc, argv, name)) {
+  if (xwalk_appcore_init(g_argc, g_argv, name, app_proxy)) {
     fprintf(stderr, "Failed to initialize appcore");
     exit(1);
   }
 #endif
 
+  init_extension_process_channel(app_proxy);
   g_main_loop_run(mainloop);
+}
+
+void connect_to_application_manager() {
+  GError* error = NULL;
+  g_connection = get_session_bus_connection(&error);
+  if (!g_connection) {
+    fprintf(stderr, "Couldn't get the session bus connection: %s\n",
+            error->message);
+    exit(1);
+  }
+
+  g_running_apps_manager =
+      g_dbus_object_manager_client_new_sync(
+          g_connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
+          xwalk_service_name, xwalk_running_path,
+          NULL, NULL, NULL, NULL, &error);
+  if (!g_running_apps_manager) {
+    fprintf(stderr, "Service '%s' does could not be reached: %s\n",
+            xwalk_service_name, error->message);
+    exit(1);
+  }
+}
+
+int main(int argc, char** argv) {
+  GError* error = NULL;
+  char* appid_or_url;
+
+  g_argc = argc;
+  g_argv = argv;
+
+#if !GLIB_CHECK_VERSION(2, 36, 0)
+  // g_type_init() is deprecated on GLib since 2.36.
+  g_type_init();
+#endif
+
+#if defined(OS_TIZEN)
+  if (xwalk_tizen_check_user_app())
+    exit(1);
+#endif
+
+  GOptionContext* context =
+      g_option_context_new("- Crosswalk Application Launcher");
+  g_option_context_add_main_entries(context, entries, NULL);
+  if (!g_option_context_parse(context, &argc, &argv, &error)) {
+    fprintf(stderr, "Option parsing failed: %s\n", error->message);
+    exit(1);
+  }
+
+  connect_to_application_manager();
+
+  // Launch app.
+  if (!strcmp(basename(argv[0]), "xwalk-launcher")) {
+    if (cmd_appid_or_url == NULL) {
+      fprintf(stderr, "No AppID informed, nothing to do.\n");
+      return 0;
+    }
+    appid_or_url = strdup(cmd_appid_or_url[0]);
+#if defined(OS_TIZEN)
+    if (GURL(appid_or_url).spec().empty()
+       && xwalk_change_cmdline(argc, argv, appid_or_url))
+      exit(1);
+#endif
+  } else {
+    appid_or_url = strdup(basename(argv[0]));
+  }
+
+
+  // Query app.
+  if (query_running) {
+    return query_application_running(appid_or_url);
+  }
 
+  launch_application(appid_or_url, fullscreen);
+  free(appid_or_url);
   return 0;
 }