Upstream version 6.34.113.0
[platform/framework/web/crosswalk.git] / src / xwalk / application / tools / linux / xwalk_launcher_main.cc
1 // Copyright (c) 2013 Intel Corporation. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <sys/types.h>
6 #include <stdlib.h>
7 #include <stdbool.h>
8 #include <string.h>
9 #include <stdio.h>
10 #include <unistd.h>
11 #include <pwd.h>
12 #include <libgen.h>
13
14 #include <glib.h>
15 #include <gio/gio.h>
16
17 #include "xwalk/application/tools/linux/dbus_connection.h"
18 #include "xwalk/application/tools/linux/xwalk_tizen_user.h"
19 #include "xwalk/application/tools/linux/xwalk_launcher_tizen.h"
20
21 static const char* xwalk_service_name = "org.crosswalkproject.Runtime1";
22 static const char* xwalk_running_path = "/running1";
23 static const char* xwalk_running_manager_iface =
24     "org.crosswalkproject.Running.Manager1";
25 static const char* xwalk_running_app_iface =
26     "org.crosswalkproject.Running.Application1";
27
28 static char* application_object_path;
29
30 static GMainLoop* mainloop;
31 static GDBusConnection* g_connection;
32
33 static int g_argc;
34 static char** g_argv;
35 static gboolean query_running = FALSE;
36 static gboolean fullscreen = FALSE;
37 static gchar** cmd_appid;
38
39 static GOptionEntry entries[] = {
40   { "running", 'r', 0, G_OPTION_ARG_NONE, &query_running,
41     "Check whether the application is running", NULL },
42   { "fullscreen", 'f', 0, G_OPTION_ARG_NONE, &fullscreen,
43     "Run the application as fullscreen", NULL },
44   { G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &cmd_appid,
45     "ID of the application to be launched", NULL },
46   { NULL }
47 };
48
49 static void object_removed(GDBusObjectManager* manager, GDBusObject* object,
50                            gpointer user_data) {
51   const char* path = g_dbus_object_get_object_path(object);
52
53   if (g_strcmp0(path, application_object_path))
54     return;
55
56   fprintf(stderr, "Application '%s' disappeared, exiting.\n", path);
57
58   g_main_loop_quit(mainloop);
59 }
60
61 static void on_app_properties_changed(GDBusProxy* proxy,
62                                       GVariant* changed_properties,
63                                       GStrv invalidated_properties,
64                                       gpointer user_data) {
65   const char* interface = g_dbus_proxy_get_interface_name(proxy);
66
67   fprintf(stderr, "properties changed %s\n", interface);
68
69   if (g_variant_n_children(changed_properties) == 0)
70     return;
71
72   if (g_strcmp0(interface, xwalk_running_app_iface))
73     return;
74
75   GVariantIter* iter;
76   const gchar* key;
77   GVariant* value;
78
79   g_variant_get(changed_properties, "a{sv}", &iter);
80
81   while (g_variant_iter_loop(iter, "{&sv}", &key, &value)) {
82     if (g_strcmp0(key, "State"))
83       continue;
84
85     const gchar* state = g_variant_get_string(value, NULL);
86
87     fprintf(stderr, "Application state %s\n", state);
88   }
89 }
90
91 static void query_application_running(GDBusObjectManager* running_om,
92                                       const char* app_id) {
93   GList* objects = g_dbus_object_manager_get_objects(running_om);
94   GList* it;
95   bool is_running = FALSE;
96
97   for (it = objects; it; it = it->next) {
98     GDBusObject* object = reinterpret_cast<GDBusObject*>(it->data);
99     GDBusInterface* iface = g_dbus_object_get_interface(
100         object,
101         xwalk_running_app_iface);
102     if (!iface)
103       continue;
104
105     GDBusProxy* proxy = G_DBUS_PROXY(iface);
106     GVariant* id_variant;
107     id_variant = g_dbus_proxy_get_cached_property(proxy, "AppID");
108     if (!id_variant) {
109       g_object_unref(iface);
110       continue;
111     }
112
113     const gchar* id;
114     g_variant_get(id_variant, "s", &id);
115     if (!strcmp(app_id, id)) {
116       is_running = TRUE;
117       break;
118     }
119
120     g_object_unref(iface);
121   }
122   const char* str = is_running ? "running" : "not running";
123   g_print("Application %s is %s.\n", app_id, str);
124
125   g_list_free_full(objects, g_object_unref);
126 }
127
128 static void launch_application(GDBusObjectManager* running_apps_manager,
129                                const char* appid,
130                                gboolean fullscreen) {
131   GError* error = NULL;
132   g_signal_connect(running_apps_manager, "object-removed",
133                    G_CALLBACK(object_removed), NULL);
134
135   GDBusProxy* running_proxy = g_dbus_proxy_new_sync(
136       g_connection,
137       G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name,
138       xwalk_running_path, xwalk_running_manager_iface, NULL, &error);
139   if (!running_proxy) {
140     g_print("Couldn't create proxy for '%s': %s\n", xwalk_running_manager_iface,
141             error->message);
142     g_error_free(error);
143     exit(1);
144   }
145
146   unsigned int launcher_pid = getpid();
147
148   GVariant* result  = g_dbus_proxy_call_sync(running_proxy, "Launch",
149       g_variant_new("(sub)", appid, launcher_pid, fullscreen),
150       G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
151   if (!result) {
152     fprintf(stderr, "Couldn't call 'Launch' method: %s\n", error->message);
153     exit(1);
154   }
155
156   g_variant_get(result, "(o)", &application_object_path);
157   fprintf(stderr, "Application launched with path '%s'\n",
158           application_object_path);
159
160   GDBusProxy* app_proxy = g_dbus_proxy_new_sync(
161       g_connection,
162       G_DBUS_PROXY_FLAGS_NONE, NULL, xwalk_service_name,
163       application_object_path, xwalk_running_app_iface, NULL, &error);
164   if (!app_proxy) {
165     g_print("Couldn't create proxy for '%s': %s\n", xwalk_running_app_iface,
166             error->message);
167     g_error_free(error);
168     exit(1);
169   }
170
171   g_signal_connect(app_proxy, "g-properties-changed",
172                    G_CALLBACK(on_app_properties_changed), NULL);
173
174   mainloop = g_main_loop_new(NULL, FALSE);
175
176 #if defined(OS_TIZEN)
177   char name[128];
178   snprintf(name, sizeof(name), "xwalk-%s", appid);
179
180   if (xwalk_appcore_init(g_argc, g_argv, name)) {
181     fprintf(stderr, "Failed to initialize appcore");
182     exit(1);
183   }
184 #endif
185
186   g_main_loop_run(mainloop);
187 }
188
189 int main(int argc, char** argv) {
190   GError* error = NULL;
191   char* appid;
192
193   g_argc = argc;
194   g_argv = argv;
195
196 #if !GLIB_CHECK_VERSION(2, 36, 0)
197   // g_type_init() is deprecated on GLib since 2.36.
198   g_type_init();
199 #endif
200
201   if (xwalk_tizen_set_home_for_user_app())
202     exit(1);
203
204   GOptionContext* context =
205       g_option_context_new("- Crosswalk Application Launcher");
206   g_option_context_add_main_entries(context, entries, NULL);
207   if (!g_option_context_parse(context, &argc, &argv, &error)) {
208     fprintf(stderr, "Option parsing failed: %s\n", error->message);
209     exit(1);
210   }
211
212   if (!strcmp(basename(argv[0]), "xwalk-launcher")) {
213     if (cmd_appid == NULL) {
214       fprintf(stderr, "No AppID informed, nothing to do.\n");
215       return 0;
216     }
217     appid = cmd_appid[0];
218   } else {
219     appid = strdup(basename(argv[0]));
220   }
221
222   g_connection = get_session_bus_connection(&error);
223   if (!g_connection) {
224     fprintf(stderr, "Couldn't get the session bus connection: %s\n",
225             error->message);
226     exit(1);
227   }
228
229   GDBusObjectManager* running_apps_manager =
230       g_dbus_object_manager_client_new_sync(
231           g_connection, G_DBUS_OBJECT_MANAGER_CLIENT_FLAGS_NONE,
232           xwalk_service_name, xwalk_running_path,
233           NULL, NULL, NULL, NULL, &error);
234   if (!running_apps_manager) {
235     fprintf(stderr, "Service '%s' does could not be reached: %s\n",
236             xwalk_service_name, error->message);
237     exit(1);
238   }
239
240   if (query_running) {
241     query_application_running(running_apps_manager, appid);
242   } else {
243     launch_application(running_apps_manager, appid, fullscreen);
244   }
245
246   return 0;
247 }