Merge lp:~ted/ubuntu-app-launch/log-file into lp:ubuntu-app-launch/14.04
- log-file
- Merge into trunk.14.04
Proposed by
Ted Gould
Status: | Superseded |
---|---|
Proposed branch: | lp:~ted/ubuntu-app-launch/log-file |
Merge into: | lp:ubuntu-app-launch/14.04 |
Diff against target: |
2657 lines (+1148/-837) 23 files modified
CMakeLists.txt (+13/-24) application-job.c (+99/-0) application.conf.in (+1/-21) debian/libupstart-app-launch2.symbols (+1/-0) desktop-single-trace.tp (+0/-5) desktop-single.c (+0/-68) helpers-keyfile.c (+95/-0) helpers.c (+0/-74) libupstart-app-launch/CMakeLists.txt (+9/-0) libupstart-app-launch/second-exec-core.c (+129/-87) libupstart-app-launch/upstart-app-launch-trace.tp (+20/-0) libupstart-app-launch/upstart-app-launch.c (+474/-240) libupstart-app-launch/upstart-app-launch.h (+13/-0) second-exec-trace.tp (+0/-16) second-exec.c (+0/-40) tests/CMakeLists.txt (+1/-18) tests/applications/multiple.desktop (+8/-0) tests/applications/single.desktop (+8/-0) tests/libual-test.cc (+272/-39) tests/link-farm/README (+3/-0) tests/link-farm/foo.desktop (+1/-0) tests/link-farm/foolike.desktop (+1/-0) tests/second-exec-test.cc (+0/-205) |
To merge this branch: | bzr merge lp:~ted/ubuntu-app-launch/log-file |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Indicator Applet Developers | Pending | ||
Review via email: mp+205241@code.launchpad.net |
This proposal has been superseded by a proposal from 2014-02-06.
Commit message
Function to get the log file for the application
Description of the change
Small function for QA so they don't have to know what is a Click app and what is not. Abstracts all that out for them.
To post a comment you must log in.
Unmerged revisions
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-01-06 15:21:25 +0000 |
3 | +++ CMakeLists.txt 2014-02-06 18:42:36 +0000 |
4 | @@ -51,9 +51,12 @@ |
5 | pkg_check_modules(ZEITGEIST REQUIRED zeitgeist-2.0) |
6 | include_directories(${ZEITGEIST_INCLUDE_DIRS}) |
7 | |
8 | -pkg_check_modules(LIBUPSTART REQUIRED libupstart libnih libnih-dbus dbus-1) |
9 | +pkg_check_modules(LIBUPSTART REQUIRED libupstart) |
10 | include_directories(${LIBUPSTART_INCLUDE_DIRS}) |
11 | |
12 | +pkg_check_modules(DBUS REQUIRED dbus-1) |
13 | +include_directories(${DBUS_INCLUDE_DIRS}) |
14 | + |
15 | pkg_check_modules(DBUSTEST REQUIRED dbustest-1>=14.04.0) |
16 | include_directories(${DBUSTEST_INCLUDE_DIRS}) |
17 | |
18 | @@ -68,7 +71,7 @@ |
19 | # Helpers |
20 | #################### |
21 | |
22 | -add_library(helpers STATIC helpers.c) |
23 | +add_library(helpers STATIC helpers.c helpers-keyfile.c) |
24 | target_link_libraries(helpers ${GIO2_LIBRARIES} ${JSONGLIB_LIBRARIES}) |
25 | |
26 | #################### |
27 | @@ -146,16 +149,6 @@ |
28 | install(TARGETS desktop-hook RUNTIME DESTINATION "${pkglibexecdir}") |
29 | |
30 | #################### |
31 | -# desktop-single |
32 | -#################### |
33 | - |
34 | -add_lttng_gen_tp(NAME desktop-single-trace) |
35 | -add_executable(desktop-single desktop-single.c desktop-single-trace.c) |
36 | -set_target_properties(desktop-single PROPERTIES OUTPUT_NAME "desktop-single") |
37 | -target_link_libraries(desktop-single helpers ${LTTNG_LIBRARIES}) |
38 | -install(TARGETS desktop-single RUNTIME DESTINATION "${pkglibexecdir}") |
39 | - |
40 | -#################### |
41 | # exec-line-exec |
42 | #################### |
43 | |
44 | @@ -175,18 +168,14 @@ |
45 | target_link_libraries(zg-report-app ${ZEITGEIST_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GLIB2_LIBRARIES}) |
46 | install(TARGETS zg-report-app RUNTIME DESTINATION "${pkglibexecdir}") |
47 | |
48 | -####################### |
49 | -# second-exec |
50 | -####################### |
51 | - |
52 | -add_lttng_gen_tp(NAME second-exec-trace) |
53 | -add_library(second-exec-core STATIC second-exec-core.c second-exec-trace.c) |
54 | -target_link_libraries(second-exec-core helpers upstart-launcher ${LTTNG_LIBRARIES}) |
55 | - |
56 | -add_executable(second-exec second-exec.c) |
57 | -set_target_properties(second-exec PROPERTIES OUTPUT_NAME "second-exec") |
58 | -target_link_libraries(second-exec second-exec-core) |
59 | -install(TARGETS second-exec RUNTIME DESTINATION "${pkglibexecdir}") |
60 | +#################### |
61 | +# application-job |
62 | +#################### |
63 | + |
64 | +add_executable(application-job application-job.c) |
65 | +set_target_properties(application-job PROPERTIES OUTPUT_NAME "application-job") |
66 | +target_link_libraries(application-job upstart-launcher) |
67 | +install(TARGETS application-job RUNTIME DESTINATION "${pkglibexecdir}") |
68 | |
69 | #################### |
70 | # application.conf |
71 | |
72 | === added file 'application-job.c' |
73 | --- application-job.c 1970-01-01 00:00:00 +0000 |
74 | +++ application-job.c 2014-02-06 18:42:36 +0000 |
75 | @@ -0,0 +1,99 @@ |
76 | +/* |
77 | + * Copyright 2013 Canonical Ltd. |
78 | + * |
79 | + * This program is free software: you can redistribute it and/or modify it |
80 | + * under the terms of the GNU General Public License version 3, as published |
81 | + * by the Free Software Foundation. |
82 | + * |
83 | + * This program is distributed in the hope that it will be useful, but |
84 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
85 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
86 | + * PURPOSE. See the GNU General Public License for more details. |
87 | + * |
88 | + * You should have received a copy of the GNU General Public License along |
89 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
90 | + * |
91 | + * Authors: |
92 | + * Ted Gould <ted.gould@canonical.com> |
93 | + */ |
94 | + |
95 | +#include <gio/gio.h> |
96 | +#include "libupstart-app-launch/upstart-app-launch.h" |
97 | + |
98 | +int retval = 0; |
99 | +const gchar * global_appid; |
100 | + |
101 | +static void |
102 | +app_started (const gchar * appid, gpointer user_data) |
103 | +{ |
104 | + if (g_strcmp0(appid, global_appid) != 0) |
105 | + return; |
106 | + g_debug("Application Started: %s", appid); |
107 | + g_main_loop_quit((GMainLoop *)user_data); |
108 | +} |
109 | + |
110 | +static void |
111 | +app_focus (const gchar * appid, gpointer user_data) |
112 | +{ |
113 | + if (g_strcmp0(appid, global_appid) != 0) |
114 | + return; |
115 | + g_debug("Application Focused"); |
116 | + g_main_loop_quit((GMainLoop *)user_data); |
117 | +} |
118 | + |
119 | +static void |
120 | +app_failed (const gchar * appid, upstart_app_launch_app_failed_t failure_type, gpointer user_data) |
121 | +{ |
122 | + if (g_strcmp0(appid, global_appid) != 0) |
123 | + return; |
124 | + g_warning("Application Startup Failed"); |
125 | + retval = 1; |
126 | + g_main_loop_quit((GMainLoop *)user_data); |
127 | +} |
128 | + |
129 | +int |
130 | +main (int argc, char * argv[]) |
131 | +{ |
132 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
133 | + g_return_val_if_fail(con != NULL, 1); |
134 | + |
135 | + global_appid = g_getenv("APP_ID"); |
136 | + g_return_val_if_fail(global_appid != NULL, 1); |
137 | + |
138 | + const gchar * uris_str = g_getenv("APP_URIS"); |
139 | + gchar ** uris = NULL; |
140 | + if (uris_str != NULL) { |
141 | + GError * error = NULL; |
142 | + gint uri_count = 0; |
143 | + g_shell_parse_argv(uris_str, &uri_count, &uris, &error); |
144 | + |
145 | + if (error != NULL) { |
146 | + g_warning("Unable to parse uris '%s': %s", uris_str, error->message); |
147 | + g_error_free(error); |
148 | + } else { |
149 | + g_debug("Got %d URIs", uri_count); |
150 | + } |
151 | + } |
152 | + |
153 | + GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
154 | + |
155 | + upstart_app_launch_observer_add_app_started(app_started, mainloop); |
156 | + upstart_app_launch_observer_add_app_focus(app_focus, mainloop); |
157 | + upstart_app_launch_observer_add_app_failed(app_failed, mainloop); |
158 | + |
159 | + g_debug("Start Application: %s", global_appid); |
160 | + g_return_val_if_fail(upstart_app_launch_start_application(global_appid, (const gchar * const *)uris), -1); |
161 | + g_strfreev(uris); |
162 | + |
163 | + g_debug("Wait for results"); |
164 | + g_main_loop_run(mainloop); |
165 | + |
166 | + upstart_app_launch_observer_delete_app_started(app_started, mainloop); |
167 | + upstart_app_launch_observer_delete_app_focus(app_focus, mainloop); |
168 | + upstart_app_launch_observer_delete_app_failed(app_failed, mainloop); |
169 | + |
170 | + g_main_loop_unref(mainloop); |
171 | + g_object_unref(con); |
172 | + |
173 | + return retval; |
174 | +} |
175 | |
176 | === modified file 'application.conf.in' |
177 | --- application.conf.in 2014-01-22 22:48:58 +0000 |
178 | +++ application.conf.in 2014-02-06 18:42:36 +0000 |
179 | @@ -14,24 +14,4 @@ |
180 | env APP_URIS |
181 | export APP_URIS |
182 | |
183 | -script |
184 | - CLICK_PKG=`echo "${APP_ID}" | cut -d _ -f 1` |
185 | - |
186 | - if [ ! -z $CLICK_PKG ] ; then |
187 | - CLICK_DIR=`click pkgdir "${CLICK_PKG}" 2> /dev/null || true` |
188 | - fi |
189 | - |
190 | - if [ ! -z $CLICK_DIR ] && [ -d $CLICK_DIR ] ; then |
191 | - if ! start application-click APP_ID="${APP_ID}" APP_URIS="${APP_URIS}"; then |
192 | - @pkglibexecdir@/second-exec |
193 | - fi |
194 | - else |
195 | - if @pkglibexecdir@/desktop-single $APP_ID ; then |
196 | - if ! start application-legacy APP_ID="${APP_ID}" INSTANCE_ID="" APP_URIS="${APP_URIS}" ; then |
197 | - @pkglibexecdir@/second-exec |
198 | - fi |
199 | - else |
200 | - start application-legacy APP_ID="${APP_ID}" INSTANCE_ID=`date -u +%s` APP_URIS="${APP_URIS}" |
201 | - fi |
202 | - fi |
203 | -end script |
204 | +exec @pkglibexecdir@/application-job |
205 | |
206 | === modified file 'debian/libupstart-app-launch2.symbols' |
207 | --- debian/libupstart-app-launch2.symbols 2014-01-29 20:08:07 +0000 |
208 | +++ debian/libupstart-app-launch2.symbols 2014-02-06 18:42:36 +0000 |
209 | @@ -1,4 +1,5 @@ |
210 | libupstart-app-launch.so.2 libupstart-app-launch2 #MINVER# |
211 | + upstart_app_launch_application_log_path@Base 0replaceme |
212 | upstart_app_launch_get_primary_pid@Base 0.2 |
213 | upstart_app_launch_list_running_apps@Base 0.2 |
214 | upstart_app_launch_observer_add_app_failed@Base 0.2 |
215 | |
216 | === removed file 'desktop-single-trace.tp' |
217 | --- desktop-single-trace.tp 2013-12-04 17:10:57 +0000 |
218 | +++ desktop-single-trace.tp 1970-01-01 00:00:00 +0000 |
219 | @@ -1,5 +0,0 @@ |
220 | - |
221 | -TRACEPOINT_EVENT(upstart_app_launch, desktop_single_start, TP_ARGS(0), TP_FIELDS()) |
222 | -TRACEPOINT_EVENT(upstart_app_launch, desktop_single_found, TP_ARGS(0), TP_FIELDS()) |
223 | -TRACEPOINT_EVENT(upstart_app_launch, desktop_single_finished, TP_ARGS(0), TP_FIELDS()) |
224 | - |
225 | |
226 | === removed file 'desktop-single.c' |
227 | --- desktop-single.c 2013-12-05 17:08:13 +0000 |
228 | +++ desktop-single.c 1970-01-01 00:00:00 +0000 |
229 | @@ -1,68 +0,0 @@ |
230 | -/* |
231 | - * Copyright 2013 Canonical Ltd. |
232 | - * |
233 | - * This program is free software: you can redistribute it and/or modify it |
234 | - * under the terms of the GNU General Public License version 3, as published |
235 | - * by the Free Software Foundation. |
236 | - * |
237 | - * This program is distributed in the hope that it will be useful, but |
238 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
239 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
240 | - * PURPOSE. See the GNU General Public License for more details. |
241 | - * |
242 | - * You should have received a copy of the GNU General Public License along |
243 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
244 | - * |
245 | - * Authors: |
246 | - * Ted Gould <ted.gould@canonical.com> |
247 | - */ |
248 | - |
249 | -#include "helpers.h" |
250 | -#include "desktop-single-trace.h" |
251 | - |
252 | -int |
253 | -main (int argc, char * argv[]) |
254 | -{ |
255 | - /* Nothing is single instance yet */ |
256 | - if (argc != 2) { |
257 | - g_error("Should be called as: %s <app_id>", argv[0]); |
258 | - return 1; |
259 | - } |
260 | - |
261 | - g_setenv("LTTNG_UST_REGISTER_TIMEOUT", "0", FALSE); /* Set to zero if not set */ |
262 | - tracepoint(upstart_app_launch, desktop_single_start); |
263 | - |
264 | - GKeyFile * keyfile = keyfile_for_appid(argv[1], NULL); |
265 | - |
266 | - if (keyfile == NULL) { |
267 | - g_error("Unable to find keyfile for application '%s'", argv[0]); |
268 | - return 1; |
269 | - } |
270 | - |
271 | - tracepoint(upstart_app_launch, desktop_single_found); |
272 | - |
273 | - gboolean singleinstance = FALSE; |
274 | - |
275 | - if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", NULL)) { |
276 | - GError * error = NULL; |
277 | - |
278 | - singleinstance = g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", &error); |
279 | - |
280 | - if (error != NULL) { |
281 | - g_warning("Unable to get single instance key for app '%s': %s", argv[1], error->message); |
282 | - g_error_free(error); |
283 | - /* Ensure that if we got an error, we assume standard case */ |
284 | - singleinstance = FALSE; |
285 | - } |
286 | - } |
287 | - |
288 | - g_key_file_free(keyfile); |
289 | - |
290 | - tracepoint(upstart_app_launch, desktop_single_finished); |
291 | - |
292 | - if (singleinstance) { |
293 | - return 0; |
294 | - } else { |
295 | - return 1; |
296 | - } |
297 | -} |
298 | |
299 | === added file 'helpers-keyfile.c' |
300 | --- helpers-keyfile.c 1970-01-01 00:00:00 +0000 |
301 | +++ helpers-keyfile.c 2014-02-06 18:42:36 +0000 |
302 | @@ -0,0 +1,95 @@ |
303 | +/* |
304 | + * Copyright 2013 Canonical Ltd. |
305 | + * |
306 | + * This program is free software: you can redistribute it and/or modify it |
307 | + * under the terms of the GNU General Public License version 3, as published |
308 | + * by the Free Software Foundation. |
309 | + * |
310 | + * This program is distributed in the hope that it will be useful, but |
311 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
312 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
313 | + * PURPOSE. See the GNU General Public License for more details. |
314 | + * |
315 | + * You should have received a copy of the GNU General Public License along |
316 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
317 | + * |
318 | + * Authors: |
319 | + * Ted Gould <ted.gould@canonical.com> |
320 | + */ |
321 | + |
322 | +#include "helpers.h" |
323 | + |
324 | +/* Check to make sure we have the sections and keys we want */ |
325 | +static gboolean |
326 | +verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop) |
327 | +{ |
328 | + if (inkeyfile == NULL) return FALSE; |
329 | + |
330 | + if (!g_key_file_has_group(inkeyfile, "Desktop Entry")) { |
331 | + g_warning("Desktop file '%s' is missing the 'Desktop Entry' group", desktop); |
332 | + return FALSE; |
333 | + } |
334 | + |
335 | + if (!g_key_file_has_key(inkeyfile, "Desktop Entry", "Exec", NULL)) { |
336 | + g_warning("Desktop file '%s' is missing the 'Exec' key", desktop); |
337 | + return FALSE; |
338 | + } |
339 | + |
340 | + return TRUE; |
341 | +} |
342 | + |
343 | +/* Try to find a desktop file in a particular data directory */ |
344 | +static GKeyFile * |
345 | +try_dir (const char * dir, const gchar * desktop) |
346 | +{ |
347 | + gchar * fullpath = g_build_filename(dir, "applications", desktop, NULL); |
348 | + GKeyFile * keyfile = g_key_file_new(); |
349 | + |
350 | + /* NOTE: Leaving off the error here as we'll get a bunch of them, |
351 | + so individuals aren't really useful */ |
352 | + gboolean loaded = g_key_file_load_from_file(keyfile, fullpath, G_KEY_FILE_NONE, NULL); |
353 | + |
354 | + g_free(fullpath); |
355 | + |
356 | + if (!loaded) { |
357 | + g_key_file_free(keyfile); |
358 | + return NULL; |
359 | + } |
360 | + |
361 | + if (!verify_keyfile(keyfile, desktop)) { |
362 | + g_key_file_free(keyfile); |
363 | + return NULL; |
364 | + } |
365 | + |
366 | + return keyfile; |
367 | +} |
368 | + |
369 | +/* Find the keyfile that we need for a particular AppID and return it. |
370 | + Or NULL if we can't find it. */ |
371 | +GKeyFile * |
372 | +keyfile_for_appid (const gchar * appid, gchar ** desktopfile) |
373 | +{ |
374 | + gchar * desktop = g_strdup_printf("%s.desktop", appid); |
375 | + |
376 | + const char * const * data_dirs = g_get_system_data_dirs(); |
377 | + GKeyFile * keyfile = NULL; |
378 | + int i; |
379 | + |
380 | + keyfile = try_dir(g_get_user_data_dir(), desktop); |
381 | + if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
382 | + *desktopfile = g_build_filename(g_get_user_data_dir(), "applications", desktop, NULL); |
383 | + } |
384 | + |
385 | + for (i = 0; data_dirs[i] != NULL && keyfile == NULL; i++) { |
386 | + keyfile = try_dir(data_dirs[i], desktop); |
387 | + |
388 | + if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
389 | + *desktopfile = g_build_filename(data_dirs[i], "applications", desktop, NULL); |
390 | + } |
391 | + } |
392 | + |
393 | + g_free(desktop); |
394 | + |
395 | + return keyfile; |
396 | +} |
397 | + |
398 | |
399 | === modified file 'helpers.c' |
400 | --- helpers.c 2013-12-12 16:57:37 +0000 |
401 | +++ helpers.c 2014-02-06 18:42:36 +0000 |
402 | @@ -468,80 +468,6 @@ |
403 | return newargv; |
404 | } |
405 | |
406 | -/* Check to make sure we have the sections and keys we want */ |
407 | -static gboolean |
408 | -verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop) |
409 | -{ |
410 | - if (inkeyfile == NULL) return FALSE; |
411 | - |
412 | - if (!g_key_file_has_group(inkeyfile, "Desktop Entry")) { |
413 | - g_warning("Desktop file '%s' is missing the 'Desktop Entry' group", desktop); |
414 | - return FALSE; |
415 | - } |
416 | - |
417 | - if (!g_key_file_has_key(inkeyfile, "Desktop Entry", "Exec", NULL)) { |
418 | - g_warning("Desktop file '%s' is missing the 'Exec' key", desktop); |
419 | - return FALSE; |
420 | - } |
421 | - |
422 | - return TRUE; |
423 | -} |
424 | - |
425 | -/* Try to find a desktop file in a particular data directory */ |
426 | -static GKeyFile * |
427 | -try_dir (const char * dir, const gchar * desktop) |
428 | -{ |
429 | - gchar * fullpath = g_build_filename(dir, "applications", desktop, NULL); |
430 | - GKeyFile * keyfile = g_key_file_new(); |
431 | - |
432 | - /* NOTE: Leaving off the error here as we'll get a bunch of them, |
433 | - so individuals aren't really useful */ |
434 | - gboolean loaded = g_key_file_load_from_file(keyfile, fullpath, G_KEY_FILE_NONE, NULL); |
435 | - |
436 | - g_free(fullpath); |
437 | - |
438 | - if (!loaded) { |
439 | - g_key_file_free(keyfile); |
440 | - return NULL; |
441 | - } |
442 | - |
443 | - if (!verify_keyfile(keyfile, desktop)) { |
444 | - g_key_file_free(keyfile); |
445 | - return NULL; |
446 | - } |
447 | - |
448 | - return keyfile; |
449 | -} |
450 | - |
451 | -/* Find the keyfile that we need for a particular AppID and return it. |
452 | - Or NULL if we can't find it. */ |
453 | -GKeyFile * |
454 | -keyfile_for_appid (const gchar * appid, gchar ** desktopfile) |
455 | -{ |
456 | - gchar * desktop = g_strdup_printf("%s.desktop", appid); |
457 | - |
458 | - const char * const * data_dirs = g_get_system_data_dirs(); |
459 | - GKeyFile * keyfile = NULL; |
460 | - int i; |
461 | - |
462 | - keyfile = try_dir(g_get_user_data_dir(), desktop); |
463 | - if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
464 | - *desktopfile = g_build_filename(g_get_user_data_dir(), "applications", desktop, NULL); |
465 | - } |
466 | - |
467 | - for (i = 0; data_dirs[i] != NULL && keyfile == NULL; i++) { |
468 | - keyfile = try_dir(data_dirs[i], desktop); |
469 | - |
470 | - if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
471 | - *desktopfile = g_build_filename(data_dirs[i], "applications", desktop, NULL); |
472 | - } |
473 | - } |
474 | - |
475 | - g_free(desktop); |
476 | - |
477 | - return keyfile; |
478 | -} |
479 | - |
480 | /* Set environment various variables to make apps work under |
481 | * confinement according to: |
482 | * https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement |
483 | |
484 | === modified file 'libupstart-app-launch/CMakeLists.txt' |
485 | --- libupstart-app-launch/CMakeLists.txt 2014-01-13 15:16:24 +0000 |
486 | +++ libupstart-app-launch/CMakeLists.txt 2014-02-06 18:42:36 +0000 |
487 | @@ -1,4 +1,7 @@ |
488 | |
489 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
490 | +include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
491 | + |
492 | ########################## |
493 | # Version Info |
494 | ########################## |
495 | @@ -11,6 +14,8 @@ |
496 | # Library |
497 | ########################## |
498 | |
499 | +add_lttng_gen_tp(NAME upstart-app-launch-trace) |
500 | + |
501 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") |
502 | |
503 | set(LAUNCHER_HEADERS |
504 | @@ -19,6 +24,9 @@ |
505 | |
506 | set(LAUNCHER_SOURCES |
507 | upstart-app-launch.c |
508 | +second-exec-core.c |
509 | +upstart-app-launch-trace.c |
510 | +"${CMAKE_SOURCE_DIR}/helpers-keyfile.c" |
511 | ) |
512 | |
513 | add_library(upstart-launcher SHARED ${LAUNCHER_SOURCES}) |
514 | @@ -34,6 +42,7 @@ |
515 | ${GOBJECT2_LIBRARIES} |
516 | ${LIBUPSTART_LIBRARIES} |
517 | ${GIO2_LIBRARIES} |
518 | + ${LTTNG_LIBRARIES} |
519 | ${JSONGLIB_LIBRARIES} |
520 | -Wl,--no-undefined |
521 | ) |
522 | |
523 | === renamed file 'second-exec-core.c' => 'libupstart-app-launch/second-exec-core.c' |
524 | --- second-exec-core.c 2013-12-06 10:38:35 +0000 |
525 | +++ libupstart-app-launch/second-exec-core.c 2014-02-06 18:42:36 +0000 |
526 | @@ -23,18 +23,21 @@ |
527 | #include "libupstart-app-launch/upstart-app-launch.h" |
528 | #include "helpers.h" |
529 | #include "second-exec-core.h" |
530 | -#include "second-exec-trace.h" |
531 | - |
532 | -/* Globals */ |
533 | -GPid app_pid = 0; |
534 | -GMainLoop * mainloop = NULL; |
535 | -guint connections_open = 0; |
536 | -const gchar * appid = NULL; |
537 | -const gchar * input_uris = NULL; |
538 | -GVariant * app_data = NULL; |
539 | -gchar * dbus_path = NULL; |
540 | -guint64 unity_starttime = 0; |
541 | -guint timer = 0; |
542 | +#include "upstart-app-launch-trace.h" |
543 | + |
544 | +typedef struct { |
545 | + GDBusConnection * bus; |
546 | + gchar * appid; |
547 | + gchar * input_uris; |
548 | + GPid app_pid; |
549 | + guint connections_open; |
550 | + GVariant * app_data; |
551 | + gchar * dbus_path; |
552 | + guint64 unity_starttime; |
553 | + guint timer; |
554 | +} second_exec_t; |
555 | + |
556 | +static void second_exec_complete (second_exec_t * data); |
557 | |
558 | /* Unity didn't respond in time, continue on */ |
559 | static gboolean |
560 | @@ -42,27 +45,27 @@ |
561 | { |
562 | tracepoint(upstart_app_launch, second_exec_resume_timeout); |
563 | g_warning("Unity didn't respond in 500ms to resume the app"); |
564 | - g_main_loop_quit(mainloop); |
565 | + second_exec_complete(user_data); |
566 | return G_SOURCE_REMOVE; |
567 | } |
568 | |
569 | /* Lower the connection count and process if it gets to zero */ |
570 | static void |
571 | -connection_count_dec (void) |
572 | +connection_count_dec (second_exec_t * data) |
573 | { |
574 | tracepoint(upstart_app_launch, second_exec_connection_complete); |
575 | - connections_open--; |
576 | - if (connections_open == 0) { |
577 | + data->connections_open--; |
578 | + if (data->connections_open == 0) { |
579 | g_debug("Finished finding connections"); |
580 | /* Check time here, either we've already heard from |
581 | Unity and we should send the data to the app (quit) or |
582 | we should wait some more */ |
583 | - guint64 timespent = g_get_monotonic_time() - unity_starttime; |
584 | + guint64 timespent = g_get_monotonic_time() - data->unity_starttime; |
585 | if (timespent > 500 /* ms */ * 1000 /* ms to us */) { |
586 | - g_main_loop_quit(mainloop); |
587 | + second_exec_complete(data); |
588 | } else { |
589 | g_debug("Timer Set"); |
590 | - timer = g_timeout_add(500 - (timespent / 1000), timer_cb, NULL); |
591 | + data->timer = g_timeout_add(500 - (timespent / 1000), timer_cb, data); |
592 | } |
593 | } |
594 | return; |
595 | @@ -73,18 +76,20 @@ |
596 | static void |
597 | unity_resume_cb (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
598 | { |
599 | + second_exec_t * data = (second_exec_t *)user_data; |
600 | g_debug("Unity Completed Resume"); |
601 | tracepoint(upstart_app_launch, second_exec_resume_complete); |
602 | |
603 | - if (timer != 0) { |
604 | - g_source_remove(timer); |
605 | + if (data->timer != 0) { |
606 | + g_source_remove(data->timer); |
607 | + data->timer = 0; |
608 | } |
609 | |
610 | - if (connections_open == 0) { |
611 | - g_main_loop_quit(mainloop); |
612 | + if (data->connections_open == 0) { |
613 | + second_exec_complete(data); |
614 | } else { |
615 | /* Make it look like we started *forever* ago */ |
616 | - unity_starttime = 0; |
617 | + data->unity_starttime = 0; |
618 | } |
619 | |
620 | return; |
621 | @@ -92,9 +97,9 @@ |
622 | |
623 | /* Turn the input string into something we can send to apps */ |
624 | static void |
625 | -parse_uris (void) |
626 | +parse_uris (second_exec_t * data) |
627 | { |
628 | - if (app_data != NULL) { |
629 | + if (data->app_data != NULL) { |
630 | /* Already done */ |
631 | return; |
632 | } |
633 | @@ -103,11 +108,11 @@ |
634 | gchar ** uri_split = NULL; |
635 | GError * error = NULL; |
636 | |
637 | - g_shell_parse_argv(input_uris, NULL, &uri_split, &error); |
638 | + g_shell_parse_argv(data->input_uris, NULL, &uri_split, &error); |
639 | |
640 | if (uri_split == NULL || uri_split[0] == NULL || error != NULL) { |
641 | if (error != NULL) { |
642 | - g_warning("Unable to parse URLs '%s': %s", input_uris, error->message); |
643 | + g_warning("Unable to parse URLs '%s': %s", data->input_uris, error->message); |
644 | g_error_free(error); |
645 | } |
646 | |
647 | @@ -136,8 +141,8 @@ |
648 | g_variant_builder_add_value(&tuple, uris); |
649 | g_variant_builder_add_value(&tuple, platform); |
650 | |
651 | - app_data = g_variant_builder_end(&tuple); |
652 | - g_variant_ref_sink(app_data); |
653 | + data->app_data = g_variant_builder_end(&tuple); |
654 | + g_variant_ref_sink(data->app_data); |
655 | |
656 | return; |
657 | } |
658 | @@ -149,14 +154,29 @@ |
659 | http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#dbus |
660 | */ |
661 | static void |
662 | -app_id_to_dbus_path (void) |
663 | +app_id_to_dbus_path (second_exec_t * data) |
664 | { |
665 | - if (dbus_path != NULL) { |
666 | + if (data->dbus_path != NULL) { |
667 | return; |
668 | } |
669 | |
670 | - dbus_path = nih_dbus_path(NULL, "", appid, NULL); |
671 | - g_debug("DBus Path: %s", dbus_path); |
672 | + GString * str = g_string_sized_new(strlen(data->appid) + 2); /* base case, we just need a / and a null */ |
673 | + g_string_append_c(str, '/'); |
674 | + |
675 | + int i; |
676 | + for (i = 0; data->appid[i] != '\0'; i++) { |
677 | + if ((data->appid[i] >= 'a' && data->appid[i] <= 'z') || |
678 | + (data->appid[i] >= 'A' && data->appid[i] <= 'Z') || |
679 | + (data->appid[i] >= '0' && data->appid[i] <= '9' && i != 0)) { |
680 | + g_string_append_c(str, data->appid[i]); |
681 | + continue; |
682 | + } |
683 | + |
684 | + g_string_append_printf(str, "_%2x", data->appid[i]); |
685 | + } |
686 | + |
687 | + data->dbus_path = g_string_free(str, FALSE); |
688 | + g_debug("DBus Path: %s", data->dbus_path); |
689 | |
690 | return; |
691 | } |
692 | @@ -178,43 +198,48 @@ |
693 | g_error_free(error); |
694 | } |
695 | |
696 | - connection_count_dec(); |
697 | + connection_count_dec(user_data); |
698 | return; |
699 | } |
700 | |
701 | /* Sends the Open message to the connection with the URIs we were given */ |
702 | static void |
703 | -contact_app (GDBusConnection * bus, const gchar * dbus_name) |
704 | +contact_app (GDBusConnection * bus, const gchar * dbus_name, second_exec_t * data) |
705 | { |
706 | tracepoint(upstart_app_launch, second_exec_contact_app); |
707 | |
708 | - parse_uris(); |
709 | - app_id_to_dbus_path(); |
710 | + parse_uris(data); |
711 | + app_id_to_dbus_path(data); |
712 | |
713 | /* Using the FD.o Application interface */ |
714 | g_dbus_connection_call(bus, |
715 | dbus_name, |
716 | - dbus_path, |
717 | + data->dbus_path, |
718 | "org.freedesktop.Application", |
719 | "Open", |
720 | - app_data, |
721 | + data->app_data, |
722 | NULL, |
723 | G_DBUS_CALL_FLAGS_NONE, |
724 | -1, |
725 | NULL, |
726 | - send_open_cb, NULL); |
727 | + send_open_cb, data); |
728 | |
729 | g_debug("Sending Open request to: %s", dbus_name); |
730 | |
731 | return; |
732 | } |
733 | |
734 | +typedef struct { |
735 | + gchar * name; |
736 | + second_exec_t * data; |
737 | +} get_pid_t; |
738 | + |
739 | /* Gets the PID for a connection, and if it matches the one we're looking |
740 | for then it tries to send a message to that connection */ |
741 | static void |
742 | get_pid_cb (GObject * object, GAsyncResult * res, gpointer user_data) |
743 | { |
744 | - gchar * dbus_name = (gchar *)user_data; |
745 | + get_pid_t * data = (get_pid_t *)user_data; |
746 | GError * error = NULL; |
747 | GVariant * vpid = NULL; |
748 | |
749 | @@ -223,12 +248,15 @@ |
750 | vpid = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); |
751 | |
752 | if (error != NULL) { |
753 | - g_warning("Unable to query PID for dbus name '%s': %s", dbus_name, error->message); |
754 | + g_warning("Unable to query PID for dbus name '%s': %s", data->name, error->message); |
755 | g_error_free(error); |
756 | - g_free(dbus_name); |
757 | |
758 | /* Lowering the connection count, this one is terminal, even if in error */ |
759 | - connection_count_dec(); |
760 | + connection_count_dec(data->data); |
761 | + |
762 | + g_free(data->name); |
763 | + g_free(data); |
764 | + |
765 | return; |
766 | } |
767 | |
768 | @@ -236,22 +264,23 @@ |
769 | g_variant_get(vpid, "(u)", &pid); |
770 | g_variant_unref(vpid); |
771 | |
772 | - if (pid == app_pid) { |
773 | + if (pid == data->data->app_pid) { |
774 | /* Trying to send a message to the connection */ |
775 | - contact_app(G_DBUS_CONNECTION(object), dbus_name); |
776 | + contact_app(G_DBUS_CONNECTION(object), data->name, data->data); |
777 | } else { |
778 | /* See if we can quit now */ |
779 | - connection_count_dec(); |
780 | + connection_count_dec(data->data); |
781 | } |
782 | |
783 | - g_free(dbus_name); |
784 | + g_free(data->name); |
785 | + g_free(data); |
786 | |
787 | return; |
788 | } |
789 | |
790 | /* Starts to look for the PID and the connections for that PID */ |
791 | void |
792 | -find_appid_pid (GDBusConnection * session) |
793 | +find_appid_pid (GDBusConnection * session, second_exec_t * data) |
794 | { |
795 | GError * error = NULL; |
796 | |
797 | @@ -276,18 +305,20 @@ |
798 | return; |
799 | } |
800 | |
801 | + g_debug("Got bus names"); |
802 | tracepoint(upstart_app_launch, second_exec_got_dbus_names); |
803 | |
804 | /* Next figure out what we're looking for (and if there is something to look for) */ |
805 | /* NOTE: We're getting the PID *after* the list of connections so |
806 | that some new process can't come in, be the same PID as it's |
807 | connection will not be in teh list we just got. */ |
808 | - app_pid = upstart_app_launch_get_primary_pid(appid); |
809 | - if (app_pid == 0) { |
810 | - g_warning("Unable to find pid for app id '%s'", appid); |
811 | + data->app_pid = upstart_app_launch_get_primary_pid(data->appid); |
812 | + if (data->app_pid == 0) { |
813 | + g_warning("Unable to find pid for app id '%s'", data->appid); |
814 | return; |
815 | } |
816 | |
817 | + g_debug("Primary PID: %d", data->app_pid); |
818 | tracepoint(upstart_app_launch, second_exec_got_primary_pid); |
819 | |
820 | /* Get the names */ |
821 | @@ -301,6 +332,10 @@ |
822 | if (!g_dbus_is_unique_name(name)) { |
823 | continue; |
824 | } |
825 | + |
826 | + get_pid_t * pid_data = g_new0(get_pid_t, 1); |
827 | + pid_data->data = data; |
828 | + pid_data->name = g_strdup(name); |
829 | |
830 | tracepoint(upstart_app_launch, second_exec_request_pid); |
831 | |
832 | @@ -315,9 +350,9 @@ |
833 | G_DBUS_CALL_FLAGS_NONE, |
834 | -1, |
835 | NULL, |
836 | - get_pid_cb, g_strdup(name)); |
837 | + get_pid_cb, pid_data); |
838 | |
839 | - connections_open++; |
840 | + data->connections_open++; |
841 | } |
842 | |
843 | g_variant_unref(names); |
844 | @@ -329,9 +364,6 @@ |
845 | gboolean |
846 | second_exec (const gchar * app_id, const gchar * appuris) |
847 | { |
848 | - appid = app_id; |
849 | - input_uris = appuris; |
850 | - |
851 | tracepoint(upstart_app_launch, second_exec_start); |
852 | |
853 | /* DBus tell us! */ |
854 | @@ -343,8 +375,11 @@ |
855 | return FALSE; |
856 | } |
857 | |
858 | - /* Allocate main loop */ |
859 | - mainloop = g_main_loop_new(NULL, FALSE); |
860 | + /* Setup our continuation data */ |
861 | + second_exec_t * data = g_new0(second_exec_t, 1); |
862 | + data->appid = g_strdup(app_id); |
863 | + data->input_uris = g_strdup(appuris); |
864 | + data->bus = session; |
865 | |
866 | /* Set up listening for the unfrozen signal from Unity */ |
867 | g_dbus_connection_signal_subscribe(session, |
868 | @@ -352,11 +387,12 @@ |
869 | "com.canonical.UpstartAppLaunch", /* interface */ |
870 | "UnityResumeResponse", /* signal */ |
871 | "/", /* path */ |
872 | - appid, /* arg0 */ |
873 | + app_id, /* arg0 */ |
874 | G_DBUS_SIGNAL_FLAGS_NONE, |
875 | - unity_resume_cb, mainloop, |
876 | + unity_resume_cb, data, |
877 | NULL); /* user data destroy */ |
878 | |
879 | + g_debug("Sending resume request"); |
880 | tracepoint(upstart_app_launch, second_exec_emit_resume); |
881 | |
882 | /* Send unfreeze to to Unity */ |
883 | @@ -365,43 +401,49 @@ |
884 | "/", /* path */ |
885 | "com.canonical.UpstartAppLaunch", /* interface */ |
886 | "UnityResumeRequest", /* signal */ |
887 | - g_variant_new("(s)", appid), |
888 | + g_variant_new("(s)", app_id), |
889 | &error); |
890 | |
891 | /* Now we start a race, we try to get to the point of knowing who |
892 | to send things to, and Unity is unfrezing it. When both are |
893 | done we can send something to the app */ |
894 | - unity_starttime = g_get_monotonic_time(); |
895 | + data->unity_starttime = g_get_monotonic_time(); |
896 | |
897 | if (error != NULL) { |
898 | /* On error let's not wait for Unity */ |
899 | g_warning("Unable to signal Unity: %s", error->message); |
900 | g_error_free(error); |
901 | error = NULL; |
902 | - unity_starttime = 0; |
903 | + data->unity_starttime = 0; |
904 | } |
905 | |
906 | /* If we've got something to give out, start looking for how */ |
907 | - if (input_uris != NULL) { |
908 | - find_appid_pid(session); |
909 | + if (data->input_uris != NULL) { |
910 | + find_appid_pid(session, data); |
911 | } |
912 | |
913 | /* Loop and wait for everything to align */ |
914 | - if (connections_open > 0 || unity_starttime > 0) { |
915 | - g_main_loop_run(mainloop); |
916 | + if (data->connections_open == 0 && data->unity_starttime == 0) { |
917 | + second_exec_complete(data); |
918 | } |
919 | - g_debug("Finishing main loop"); |
920 | - |
921 | + |
922 | + return TRUE; |
923 | +} |
924 | + |
925 | +static void |
926 | +second_exec_complete (second_exec_t * data) |
927 | +{ |
928 | + GError * error = NULL; |
929 | tracepoint(upstart_app_launch, second_exec_emit_focus); |
930 | |
931 | /* Now that we're done sending the info to the app, we can ask |
932 | Unity to focus the application. */ |
933 | - g_dbus_connection_emit_signal(session, |
934 | + g_dbus_connection_emit_signal(data->bus, |
935 | NULL, /* destination */ |
936 | "/", /* path */ |
937 | "com.canonical.UpstartAppLaunch", /* interface */ |
938 | "UnityFocusRequest", /* signal */ |
939 | - g_variant_new("(s)", appid), |
940 | + g_variant_new("(s)", data->appid), |
941 | &error); |
942 | |
943 | if (error != NULL) { |
944 | @@ -411,23 +453,23 @@ |
945 | } |
946 | |
947 | /* Make sure the signal hits the bus */ |
948 | - g_dbus_connection_flush_sync(session, NULL, NULL); |
949 | + g_dbus_connection_flush_sync(data->bus, NULL, &error); |
950 | + if (error != NULL) { |
951 | + g_warning("Unable to flush session bus: %s", error->message); |
952 | + g_error_free(error); |
953 | + error = NULL; |
954 | + } |
955 | |
956 | /* Clean up */ |
957 | - if (app_data != NULL) { |
958 | - g_variant_unref(app_data); |
959 | - app_data = NULL; |
960 | - } |
961 | - |
962 | - g_main_loop_unref(mainloop); |
963 | - g_object_unref(session); |
964 | - |
965 | - if (dbus_path != NULL) { |
966 | - nih_free(dbus_path); |
967 | - dbus_path = NULL; |
968 | - } |
969 | + g_object_unref(data->bus); |
970 | + if (data->app_data != NULL) |
971 | + g_variant_unref(data->app_data); |
972 | + g_free(data->appid); |
973 | + g_free(data->input_uris); |
974 | + g_free(data->dbus_path); |
975 | + g_free(data); |
976 | |
977 | tracepoint(upstart_app_launch, second_exec_finish); |
978 | |
979 | - return TRUE; |
980 | + return; |
981 | } |
982 | |
983 | === renamed file 'second-exec-core.h' => 'libupstart-app-launch/second-exec-core.h' |
984 | === added file 'libupstart-app-launch/upstart-app-launch-trace.tp' |
985 | --- libupstart-app-launch/upstart-app-launch-trace.tp 1970-01-01 00:00:00 +0000 |
986 | +++ libupstart-app-launch/upstart-app-launch-trace.tp 2014-02-06 18:42:36 +0000 |
987 | @@ -0,0 +1,20 @@ |
988 | + |
989 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_start, TP_ARGS(0), TP_FIELDS()) |
990 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_resume, TP_ARGS(0), TP_FIELDS()) |
991 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_complete, TP_ARGS(0), TP_FIELDS()) |
992 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_timeout, TP_ARGS(0), TP_FIELDS()) |
993 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_focus, TP_ARGS(0), TP_FIELDS()) |
994 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_finish, TP_ARGS(0), TP_FIELDS()) |
995 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_dbus_names, TP_ARGS(0), TP_FIELDS()) |
996 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_primary_pid, TP_ARGS(0), TP_FIELDS()) |
997 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_request_pid, TP_ARGS(0), TP_FIELDS()) |
998 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_pid, TP_ARGS(0), TP_FIELDS()) |
999 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_contact_app, TP_ARGS(0), TP_FIELDS()) |
1000 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_contacted, TP_ARGS(0), TP_FIELDS()) |
1001 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_error, TP_ARGS(0), TP_FIELDS()) |
1002 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_connection_complete, TP_ARGS(0), TP_FIELDS()) |
1003 | + |
1004 | +TRACEPOINT_EVENT(upstart_app_launch, desktop_single_start, TP_ARGS(0), TP_FIELDS()) |
1005 | +TRACEPOINT_EVENT(upstart_app_launch, desktop_single_found, TP_ARGS(0), TP_FIELDS()) |
1006 | +TRACEPOINT_EVENT(upstart_app_launch, desktop_single_finished, TP_ARGS(0), TP_FIELDS()) |
1007 | + |
1008 | |
1009 | === modified file 'libupstart-app-launch/upstart-app-launch.c' |
1010 | --- libupstart-app-launch/upstart-app-launch.c 2014-01-29 02:19:27 +0000 |
1011 | +++ libupstart-app-launch/upstart-app-launch.c 2014-02-06 18:42:36 +0000 |
1012 | @@ -20,53 +20,16 @@ |
1013 | #include "upstart-app-launch.h" |
1014 | #include <json-glib/json-glib.h> |
1015 | #include <upstart.h> |
1016 | -#include <nih/alloc.h> |
1017 | -#include <nih/error.h> |
1018 | #include <gio/gio.h> |
1019 | #include <string.h> |
1020 | |
1021 | -static void apps_for_job (NihDBusProxy * upstart, const gchar * name, GArray * apps, gboolean truncate_legacy); |
1022 | +#include "upstart-app-launch-trace.h" |
1023 | +#include "second-exec-core.h" |
1024 | +#include "../helpers.h" |
1025 | + |
1026 | +static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy); |
1027 | static void free_helper (gpointer value); |
1028 | |
1029 | -static NihDBusProxy * |
1030 | -nih_proxy_create (void) |
1031 | -{ |
1032 | - NihDBusProxy * upstart; |
1033 | - DBusConnection * conn; |
1034 | - DBusError error; |
1035 | - const gchar * bus_name = NULL; |
1036 | - |
1037 | - dbus_error_init(&error); |
1038 | - |
1039 | - conn = dbus_bus_get(DBUS_BUS_SESSION, &error); |
1040 | - bus_name = "com.ubuntu.Upstart"; |
1041 | - |
1042 | - if (conn == NULL) { |
1043 | - g_warning("Unable to connect to the Upstart Session: %s", error.message); |
1044 | - dbus_error_free(&error); |
1045 | - return NULL; |
1046 | - } |
1047 | - |
1048 | - dbus_error_free(&error); |
1049 | - |
1050 | - upstart = nih_dbus_proxy_new(NULL, conn, |
1051 | - bus_name, |
1052 | - DBUS_PATH_UPSTART, |
1053 | - NULL, NULL); |
1054 | - |
1055 | - if (upstart == NULL) { |
1056 | - g_warning("Unable to build proxy to Upstart"); |
1057 | - dbus_connection_unref(conn); |
1058 | - return NULL; |
1059 | - } |
1060 | - |
1061 | - dbus_connection_unref(conn); |
1062 | - |
1063 | - upstart->auto_start = FALSE; |
1064 | - |
1065 | - return upstart; |
1066 | -} |
1067 | - |
1068 | /* Function to take the urls and escape them so that they can be |
1069 | parsed on the other side correctly. */ |
1070 | static gchar * |
1071 | @@ -87,83 +50,260 @@ |
1072 | return urisjoin; |
1073 | } |
1074 | |
1075 | +typedef struct { |
1076 | + gchar * appid; |
1077 | + gchar * uris; |
1078 | +} app_start_t; |
1079 | + |
1080 | +static void |
1081 | +application_start_cb (GObject * obj, GAsyncResult * res, gpointer user_data) |
1082 | +{ |
1083 | + app_start_t * data = (app_start_t *)user_data; |
1084 | + GError * error = NULL; |
1085 | + GVariant * result = NULL; |
1086 | + |
1087 | + g_debug("Started Message Callback: %s", data->appid); |
1088 | + |
1089 | + result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error); |
1090 | + |
1091 | + if (result != NULL) |
1092 | + g_variant_unref(result); |
1093 | + |
1094 | + if (error != NULL) { |
1095 | + if (g_dbus_error_is_remote_error(error)) { |
1096 | + gchar * remote_error = g_dbus_error_get_remote_error(error); |
1097 | + g_debug("Remote error: %s", remote_error); |
1098 | + if (g_strcmp0(remote_error, "com.ubuntu.Upstart0_6.Error.AlreadyStarted") == 0) { |
1099 | + second_exec(data->appid, data->uris); |
1100 | + } |
1101 | + |
1102 | + g_free(remote_error); |
1103 | + } else { |
1104 | + g_warning("Unable to emit event to start application: %s", error->message); |
1105 | + } |
1106 | + g_error_free(error); |
1107 | + } |
1108 | + |
1109 | + g_free(data->appid); |
1110 | + g_free(data->uris); |
1111 | + g_free(data); |
1112 | +} |
1113 | + |
1114 | +/* Get the path of the job from Upstart, if we've got it already, we'll just |
1115 | + use the cache of the value */ |
1116 | +static const gchar * |
1117 | +get_jobpath (GDBusConnection * con, const gchar * jobname) |
1118 | +{ |
1119 | + gchar * cachepath = g_strdup_printf("upstart-app-lauch-job-path-cache-%s", jobname); |
1120 | + gpointer cachedata = g_object_get_data(G_OBJECT(con), cachepath); |
1121 | + |
1122 | + if (cachedata != NULL) { |
1123 | + g_free(cachepath); |
1124 | + return cachedata; |
1125 | + } |
1126 | + |
1127 | + GError * error = NULL; |
1128 | + GVariant * job_path_variant = g_dbus_connection_call_sync(con, |
1129 | + DBUS_SERVICE_UPSTART, |
1130 | + DBUS_PATH_UPSTART, |
1131 | + DBUS_INTERFACE_UPSTART, |
1132 | + "GetJobByName", |
1133 | + g_variant_new("(s)", jobname), |
1134 | + G_VARIANT_TYPE("(o)"), |
1135 | + G_DBUS_CALL_FLAGS_NONE, |
1136 | + -1, /* timeout: default */ |
1137 | + NULL, /* cancelable */ |
1138 | + &error); |
1139 | + |
1140 | + if (error != NULL) { |
1141 | + g_warning("Unable to find job '%s': %s", jobname, error->message); |
1142 | + g_error_free(error); |
1143 | + g_free(cachepath); |
1144 | + return NULL; |
1145 | + } |
1146 | + |
1147 | + gchar * job_path = NULL; |
1148 | + g_variant_get(job_path_variant, "(o)", &job_path); |
1149 | + g_variant_unref(job_path_variant); |
1150 | + |
1151 | + g_object_set_data_full(G_OBJECT(con), cachepath, job_path, g_free); |
1152 | + g_free(cachepath); |
1153 | + |
1154 | + return job_path; |
1155 | +} |
1156 | + |
1157 | +/* Check to see if a legacy app wants us to manage whether they're |
1158 | + single instance or not */ |
1159 | +static gboolean |
1160 | +legacy_single_instance (const gchar * appid) |
1161 | +{ |
1162 | + tracepoint(upstart_app_launch, desktop_single_start); |
1163 | + |
1164 | + GKeyFile * keyfile = keyfile_for_appid(appid, NULL); |
1165 | + |
1166 | + if (keyfile == NULL) { |
1167 | + g_warning("Unable to find keyfile for application '%s'", appid); |
1168 | + return FALSE; |
1169 | + } |
1170 | + |
1171 | + tracepoint(upstart_app_launch, desktop_single_found); |
1172 | + |
1173 | + gboolean singleinstance = FALSE; |
1174 | + |
1175 | + if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", NULL)) { |
1176 | + GError * error = NULL; |
1177 | + |
1178 | + singleinstance = g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", &error); |
1179 | + |
1180 | + if (error != NULL) { |
1181 | + g_warning("Unable to get single instance key for app '%s': %s", appid, error->message); |
1182 | + g_error_free(error); |
1183 | + /* Ensure that if we got an error, we assume standard case */ |
1184 | + singleinstance = FALSE; |
1185 | + } |
1186 | + } |
1187 | + |
1188 | + g_key_file_free(keyfile); |
1189 | + |
1190 | + tracepoint(upstart_app_launch, desktop_single_finished); |
1191 | + |
1192 | + return singleinstance; |
1193 | +} |
1194 | + |
1195 | +/* Determine whether it's a click package by looking for the symlink |
1196 | + that is created by the desktop hook */ |
1197 | +static gboolean |
1198 | +is_click (const gchar * appid) |
1199 | +{ |
1200 | + gchar * appiddesktop = g_strdup_printf("%s.desktop", appid); |
1201 | + gchar * click_link = NULL; |
1202 | + const gchar * link_farm_dir = g_getenv("UPSTART_APP_LAUNCH_LINK_FARM"); |
1203 | + if (G_LIKELY(link_farm_dir == NULL)) { |
1204 | + click_link = g_build_filename(g_get_home_dir(), ".cache", "upstart-app-launch", "desktop", appiddesktop, NULL); |
1205 | + } else { |
1206 | + click_link = g_build_filename(link_farm_dir, appiddesktop, NULL); |
1207 | + } |
1208 | + g_free(appiddesktop); |
1209 | + gboolean click = g_file_test(click_link, G_FILE_TEST_EXISTS); |
1210 | + g_free(click_link); |
1211 | + |
1212 | + return click; |
1213 | +} |
1214 | + |
1215 | gboolean |
1216 | upstart_app_launch_start_application (const gchar * appid, const gchar * const * uris) |
1217 | { |
1218 | - NihDBusProxy * proxy = NULL; |
1219 | - |
1220 | - proxy = nih_proxy_create(); |
1221 | - if (proxy == NULL) { |
1222 | + g_return_val_if_fail(appid != NULL, FALSE); |
1223 | + |
1224 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1225 | + g_return_val_if_fail(con != NULL, FALSE); |
1226 | + |
1227 | + gboolean click = is_click(appid); |
1228 | + |
1229 | + /* Figure out the DBus path for the job */ |
1230 | + const gchar * jobpath = NULL; |
1231 | + if (click) { |
1232 | + jobpath = get_jobpath(con, "application-click"); |
1233 | + } else { |
1234 | + jobpath = get_jobpath(con, "application-legacy"); |
1235 | + } |
1236 | + |
1237 | + if (jobpath == NULL) |
1238 | return FALSE; |
1239 | - } |
1240 | - |
1241 | - gchar * env_appid = g_strdup_printf("APP_ID=%s", appid); |
1242 | - gchar * env_uris = NULL; |
1243 | + |
1244 | + /* Callback data */ |
1245 | + app_start_t * app_start_data = g_new0(app_start_t, 1); |
1246 | + app_start_data->appid = g_strdup(appid); |
1247 | + |
1248 | + /* Build up our environment */ |
1249 | + GVariantBuilder builder; |
1250 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
1251 | + |
1252 | + g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
1253 | + |
1254 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appid))); |
1255 | |
1256 | if (uris != NULL) { |
1257 | gchar * urisjoin = app_uris_string(uris); |
1258 | - env_uris = g_strdup_printf("APP_URIS=%s", urisjoin); |
1259 | - g_free(urisjoin); |
1260 | - } |
1261 | - |
1262 | - gchar * env[3]; |
1263 | - env[0] = env_appid; |
1264 | - env[1] = env_uris; |
1265 | - env[2] = NULL; |
1266 | - |
1267 | - gboolean retval = TRUE; |
1268 | - if (upstart_emit_event_sync(NULL, proxy, "application-start", env, 0) != 0) { |
1269 | - g_warning("Unable to emit signal 'application-start'"); |
1270 | - retval = FALSE; |
1271 | - } |
1272 | - |
1273 | - g_free(env_appid); |
1274 | - g_free(env_uris); |
1275 | - nih_unref(proxy, NULL); |
1276 | - |
1277 | - return retval; |
1278 | + gchar * urienv = g_strdup_printf("APP_URIS=%s", urisjoin); |
1279 | + app_start_data->uris = urisjoin; |
1280 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(urienv)); |
1281 | + } |
1282 | + |
1283 | + if (!click) { |
1284 | + if (legacy_single_instance(appid)) { |
1285 | + g_variant_builder_add_value(&builder, g_variant_new_string("INSTANCE_ID=")); |
1286 | + } else { |
1287 | + gchar * instanceid = g_strdup_printf("INSTANCE_ID=%" G_GUINT64_FORMAT, g_get_real_time()); |
1288 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(instanceid)); |
1289 | + } |
1290 | + } |
1291 | + |
1292 | + g_variant_builder_close(&builder); |
1293 | + g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
1294 | + |
1295 | + /* Call the job start function */ |
1296 | + g_dbus_connection_call(con, |
1297 | + DBUS_SERVICE_UPSTART, |
1298 | + jobpath, |
1299 | + DBUS_INTERFACE_UPSTART_JOB, |
1300 | + "Start", |
1301 | + g_variant_builder_end(&builder), |
1302 | + NULL, |
1303 | + G_DBUS_CALL_FLAGS_NONE, |
1304 | + -1, |
1305 | + NULL, /* cancelable */ |
1306 | + application_start_cb, |
1307 | + app_start_data); |
1308 | + |
1309 | + g_object_unref(con); |
1310 | + |
1311 | + return TRUE; |
1312 | } |
1313 | |
1314 | static void |
1315 | -stop_job (NihDBusProxy * upstart, const gchar * jobname, const gchar * appname, const gchar * instanceid) |
1316 | +stop_job (GDBusConnection * con, const gchar * jobname, const gchar * appname, const gchar * instanceid) |
1317 | { |
1318 | g_debug("Stopping job %s app_id %s instance_id %s", jobname, appname, instanceid); |
1319 | - nih_local char * job_path = NULL; |
1320 | - if (upstart_get_job_by_name_sync(NULL, upstart, jobname, &job_path) != 0) { |
1321 | - g_warning("Unable to find job '%s'", jobname); |
1322 | - return; |
1323 | - } |
1324 | - |
1325 | - NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
1326 | - upstart->name, |
1327 | - job_path, |
1328 | - NULL, NULL); |
1329 | - |
1330 | - if (job_proxy == NULL) { |
1331 | - g_warning("Unable to build proxy to Job '%s'", jobname); |
1332 | - return; |
1333 | - } |
1334 | - |
1335 | - gchar * app = g_strdup_printf("APP_ID=%s", appname); |
1336 | - gchar * inst = NULL; |
1337 | + |
1338 | + const gchar * job_path = get_jobpath(con, jobname); |
1339 | + if (job_path == NULL) |
1340 | + return; |
1341 | + |
1342 | + GVariantBuilder builder; |
1343 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
1344 | + g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
1345 | + |
1346 | + g_variant_builder_add_value(&builder, |
1347 | + g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appname))); |
1348 | |
1349 | if (instanceid != NULL) { |
1350 | - inst = g_strdup_printf("INSTANCE_ID=%s", instanceid); |
1351 | - } |
1352 | - |
1353 | - gchar * env[3] = { |
1354 | - app, |
1355 | - inst, |
1356 | - NULL |
1357 | - }; |
1358 | - |
1359 | - if (job_class_stop_sync(NULL, job_proxy, env, 0) != 0) { |
1360 | - g_warning("Unable to stop job %s app %s instance %s", jobname, appname, instanceid); |
1361 | - } |
1362 | - |
1363 | - g_free(app); |
1364 | - g_free(inst); |
1365 | - nih_unref(job_proxy, NULL); |
1366 | + g_variant_builder_add_value(&builder, |
1367 | + g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instanceid))); |
1368 | + } |
1369 | + |
1370 | + g_variant_builder_close(&builder); |
1371 | + g_variant_builder_add_value(&builder, g_variant_new_boolean(FALSE)); /* wait */ |
1372 | + |
1373 | + GError * error = NULL; |
1374 | + GVariant * stop_variant = g_dbus_connection_call_sync(con, |
1375 | + DBUS_SERVICE_UPSTART, |
1376 | + job_path, |
1377 | + DBUS_INTERFACE_UPSTART_JOB, |
1378 | + "Stop", |
1379 | + g_variant_builder_end(&builder), |
1380 | + NULL, |
1381 | + G_DBUS_CALL_FLAGS_NONE, |
1382 | + -1, /* timeout: default */ |
1383 | + NULL, /* cancelable */ |
1384 | + &error); |
1385 | + |
1386 | + if (error != NULL) { |
1387 | + g_warning("Unable to stop job %s app_id %s instance_id %s: %s", jobname, appname, instanceid, error->message); |
1388 | + g_error_free(error); |
1389 | + } |
1390 | + |
1391 | + g_variant_unref(stop_variant); |
1392 | } |
1393 | |
1394 | static void |
1395 | @@ -176,25 +316,24 @@ |
1396 | gboolean |
1397 | upstart_app_launch_stop_application (const gchar * appid) |
1398 | { |
1399 | + g_return_val_if_fail(appid != NULL, FALSE); |
1400 | + |
1401 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1402 | + g_return_val_if_fail(con != NULL, FALSE); |
1403 | + |
1404 | gboolean found = FALSE; |
1405 | int i; |
1406 | - NihDBusProxy * proxy = NULL; |
1407 | - |
1408 | - proxy = nih_proxy_create(); |
1409 | - if (proxy == NULL) { |
1410 | - return FALSE; |
1411 | - } |
1412 | |
1413 | GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *)); |
1414 | g_array_set_clear_func(apps, free_helper); |
1415 | |
1416 | /* Look through the click jobs and see if any match. There can |
1417 | only be one instance for each ID in the click world */ |
1418 | - apps_for_job(proxy, "application-click", apps, FALSE); |
1419 | + apps_for_job(con, "application-click", apps, FALSE); |
1420 | for (i = 0; i < apps->len; i++) { |
1421 | const gchar * array_id = g_array_index(apps, const gchar *, i); |
1422 | if (g_strcmp0(array_id, appid) == 0) { |
1423 | - stop_job(proxy, "application-click", appid, NULL); |
1424 | + stop_job(con, "application-click", appid, NULL); |
1425 | found = TRUE; |
1426 | break; /* There can be only one with click */ |
1427 | } |
1428 | @@ -206,24 +345,71 @@ |
1429 | /* Look through the legacy apps. Trickier because we know that there |
1430 | can be many instances of the legacy jobs out there, so we might |
1431 | have to kill more than one of them. */ |
1432 | - apps_for_job(proxy, "application-legacy", apps, FALSE); |
1433 | + apps_for_job(con, "application-legacy", apps, FALSE); |
1434 | gchar * appiddash = g_strdup_printf("%s-", appid); /* Probably could go RegEx here, but let's start with just a prefix lookup */ |
1435 | for (i = 0; i < apps->len; i++) { |
1436 | const gchar * array_id = g_array_index(apps, const gchar *, i); |
1437 | if (g_str_has_prefix(array_id, appiddash)) { |
1438 | gchar * instanceid = g_strrstr(array_id, "-"); |
1439 | - stop_job(proxy, "application-legacy", appid, &(instanceid[1])); |
1440 | + stop_job(con, "application-legacy", appid, &(instanceid[1])); |
1441 | found = TRUE; |
1442 | } |
1443 | } |
1444 | g_free(appiddash); |
1445 | |
1446 | g_array_free(apps, TRUE); |
1447 | - nih_unref(proxy, NULL); |
1448 | + g_object_unref(con); |
1449 | |
1450 | return found; |
1451 | } |
1452 | |
1453 | +gchar * |
1454 | +upstart_app_launch_application_log_path (const gchar * appid) |
1455 | +{ |
1456 | + gchar * path = NULL; |
1457 | + g_return_val_if_fail(appid != NULL, NULL); |
1458 | + |
1459 | + if (is_click(appid)) { |
1460 | + gchar * appfile = g_strdup_printf("application-click-%s.log", appid); |
1461 | + path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL); |
1462 | + g_free(appfile); |
1463 | + return path; |
1464 | + } |
1465 | + |
1466 | + if (legacy_single_instance(appid)) { |
1467 | + gchar * appfile = g_strdup_printf("application-legacy-%s-.log", appid); |
1468 | + path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL); |
1469 | + g_free(appfile); |
1470 | + return path; |
1471 | + } |
1472 | + |
1473 | + /* If we're not single instance, we can't recreate the instance ID |
1474 | + but if it's running we can grab it. */ |
1475 | + unsigned int i; |
1476 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1477 | + g_return_val_if_fail(con != NULL, NULL); |
1478 | + |
1479 | + GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *)); |
1480 | + g_array_set_clear_func(apps, free_helper); |
1481 | + |
1482 | + apps_for_job(con, "application-legacy", apps, FALSE); |
1483 | + gchar * appiddash = g_strdup_printf("%s-", appid); /* Probably could go RegEx here, but let's start with just a prefix lookup */ |
1484 | + for (i = 0; i < apps->len && path == NULL; i++) { |
1485 | + const gchar * array_id = g_array_index(apps, const gchar *, i); |
1486 | + if (g_str_has_prefix(array_id, appiddash)) { |
1487 | + gchar * appfile = g_strdup_printf("application-legacy-%s.log", array_id); |
1488 | + path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL); |
1489 | + g_free(appfile); |
1490 | + } |
1491 | + } |
1492 | + g_free(appiddash); |
1493 | + |
1494 | + g_array_free(apps, TRUE); |
1495 | + g_object_unref(con); |
1496 | + |
1497 | + return path; |
1498 | +} |
1499 | + |
1500 | static GDBusConnection * |
1501 | gdbus_upstart_ref (void) { |
1502 | static GDBusConnection * gdbus_upstart = NULL; |
1503 | @@ -523,164 +709,210 @@ |
1504 | return FALSE; |
1505 | } |
1506 | |
1507 | +typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data); |
1508 | + |
1509 | +static void |
1510 | +foreach_job_instance (GDBusConnection * con, const gchar * jobname, per_instance_func_t func, gpointer user_data) |
1511 | +{ |
1512 | + const gchar * job_path = get_jobpath(con, jobname); |
1513 | + if (job_path == NULL) |
1514 | + return; |
1515 | + |
1516 | + GError * error = NULL; |
1517 | + GVariant * instance_tuple = g_dbus_connection_call_sync(con, |
1518 | + DBUS_SERVICE_UPSTART, |
1519 | + job_path, |
1520 | + DBUS_INTERFACE_UPSTART_JOB, |
1521 | + "GetAllInstances", |
1522 | + NULL, |
1523 | + G_VARIANT_TYPE("(ao)"), |
1524 | + G_DBUS_CALL_FLAGS_NONE, |
1525 | + -1, /* timeout: default */ |
1526 | + NULL, /* cancelable */ |
1527 | + &error); |
1528 | + |
1529 | + if (error != NULL) { |
1530 | + g_warning("Unable to get instances of job '%s': %s", jobname, error->message); |
1531 | + g_error_free(error); |
1532 | + return; |
1533 | + } |
1534 | + |
1535 | + GVariant * instance_list = g_variant_get_child_value(instance_tuple, 0); |
1536 | + g_variant_unref(instance_tuple); |
1537 | + |
1538 | + GVariantIter instance_iter; |
1539 | + g_variant_iter_init(&instance_iter, instance_list); |
1540 | + const gchar * instance_path = NULL; |
1541 | + |
1542 | + while (g_variant_iter_loop(&instance_iter, "&o", &instance_path)) { |
1543 | + GVariant * props_tuple = g_dbus_connection_call_sync(con, |
1544 | + DBUS_SERVICE_UPSTART, |
1545 | + instance_path, |
1546 | + "org.freedesktop.DBus.Properties", |
1547 | + "GetAll", |
1548 | + g_variant_new("(s)", DBUS_INTERFACE_UPSTART_INSTANCE), |
1549 | + G_VARIANT_TYPE("(a{sv})"), |
1550 | + G_DBUS_CALL_FLAGS_NONE, |
1551 | + -1, /* timeout: default */ |
1552 | + NULL, /* cancelable */ |
1553 | + &error); |
1554 | + |
1555 | + if (error != NULL) { |
1556 | + g_warning("Unable to name of instance '%s': %s", instance_path, error->message); |
1557 | + g_error_free(error); |
1558 | + error = NULL; |
1559 | + continue; |
1560 | + } |
1561 | + |
1562 | + GVariant * props_dict = g_variant_get_child_value(props_tuple, 0); |
1563 | + |
1564 | + func(con, props_dict, user_data); |
1565 | + |
1566 | + g_variant_unref(props_dict); |
1567 | + g_variant_unref(props_tuple); |
1568 | + |
1569 | + } |
1570 | + |
1571 | + g_variant_unref(instance_list); |
1572 | +} |
1573 | + |
1574 | +typedef struct { |
1575 | + GArray * apps; |
1576 | + gboolean truncate_legacy; |
1577 | + const gchar * jobname; |
1578 | +} apps_for_job_t; |
1579 | + |
1580 | +static void |
1581 | +apps_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data) |
1582 | +{ |
1583 | + GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
1584 | + if (namev == NULL) { |
1585 | + return; |
1586 | + } |
1587 | + |
1588 | + apps_for_job_t * data = (apps_for_job_t *)user_data; |
1589 | + gchar * instance_name = g_variant_dup_string(namev, NULL); |
1590 | + g_variant_unref(namev); |
1591 | + |
1592 | + if (data->truncate_legacy && g_strcmp0(data->jobname, "application-legacy") == 0) { |
1593 | + gchar * last_dash = g_strrstr(instance_name, "-"); |
1594 | + if (last_dash != NULL) { |
1595 | + last_dash[0] = '\0'; |
1596 | + } |
1597 | + } |
1598 | + |
1599 | + g_array_append_val(data->apps, instance_name); |
1600 | +} |
1601 | + |
1602 | /* Get all the instances for a given job name */ |
1603 | static void |
1604 | -apps_for_job (NihDBusProxy * upstart, const gchar * name, GArray * apps, gboolean truncate_legacy) |
1605 | +apps_for_job (GDBusConnection * con, const gchar * jobname, GArray * apps, gboolean truncate_legacy) |
1606 | { |
1607 | - nih_local char * job_path = NULL; |
1608 | - if (upstart_get_job_by_name_sync(NULL, upstart, name, &job_path) != 0) { |
1609 | - g_warning("Unable to find job '%s'", name); |
1610 | - return; |
1611 | - } |
1612 | - |
1613 | - nih_local NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
1614 | - upstart->name, |
1615 | - job_path, |
1616 | - NULL, NULL); |
1617 | - |
1618 | - if (job_proxy == NULL) { |
1619 | - g_warning("Unable to build proxy to Job '%s'", name); |
1620 | - return; |
1621 | - } |
1622 | - |
1623 | - nih_local char ** instances; |
1624 | - if (job_class_get_all_instances_sync(NULL, job_proxy, &instances) != 0) { |
1625 | - NihError * error = nih_error_get(); |
1626 | - g_warning("Unable to get instances for job '%s': %s", name, error->message); |
1627 | - nih_free(error); |
1628 | - return; |
1629 | - } |
1630 | - |
1631 | - int jobnum; |
1632 | - for (jobnum = 0; instances[jobnum] != NULL; jobnum++) { |
1633 | - NihDBusProxy * instance_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
1634 | - upstart->name, |
1635 | - instances[jobnum], |
1636 | - NULL, NULL); |
1637 | - |
1638 | - nih_local char * instance_name = NULL; |
1639 | - if (job_get_name_sync(NULL, instance_proxy, &instance_name) == 0) { |
1640 | - gchar * dup = g_strdup(instance_name); |
1641 | - |
1642 | - if (truncate_legacy && g_strcmp0(name, "application-legacy") == 0) { |
1643 | - gchar * last_dash = g_strrstr(dup, "-"); |
1644 | - if (last_dash != NULL) { |
1645 | - last_dash[0] = '\0'; |
1646 | - } |
1647 | - } |
1648 | - |
1649 | - g_array_append_val(apps, dup); |
1650 | - } else { |
1651 | - g_warning("Unable to get name for instance '%s' of job '%s'", instances[jobnum], name); |
1652 | - } |
1653 | - |
1654 | - nih_unref(instance_proxy, NULL); |
1655 | - } |
1656 | + apps_for_job_t data = { |
1657 | + .jobname = jobname, |
1658 | + .apps = apps, |
1659 | + .truncate_legacy = truncate_legacy |
1660 | + }; |
1661 | + |
1662 | + foreach_job_instance(con, jobname, apps_for_job_instance, &data); |
1663 | } |
1664 | |
1665 | gchar ** |
1666 | upstart_app_launch_list_running_apps (void) |
1667 | { |
1668 | - NihDBusProxy * proxy = NULL; |
1669 | - |
1670 | - proxy = nih_proxy_create(); |
1671 | - if (proxy == NULL) { |
1672 | - return g_new0(gchar *, 1); |
1673 | - } |
1674 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1675 | + g_return_val_if_fail(con != NULL, g_new0(gchar *, 1)); |
1676 | |
1677 | GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *)); |
1678 | |
1679 | - apps_for_job(proxy, "application-legacy", apps, TRUE); |
1680 | - apps_for_job(proxy, "application-click", apps, FALSE); |
1681 | + apps_for_job(con, "application-legacy", apps, TRUE); |
1682 | + apps_for_job(con, "application-click", apps, FALSE); |
1683 | |
1684 | - nih_unref(proxy, NULL); |
1685 | + g_object_unref(con); |
1686 | |
1687 | return (gchar **)g_array_free(apps, FALSE); |
1688 | } |
1689 | |
1690 | +typedef struct { |
1691 | + GPid pid; |
1692 | + const gchar * appid; |
1693 | + const gchar * jobname; |
1694 | +} pid_for_job_t; |
1695 | + |
1696 | +static void |
1697 | +pid_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data) |
1698 | +{ |
1699 | + GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
1700 | + if (namev == NULL) { |
1701 | + return; |
1702 | + } |
1703 | + |
1704 | + pid_for_job_t * data = (pid_for_job_t *)user_data; |
1705 | + gchar * instance_name = g_variant_dup_string(namev, NULL); |
1706 | + g_variant_unref(namev); |
1707 | + |
1708 | + if (g_strcmp0(data->jobname, "application-legacy") == 0) { |
1709 | + gchar * last_dash = g_strrstr(instance_name, "-"); |
1710 | + if (last_dash != NULL) { |
1711 | + last_dash[0] = '\0'; |
1712 | + } |
1713 | + } |
1714 | + |
1715 | + if (g_strcmp0(instance_name, data->appid) == 0) { |
1716 | + GVariant * processv = g_variant_lookup_value(props_dict, "processes", G_VARIANT_TYPE("a(si)")); |
1717 | + |
1718 | + if (processv != NULL) { |
1719 | + if (g_variant_n_children(processv) > 0) { |
1720 | + GVariant * first_entry = g_variant_get_child_value(processv, 0); |
1721 | + GVariant * pidv = g_variant_get_child_value(first_entry, 1); |
1722 | + |
1723 | + data->pid = g_variant_get_int32(pidv); |
1724 | + |
1725 | + g_variant_unref(pidv); |
1726 | + g_variant_unref(first_entry); |
1727 | + } |
1728 | + |
1729 | + g_variant_unref(processv); |
1730 | + } |
1731 | + } |
1732 | + |
1733 | + g_free(instance_name); |
1734 | +} |
1735 | + |
1736 | /* Look for the app for a job */ |
1737 | static GPid |
1738 | -pid_for_job (NihDBusProxy * upstart, const gchar * job, const gchar * appid) |
1739 | +pid_for_job (GDBusConnection * con, const gchar * jobname, const gchar * appid) |
1740 | { |
1741 | - nih_local char * job_path = NULL; |
1742 | - if (upstart_get_job_by_name_sync(NULL, upstart, job, &job_path) != 0) { |
1743 | - g_warning("Unable to find job '%s'", job); |
1744 | - return 0; |
1745 | - } |
1746 | - |
1747 | - NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
1748 | - upstart->name, |
1749 | - job_path, |
1750 | - NULL, NULL); |
1751 | - |
1752 | - if (job_proxy == NULL) { |
1753 | - g_warning("Unable to build proxy to Job '%s'", job); |
1754 | - return 0; |
1755 | - } |
1756 | - |
1757 | - nih_local char ** instances; |
1758 | - if (job_class_get_all_instances_sync(NULL, job_proxy, &instances) != 0) { |
1759 | - g_warning("Unable to get instances for job '%s'", job); |
1760 | - nih_unref(job_proxy, NULL); |
1761 | - return 0; |
1762 | - } |
1763 | - |
1764 | - GPid pid = 0; |
1765 | - int jobnum; |
1766 | - for (jobnum = 0; instances[jobnum] != NULL && pid == 0; jobnum++) { |
1767 | - NihDBusProxy * instance_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
1768 | - upstart->name, |
1769 | - instances[jobnum], |
1770 | - NULL, NULL); |
1771 | - |
1772 | - nih_local char * instance_name = NULL; |
1773 | - if (job_get_name_sync(NULL, instance_proxy, &instance_name) == 0) { |
1774 | - if (g_strcmp0(job, "application-legacy") == 0) { |
1775 | - gchar * last_dash = g_strrstr(instance_name, "-"); |
1776 | - if (last_dash != NULL) { |
1777 | - last_dash[0] = '\0'; |
1778 | - } |
1779 | - } |
1780 | - } else { |
1781 | - g_warning("Unable to get name for instance '%s' of job '%s'", instances[jobnum], job); |
1782 | - } |
1783 | - |
1784 | - if (g_strcmp0(instance_name, appid) == 0) { |
1785 | - nih_local JobProcessesElement ** elements; |
1786 | - if (job_get_processes_sync(NULL, instance_proxy, &elements) == 0) { |
1787 | - pid = elements[0]->item1; |
1788 | - } |
1789 | - } |
1790 | - |
1791 | - nih_unref(instance_proxy, NULL); |
1792 | - } |
1793 | - |
1794 | - nih_unref(job_proxy, NULL); |
1795 | - |
1796 | - return pid; |
1797 | + pid_for_job_t data = { |
1798 | + .jobname = jobname, |
1799 | + .appid = appid, |
1800 | + .pid = 0 |
1801 | + }; |
1802 | + |
1803 | + foreach_job_instance(con, jobname, pid_for_job_instance, &data); |
1804 | + |
1805 | + return data.pid; |
1806 | } |
1807 | |
1808 | GPid |
1809 | upstart_app_launch_get_primary_pid (const gchar * appid) |
1810 | { |
1811 | - NihDBusProxy * proxy = NULL; |
1812 | + g_return_val_if_fail(appid != NULL, 0); |
1813 | |
1814 | - proxy = nih_proxy_create(); |
1815 | - if (proxy == NULL) { |
1816 | - return 0; |
1817 | - } |
1818 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1819 | + g_return_val_if_fail(con != NULL, 0); |
1820 | |
1821 | GPid pid = 0; |
1822 | |
1823 | if (pid == 0) { |
1824 | - pid = pid_for_job(proxy, "application-legacy", appid); |
1825 | + pid = pid_for_job(con, "application-legacy", appid); |
1826 | } |
1827 | |
1828 | if (pid == 0) { |
1829 | - pid = pid_for_job(proxy, "application-click", appid); |
1830 | + pid = pid_for_job(con, "application-click", appid); |
1831 | } |
1832 | |
1833 | - nih_unref(proxy, NULL); |
1834 | + g_object_unref(con); |
1835 | |
1836 | return pid; |
1837 | } |
1838 | @@ -688,6 +920,8 @@ |
1839 | gboolean |
1840 | upstart_app_launch_pid_in_app_id (GPid pid, const gchar * appid) |
1841 | { |
1842 | + g_return_val_if_fail(appid != NULL, FALSE); |
1843 | + |
1844 | if (pid == 0) { |
1845 | return FALSE; |
1846 | } |
1847 | |
1848 | === modified file 'libupstart-app-launch/upstart-app-launch.h' |
1849 | --- libupstart-app-launch/upstart-app-launch.h 2014-01-29 02:33:52 +0000 |
1850 | +++ libupstart-app-launch/upstart-app-launch.h 2014-02-06 18:42:36 +0000 |
1851 | @@ -80,6 +80,19 @@ |
1852 | gboolean upstart_app_launch_stop_application (const gchar * appid); |
1853 | |
1854 | /** |
1855 | + * upstart_app_launch_application_log_path: |
1856 | + * @appid: ID of the application |
1857 | + * |
1858 | + * Calculates the path for the log file that may be generated by |
1859 | + * the application. The log file won't be created until the application |
1860 | + * prints some output. Also, this doens't work for legacy applications |
1861 | + * that are multi-instance, only single instance ones. |
1862 | + * |
1863 | + * Return value: Path to a log file or NULL if unavailable |
1864 | + */ |
1865 | +gchar * upstart_app_launch_application_log_path (const gchar * appid); |
1866 | + |
1867 | +/** |
1868 | * upstart_app_launch_observer_add_app_starting: |
1869 | * @observer: Callback when an application is about to start |
1870 | * @user_data: (allow none): Data to pass to the observer |
1871 | |
1872 | === removed file 'second-exec-trace.tp' |
1873 | --- second-exec-trace.tp 2013-12-04 17:32:23 +0000 |
1874 | +++ second-exec-trace.tp 1970-01-01 00:00:00 +0000 |
1875 | @@ -1,16 +0,0 @@ |
1876 | - |
1877 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_start, TP_ARGS(0), TP_FIELDS()) |
1878 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_resume, TP_ARGS(0), TP_FIELDS()) |
1879 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_complete, TP_ARGS(0), TP_FIELDS()) |
1880 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_timeout, TP_ARGS(0), TP_FIELDS()) |
1881 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_focus, TP_ARGS(0), TP_FIELDS()) |
1882 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_finish, TP_ARGS(0), TP_FIELDS()) |
1883 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_dbus_names, TP_ARGS(0), TP_FIELDS()) |
1884 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_primary_pid, TP_ARGS(0), TP_FIELDS()) |
1885 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_request_pid, TP_ARGS(0), TP_FIELDS()) |
1886 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_pid, TP_ARGS(0), TP_FIELDS()) |
1887 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_contact_app, TP_ARGS(0), TP_FIELDS()) |
1888 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_contacted, TP_ARGS(0), TP_FIELDS()) |
1889 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_error, TP_ARGS(0), TP_FIELDS()) |
1890 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_connection_complete, TP_ARGS(0), TP_FIELDS()) |
1891 | - |
1892 | |
1893 | === removed file 'second-exec.c' |
1894 | --- second-exec.c 2013-12-05 17:08:13 +0000 |
1895 | +++ second-exec.c 1970-01-01 00:00:00 +0000 |
1896 | @@ -1,40 +0,0 @@ |
1897 | -/* |
1898 | - * Copyright 2013 Canonical Ltd. |
1899 | - * |
1900 | - * This program is free software: you can redistribute it and/or modify it |
1901 | - * under the terms of the GNU General Public License version 3, as published |
1902 | - * by the Free Software Foundation. |
1903 | - * |
1904 | - * This program is distributed in the hope that it will be useful, but |
1905 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
1906 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1907 | - * PURPOSE. See the GNU General Public License for more details. |
1908 | - * |
1909 | - * You should have received a copy of the GNU General Public License along |
1910 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
1911 | - * |
1912 | - * Authors: |
1913 | - * Ted Gould <ted.gould@canonical.com> |
1914 | - */ |
1915 | - |
1916 | -#include "second-exec-core.h" |
1917 | - |
1918 | -int |
1919 | -main (int argc, char * argv[]) |
1920 | -{ |
1921 | - if (argc != 1) { |
1922 | - g_error("Should be called as: %s", argv[0]); |
1923 | - return 1; |
1924 | - } |
1925 | - |
1926 | - const gchar * appid = g_getenv("APP_ID"); |
1927 | - const gchar * appuris = g_getenv("APP_URIS"); |
1928 | - |
1929 | - g_setenv("LTTNG_UST_REGISTER_TIMEOUT", "0", FALSE); /* Set to zero if not set */ |
1930 | - |
1931 | - if (second_exec(appid, appuris)) { |
1932 | - return 0; |
1933 | - } else { |
1934 | - return 1; |
1935 | - } |
1936 | -} |
1937 | |
1938 | === modified file 'tests/CMakeLists.txt' |
1939 | --- tests/CMakeLists.txt 2014-01-13 15:16:24 +0000 |
1940 | +++ tests/CMakeLists.txt 2014-02-06 18:42:36 +0000 |
1941 | @@ -25,16 +25,6 @@ |
1942 | |
1943 | add_test (helper-handshake-test helper-handshake-test) |
1944 | |
1945 | -# Second Exec Test |
1946 | - |
1947 | -include_directories("${CMAKE_SOURCE_DIR}/libupstart-app-launch") |
1948 | - |
1949 | -add_executable (second-exec-test |
1950 | - second-exec-test.cc |
1951 | - upstart-app-launch-mock.c) |
1952 | -target_link_libraries (second-exec-test helpers gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} upstart-launcher second-exec-core) |
1953 | -add_test (second-exec-test second-exec-test) |
1954 | - |
1955 | # libUAL Test |
1956 | |
1957 | include_directories("${CMAKE_SOURCE_DIR}/libupstart-app-launch") |
1958 | @@ -43,14 +33,7 @@ |
1959 | libual-test.cc) |
1960 | target_link_libraries (libual-test helpers gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} upstart-launcher) |
1961 | |
1962 | -# NOTE: Tests are broken into individual runs to avoid problems with libdbus |
1963 | -add_test (NAME libual-test-start COMMAND libual-test --gtest_filter=*StartApplication) |
1964 | -add_test (NAME libual-test-stop COMMAND libual-test --gtest_filter=*StopApplication) |
1965 | -add_test (NAME libual-test-pid COMMAND libual-test --gtest_filter=*ApplicationPid) |
1966 | -add_test (NAME libual-test-app-id COMMAND libual-test --gtest_filter=*ApplicationId) |
1967 | -add_test (NAME libual-test-list COMMAND libual-test --gtest_filter=*ApplicationList) |
1968 | -add_test (NAME libual-test-observer COMMAND libual-test --gtest_filter=*StartStopObserver) |
1969 | -add_test (NAME libual-test-starting COMMAND libual-test --gtest_filter=*StartingResponses) |
1970 | +add_test (NAME libual-test COMMAND libual-test) |
1971 | |
1972 | # ZG Test |
1973 | |
1974 | |
1975 | === added file 'tests/applications/multiple.desktop' |
1976 | --- tests/applications/multiple.desktop 1970-01-01 00:00:00 +0000 |
1977 | +++ tests/applications/multiple.desktop 2014-02-06 18:42:36 +0000 |
1978 | @@ -0,0 +1,8 @@ |
1979 | +[Desktop Entry] |
1980 | +Name=Multiple |
1981 | +Type=Application |
1982 | +Exec=multiple |
1983 | +NoDisplay=false |
1984 | +Hidden=false |
1985 | +Terminal=false |
1986 | +X-Ubuntu-Single-Instance=false |
1987 | |
1988 | === added file 'tests/applications/single.desktop' |
1989 | --- tests/applications/single.desktop 1970-01-01 00:00:00 +0000 |
1990 | +++ tests/applications/single.desktop 2014-02-06 18:42:36 +0000 |
1991 | @@ -0,0 +1,8 @@ |
1992 | +[Desktop Entry] |
1993 | +Name=Single |
1994 | +Type=Application |
1995 | +Exec=single |
1996 | +NoDisplay=false |
1997 | +Hidden=false |
1998 | +Terminal=false |
1999 | +X-Ubuntu-Single-Instance=true |
2000 | |
2001 | === modified file 'tests/libual-test.cc' |
2002 | --- tests/libual-test.cc 2014-01-29 02:24:06 +0000 |
2003 | +++ tests/libual-test.cc 2014-02-06 18:42:36 +0000 |
2004 | @@ -31,6 +31,26 @@ |
2005 | DbusTestService * service = NULL; |
2006 | DbusTestDbusMock * mock = NULL; |
2007 | GDBusConnection * bus = NULL; |
2008 | + std::string last_focus_appid; |
2009 | + std::string last_resume_appid; |
2010 | + guint resume_timeout = 0; |
2011 | + |
2012 | + private: |
2013 | + static void focus_cb (const gchar * appid, gpointer user_data) { |
2014 | + g_debug("Focus Callback: %s", appid); |
2015 | + LibUAL * _this = static_cast<LibUAL *>(user_data); |
2016 | + _this->last_focus_appid = appid; |
2017 | + } |
2018 | + |
2019 | + static void resume_cb (const gchar * appid, gpointer user_data) { |
2020 | + g_debug("Resume Callback: %s", appid); |
2021 | + LibUAL * _this = static_cast<LibUAL *>(user_data); |
2022 | + _this->last_resume_appid = appid; |
2023 | + |
2024 | + if (_this->resume_timeout > 0) { |
2025 | + _this->pause(_this->resume_timeout); |
2026 | + } |
2027 | + } |
2028 | |
2029 | protected: |
2030 | /* Useful debugging stuff, but not on by default. You really want to |
2031 | @@ -48,8 +68,15 @@ |
2032 | } |
2033 | |
2034 | virtual void SetUp() { |
2035 | + gchar * linkfarmpath = g_build_filename(CMAKE_SOURCE_DIR, "link-farm", NULL); |
2036 | + g_setenv("UPSTART_APP_LAUNCH_LINK_FARM", linkfarmpath, TRUE); |
2037 | + g_free(linkfarmpath); |
2038 | + |
2039 | + g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
2040 | + g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR, TRUE); |
2041 | + |
2042 | service = dbus_test_service_new(NULL); |
2043 | - g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
2044 | + |
2045 | const gchar * oldpath = g_getenv("PATH"); |
2046 | gchar * newpath = g_strjoin(":", CMAKE_SOURCE_DIR, oldpath, NULL); |
2047 | g_setenv("PATH", newpath, TRUE); |
2048 | @@ -81,6 +108,14 @@ |
2049 | DbusTestDbusMockObject * jobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
2050 | |
2051 | dbus_test_dbus_mock_object_add_method(mock, jobobj, |
2052 | + "Start", |
2053 | + G_VARIANT_TYPE("(asb)"), |
2054 | + NULL, |
2055 | + "if args[0][0] == 'APP_ID=foo':" |
2056 | + " raise dbus.exceptions.DBusException('Foo running', name='com.ubuntu.Upstart0_6.Error.AlreadyStarted')", |
2057 | + NULL); |
2058 | + |
2059 | + dbus_test_dbus_mock_object_add_method(mock, jobobj, |
2060 | "Stop", |
2061 | G_VARIANT_TYPE("(asb)"), |
2062 | NULL, |
2063 | @@ -100,15 +135,24 @@ |
2064 | G_VARIANT_TYPE_STRING, |
2065 | g_variant_new_string("foo"), |
2066 | NULL); |
2067 | + gchar * process_var = g_strdup_printf("[('main', %d)]", getpid()); |
2068 | dbus_test_dbus_mock_object_add_property(mock, instobj, |
2069 | "processes", |
2070 | G_VARIANT_TYPE("a(si)"), |
2071 | - g_variant_new_parsed("[('main', 1234)]"), |
2072 | + g_variant_new_parsed(process_var), |
2073 | NULL); |
2074 | + g_free(process_var); |
2075 | |
2076 | DbusTestDbusMockObject * ljobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
2077 | |
2078 | dbus_test_dbus_mock_object_add_method(mock, ljobobj, |
2079 | + "Start", |
2080 | + G_VARIANT_TYPE("(asb)"), |
2081 | + NULL, |
2082 | + "", |
2083 | + NULL); |
2084 | + |
2085 | + dbus_test_dbus_mock_object_add_method(mock, ljobobj, |
2086 | "Stop", |
2087 | G_VARIANT_TYPE("(asb)"), |
2088 | NULL, |
2089 | @@ -140,9 +184,15 @@ |
2090 | bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2091 | g_dbus_connection_set_exit_on_close(bus, FALSE); |
2092 | g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus); |
2093 | + |
2094 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_focus(focus_cb, this)); |
2095 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_resume(resume_cb, this)); |
2096 | } |
2097 | |
2098 | virtual void TearDown() { |
2099 | + upstart_app_launch_observer_delete_app_focus(focus_cb, this); |
2100 | + upstart_app_launch_observer_delete_app_resume(resume_cb, this); |
2101 | + |
2102 | g_clear_object(&mock); |
2103 | g_clear_object(&service); |
2104 | |
2105 | @@ -150,12 +200,10 @@ |
2106 | |
2107 | unsigned int cleartry = 0; |
2108 | while (bus != NULL && cleartry < 100) { |
2109 | - g_usleep(100000); |
2110 | - while (g_main_pending()) { |
2111 | - g_main_iteration(TRUE); |
2112 | - } |
2113 | + pause(100); |
2114 | cleartry++; |
2115 | } |
2116 | + ASSERT_EQ(bus, nullptr); |
2117 | } |
2118 | |
2119 | bool check_env (GVariant * env_array, const gchar * var, const gchar * value) { |
2120 | @@ -189,18 +237,17 @@ |
2121 | } |
2122 | |
2123 | static gboolean pause_helper (gpointer pmainloop) { |
2124 | - g_main_loop_quit((GMainLoop *)pmainloop); |
2125 | + g_main_loop_quit(static_cast<GMainLoop *>(pmainloop)); |
2126 | return G_SOURCE_REMOVE; |
2127 | } |
2128 | |
2129 | void pause (guint time) { |
2130 | if (time > 0) { |
2131 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
2132 | - guint timer = g_timeout_add(time, pause_helper, mainloop); |
2133 | + g_timeout_add(time, pause_helper, mainloop); |
2134 | |
2135 | g_main_loop_run(mainloop); |
2136 | |
2137 | - g_source_remove(timer); |
2138 | g_main_loop_unref(mainloop); |
2139 | } |
2140 | |
2141 | @@ -212,35 +259,31 @@ |
2142 | |
2143 | TEST_F(LibUAL, StartApplication) |
2144 | { |
2145 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
2146 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
2147 | |
2148 | /* Basic make sure we can send the event */ |
2149 | - ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
2150 | - ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "EmitEvent", NULL, NULL), 1); |
2151 | + ASSERT_TRUE(upstart_app_launch_start_application("foolike", NULL)); |
2152 | + EXPECT_EQ(1, dbus_test_dbus_mock_object_check_method_call(mock, obj, "Start", NULL, NULL)); |
2153 | |
2154 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
2155 | |
2156 | /* Now look at the details of the call */ |
2157 | - ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
2158 | + ASSERT_TRUE(upstart_app_launch_start_application("foolike", NULL)); |
2159 | |
2160 | guint len = 0; |
2161 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "EmitEvent", &len, NULL); |
2162 | - ASSERT_NE(calls, nullptr); |
2163 | - ASSERT_EQ(len, 1); |
2164 | - |
2165 | - ASSERT_STREQ(calls->name, "EmitEvent"); |
2166 | - ASSERT_EQ(g_variant_n_children(calls->params), 3); |
2167 | - |
2168 | - GVariant * name = g_variant_get_child_value(calls->params, 0); |
2169 | - ASSERT_STREQ(g_variant_get_string(name, NULL), "application-start"); |
2170 | - g_variant_unref(name); |
2171 | - |
2172 | - GVariant * block = g_variant_get_child_value(calls->params, 2); |
2173 | - ASSERT_FALSE(g_variant_get_boolean(block)); |
2174 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
2175 | + EXPECT_NE(nullptr, calls); |
2176 | + EXPECT_EQ(1, len); |
2177 | + |
2178 | + EXPECT_STREQ("Start", calls->name); |
2179 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
2180 | + |
2181 | + GVariant * block = g_variant_get_child_value(calls->params, 1); |
2182 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
2183 | g_variant_unref(block); |
2184 | |
2185 | - GVariant * env = g_variant_get_child_value(calls->params, 1); |
2186 | - ASSERT_TRUE(check_env(env, "APP_ID", "foo")); |
2187 | + GVariant * env = g_variant_get_child_value(calls->params, 0); |
2188 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
2189 | g_variant_unref(env); |
2190 | |
2191 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
2192 | @@ -252,16 +295,16 @@ |
2193 | "file:///home/phablet/test.txt", |
2194 | NULL |
2195 | }; |
2196 | - ASSERT_TRUE(upstart_app_launch_start_application("foo", urls)); |
2197 | + ASSERT_TRUE(upstart_app_launch_start_application("foolike", urls)); |
2198 | |
2199 | len = 0; |
2200 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "EmitEvent", &len, NULL); |
2201 | - ASSERT_NE(calls, nullptr); |
2202 | - ASSERT_EQ(len, 1); |
2203 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
2204 | + EXPECT_NE(nullptr, calls); |
2205 | + EXPECT_EQ(1, len); |
2206 | |
2207 | - env = g_variant_get_child_value(calls->params, 1); |
2208 | - ASSERT_TRUE(check_env(env, "APP_ID", "foo")); |
2209 | - ASSERT_TRUE(check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
2210 | + env = g_variant_get_child_value(calls->params, 0); |
2211 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
2212 | + EXPECT_TRUE(check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
2213 | g_variant_unref(env); |
2214 | |
2215 | return; |
2216 | @@ -277,12 +320,27 @@ |
2217 | |
2218 | } |
2219 | |
2220 | +TEST_F(LibUAL, ApplicationLog) |
2221 | +{ |
2222 | + gchar * click_log = upstart_app_launch_application_log_path("foo"); |
2223 | + EXPECT_STREQ(CMAKE_SOURCE_DIR "/upstart/application-click-foo.log", click_log); |
2224 | + g_free(click_log); |
2225 | + |
2226 | + gchar * legacy_single = upstart_app_launch_application_log_path("single"); |
2227 | + EXPECT_STREQ(CMAKE_SOURCE_DIR "/upstart/application-legacy-single-.log", legacy_single); |
2228 | + g_free(legacy_single); |
2229 | + |
2230 | + gchar * legacy_multiple = upstart_app_launch_application_log_path("bar"); |
2231 | + EXPECT_STREQ(CMAKE_SOURCE_DIR "/upstart/application-legacy-bar-2342345.log", legacy_multiple); |
2232 | + g_free(legacy_multiple); |
2233 | +} |
2234 | + |
2235 | TEST_F(LibUAL, ApplicationPid) |
2236 | { |
2237 | - ASSERT_EQ(upstart_app_launch_get_primary_pid("foo"), 1234); |
2238 | - ASSERT_EQ(upstart_app_launch_get_primary_pid("bar"), 5678); |
2239 | - ASSERT_TRUE(upstart_app_launch_pid_in_app_id(1234, "foo")); |
2240 | - ASSERT_FALSE(upstart_app_launch_pid_in_app_id(5678, "foo")); |
2241 | + EXPECT_EQ(upstart_app_launch_get_primary_pid("foo"), getpid()); |
2242 | + EXPECT_EQ(upstart_app_launch_get_primary_pid("bar"), 5678); |
2243 | + EXPECT_TRUE(upstart_app_launch_pid_in_app_id(getpid(), "foo")); |
2244 | + EXPECT_FALSE(upstart_app_launch_pid_in_app_id(5678, "foo")); |
2245 | } |
2246 | |
2247 | TEST_F(LibUAL, ApplicationId) |
2248 | @@ -527,3 +585,178 @@ |
2249 | g_dbus_connection_remove_filter(session, filter); |
2250 | g_object_unref(session); |
2251 | } |
2252 | + |
2253 | +TEST_F(LibUAL, AppIdTest) |
2254 | +{ |
2255 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
2256 | + pause(50); /* Ensure all the events come through */ |
2257 | + EXPECT_EQ("foo", this->last_focus_appid); |
2258 | + EXPECT_EQ("foo", this->last_resume_appid); |
2259 | +} |
2260 | + |
2261 | +GDBusMessage * |
2262 | +filter_func_good (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
2263 | +{ |
2264 | + if (!incomming) { |
2265 | + return message; |
2266 | + } |
2267 | + |
2268 | + if (g_strcmp0(g_dbus_message_get_path(message), (gchar *)user_data) == 0) { |
2269 | + GDBusMessage * reply = g_dbus_message_new_method_reply(message); |
2270 | + g_dbus_connection_send_message(conn, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); |
2271 | + g_object_unref(message); |
2272 | + return NULL; |
2273 | + } |
2274 | + |
2275 | + return message; |
2276 | +} |
2277 | + |
2278 | +TEST_F(LibUAL, UrlSendTest) |
2279 | +{ |
2280 | + GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2281 | + guint filter = g_dbus_connection_add_filter(session, |
2282 | + filter_func_good, |
2283 | + (gpointer)"/foo", |
2284 | + NULL); |
2285 | + |
2286 | + const gchar * uris[] = { |
2287 | + "http://www.test.com", |
2288 | + NULL |
2289 | + }; |
2290 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
2291 | + pause(100); /* Ensure all the events come through */ |
2292 | + |
2293 | + EXPECT_EQ("foo", this->last_focus_appid); |
2294 | + EXPECT_EQ("foo", this->last_resume_appid); |
2295 | + |
2296 | + g_dbus_connection_remove_filter(session, filter); |
2297 | + g_object_unref(session); |
2298 | +} |
2299 | + |
2300 | +TEST_F(LibUAL, UrlSendNoObjectTest) |
2301 | +{ |
2302 | + const gchar * uris[] = { |
2303 | + "http://www.test.com", |
2304 | + NULL |
2305 | + }; |
2306 | + |
2307 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
2308 | + pause(100); /* Ensure all the events come through */ |
2309 | + |
2310 | + EXPECT_EQ("foo", this->last_focus_appid); |
2311 | + EXPECT_EQ("foo", this->last_resume_appid); |
2312 | +} |
2313 | + |
2314 | +TEST_F(LibUAL, UnityTimeoutTest) |
2315 | +{ |
2316 | + this->resume_timeout = 100; |
2317 | + |
2318 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
2319 | + pause(1000); /* Ensure all the events come through */ |
2320 | + EXPECT_EQ("foo", this->last_focus_appid); |
2321 | + EXPECT_EQ("foo", this->last_resume_appid); |
2322 | +} |
2323 | + |
2324 | +TEST_F(LibUAL, UnityTimeoutUriTest) |
2325 | +{ |
2326 | + this->resume_timeout = 200; |
2327 | + |
2328 | + const gchar * uris[] = { |
2329 | + "http://www.test.com", |
2330 | + NULL |
2331 | + }; |
2332 | + |
2333 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
2334 | + pause(1000); /* Ensure all the events come through */ |
2335 | + EXPECT_EQ("foo", this->last_focus_appid); |
2336 | + EXPECT_EQ("foo", this->last_resume_appid); |
2337 | +} |
2338 | + |
2339 | +GDBusMessage * |
2340 | +filter_respawn (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
2341 | +{ |
2342 | + if (g_strcmp0(g_dbus_message_get_member(message), "UnityResumeResponse") == 0) { |
2343 | + g_object_unref(message); |
2344 | + return NULL; |
2345 | + } |
2346 | + |
2347 | + return message; |
2348 | +} |
2349 | + |
2350 | +TEST_F(LibUAL, UnityLostTest) |
2351 | +{ |
2352 | + GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2353 | + guint filter = g_dbus_connection_add_filter(session, |
2354 | + filter_respawn, |
2355 | + NULL, |
2356 | + NULL); |
2357 | + |
2358 | + guint start = g_get_monotonic_time(); |
2359 | + |
2360 | + const gchar * uris[] = { |
2361 | + "http://www.test.com", |
2362 | + NULL |
2363 | + }; |
2364 | + |
2365 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
2366 | + |
2367 | + guint end = g_get_monotonic_time(); |
2368 | + |
2369 | + EXPECT_LT(end - start, 600 * 1000); |
2370 | + |
2371 | + pause(1000); /* Ensure all the events come through */ |
2372 | + |
2373 | + EXPECT_EQ("foo", this->last_focus_appid); |
2374 | + EXPECT_EQ("foo", this->last_resume_appid); |
2375 | + |
2376 | + g_dbus_connection_remove_filter(session, filter); |
2377 | + g_object_unref(session); |
2378 | +} |
2379 | + |
2380 | + |
2381 | +TEST_F(LibUAL, LegacySingleInstance) |
2382 | +{ |
2383 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
2384 | + |
2385 | + /* Check for a single-instance app */ |
2386 | + ASSERT_TRUE(upstart_app_launch_start_application("single", NULL)); |
2387 | + |
2388 | + guint len = 0; |
2389 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
2390 | + EXPECT_NE(nullptr, calls); |
2391 | + EXPECT_EQ(1, len); |
2392 | + |
2393 | + EXPECT_STREQ("Start", calls->name); |
2394 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
2395 | + |
2396 | + GVariant * block = g_variant_get_child_value(calls->params, 1); |
2397 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
2398 | + g_variant_unref(block); |
2399 | + |
2400 | + GVariant * env = g_variant_get_child_value(calls->params, 0); |
2401 | + EXPECT_TRUE(check_env(env, "APP_ID", "single")); |
2402 | + EXPECT_TRUE(check_env(env, "INSTANCE_ID", "")); |
2403 | + g_variant_unref(env); |
2404 | + |
2405 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
2406 | + |
2407 | + /* Check for a multi-instance app */ |
2408 | + ASSERT_TRUE(upstart_app_launch_start_application("multiple", NULL)); |
2409 | + |
2410 | + len = 0; |
2411 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
2412 | + EXPECT_NE(nullptr, calls); |
2413 | + EXPECT_EQ(1, len); |
2414 | + |
2415 | + EXPECT_STREQ("Start", calls->name); |
2416 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
2417 | + |
2418 | + block = g_variant_get_child_value(calls->params, 1); |
2419 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
2420 | + g_variant_unref(block); |
2421 | + |
2422 | + env = g_variant_get_child_value(calls->params, 0); |
2423 | + EXPECT_TRUE(check_env(env, "APP_ID", "multiple")); |
2424 | + EXPECT_FALSE(check_env(env, "INSTANCE_ID", "")); |
2425 | + g_variant_unref(env); |
2426 | +} |
2427 | |
2428 | === added directory 'tests/link-farm' |
2429 | === added file 'tests/link-farm/README' |
2430 | --- tests/link-farm/README 1970-01-01 00:00:00 +0000 |
2431 | +++ tests/link-farm/README 2014-02-06 18:42:36 +0000 |
2432 | @@ -0,0 +1,3 @@ |
2433 | +This directory is setup as our testing link farm. Anything that has a |
2434 | +desktop in here will be detected as a click package, something without |
2435 | +will be seen as a legacy package. |
2436 | |
2437 | === added file 'tests/link-farm/foo.desktop' |
2438 | --- tests/link-farm/foo.desktop 1970-01-01 00:00:00 +0000 |
2439 | +++ tests/link-farm/foo.desktop 2014-02-06 18:42:36 +0000 |
2440 | @@ -0,0 +1,1 @@ |
2441 | +Needs to exist |
2442 | |
2443 | === added file 'tests/link-farm/foolike.desktop' |
2444 | --- tests/link-farm/foolike.desktop 1970-01-01 00:00:00 +0000 |
2445 | +++ tests/link-farm/foolike.desktop 2014-02-06 18:42:36 +0000 |
2446 | @@ -0,0 +1,1 @@ |
2447 | +Needs to exist |
2448 | |
2449 | === removed file 'tests/second-exec-test.cc' |
2450 | --- tests/second-exec-test.cc 2013-12-06 11:44:25 +0000 |
2451 | +++ tests/second-exec-test.cc 1970-01-01 00:00:00 +0000 |
2452 | @@ -1,205 +0,0 @@ |
2453 | -/* |
2454 | - * Copyright 2013 Canonical Ltd. |
2455 | - * |
2456 | - * This program is free software: you can redistribute it and/or modify it |
2457 | - * under the terms of the GNU General Public License version 3, as published |
2458 | - * by the Free Software Foundation. |
2459 | - * |
2460 | - * This program is distributed in the hope that it will be useful, but |
2461 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2462 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2463 | - * PURPOSE. See the GNU General Public License for more details. |
2464 | - * |
2465 | - * You should have received a copy of the GNU General Public License along |
2466 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2467 | - * |
2468 | - * Authors: |
2469 | - * Ted Gould <ted.gould@canonical.com> |
2470 | - */ |
2471 | - |
2472 | -#include <gtest/gtest.h> |
2473 | -#include <gio/gio.h> |
2474 | - |
2475 | -extern "C" { |
2476 | -#include "../second-exec-core.h" |
2477 | -#include "upstart-app-launch.h" |
2478 | -#include "upstart-app-launch-mock.h" |
2479 | -} |
2480 | - |
2481 | -class SecondExecTest : public ::testing::Test |
2482 | -{ |
2483 | - private: |
2484 | - GTestDBus * testbus = NULL; |
2485 | - |
2486 | - protected: |
2487 | - std::string last_focus_appid; |
2488 | - std::string last_resume_appid; |
2489 | - guint resume_timeout = 0; |
2490 | - |
2491 | - private: |
2492 | - static void focus_cb (const gchar * appid, gpointer user_data) { |
2493 | - SecondExecTest * _this = static_cast<SecondExecTest *>(user_data); |
2494 | - _this->last_focus_appid = appid; |
2495 | - } |
2496 | - |
2497 | - static void resume_cb (const gchar * appid, gpointer user_data) { |
2498 | - SecondExecTest * _this = static_cast<SecondExecTest *>(user_data); |
2499 | - _this->last_resume_appid = appid; |
2500 | - |
2501 | - if (_this->resume_timeout > 0) { |
2502 | - _this->pause(_this->resume_timeout); |
2503 | - } |
2504 | - } |
2505 | - |
2506 | - protected: |
2507 | - virtual void SetUp() { |
2508 | - testbus = g_test_dbus_new(G_TEST_DBUS_NONE); |
2509 | - g_test_dbus_up(testbus); |
2510 | - |
2511 | - upstart_app_launch_observer_add_app_focus(focus_cb, this); |
2512 | - upstart_app_launch_observer_add_app_resume(resume_cb, this); |
2513 | - } |
2514 | - virtual void TearDown() { |
2515 | - upstart_app_launch_observer_delete_app_focus(focus_cb, this); |
2516 | - upstart_app_launch_observer_delete_app_resume(resume_cb, this); |
2517 | - |
2518 | - g_test_dbus_down(testbus); |
2519 | - g_object_unref(testbus); |
2520 | - } |
2521 | - |
2522 | - static gboolean pause_helper (gpointer pmainloop) { |
2523 | - g_main_loop_quit((GMainLoop *)pmainloop); |
2524 | - return G_SOURCE_REMOVE; |
2525 | - } |
2526 | - |
2527 | - void pause (guint time) { |
2528 | - if (time > 0) { |
2529 | - GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
2530 | - guint timer = g_timeout_add(time, pause_helper, mainloop); |
2531 | - |
2532 | - g_main_loop_run(mainloop); |
2533 | - |
2534 | - g_source_remove(timer); |
2535 | - g_main_loop_unref(mainloop); |
2536 | - } |
2537 | - |
2538 | - while (g_main_pending()) { |
2539 | - g_main_iteration(TRUE); |
2540 | - } |
2541 | - } |
2542 | -}; |
2543 | - |
2544 | -TEST_F(SecondExecTest, AppIdTest) |
2545 | -{ |
2546 | - ASSERT_TRUE(second_exec("foo", NULL)); |
2547 | - pause(50); /* Ensure all the events come through */ |
2548 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
2549 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
2550 | -} |
2551 | - |
2552 | -GDBusMessage * |
2553 | -filter_func_good (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
2554 | -{ |
2555 | - if (!incomming) { |
2556 | - return message; |
2557 | - } |
2558 | - |
2559 | - if (g_strcmp0(g_dbus_message_get_path(message), (gchar *)user_data) == 0) { |
2560 | - GDBusMessage * reply = g_dbus_message_new_method_reply(message); |
2561 | - g_dbus_connection_send_message(conn, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); |
2562 | - g_object_unref(message); |
2563 | - return NULL; |
2564 | - } |
2565 | - |
2566 | - return message; |
2567 | -} |
2568 | - |
2569 | -TEST_F(SecondExecTest, UrlSendTest) |
2570 | -{ |
2571 | - upstart_app_launch_mock_set_primary_pid(getpid()); |
2572 | - |
2573 | - GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2574 | - guint filter = g_dbus_connection_add_filter(session, |
2575 | - filter_func_good, |
2576 | - (gpointer)"/foo", |
2577 | - NULL); |
2578 | - |
2579 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
2580 | - pause(100); /* Ensure all the events come through */ |
2581 | - |
2582 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
2583 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
2584 | - |
2585 | - g_dbus_connection_remove_filter(session, filter); |
2586 | - g_object_unref(session); |
2587 | -} |
2588 | - |
2589 | -TEST_F(SecondExecTest, UrlSendNoObjectTest) |
2590 | -{ |
2591 | - upstart_app_launch_mock_set_primary_pid(getpid()); |
2592 | - |
2593 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
2594 | - pause(100); /* Ensure all the events come through */ |
2595 | - |
2596 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
2597 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
2598 | -} |
2599 | - |
2600 | -TEST_F(SecondExecTest, UnityTimeoutTest) |
2601 | -{ |
2602 | - this->resume_timeout = 100; |
2603 | - |
2604 | - ASSERT_TRUE(second_exec("foo", NULL)); |
2605 | - pause(100); /* Ensure all the events come through */ |
2606 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
2607 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
2608 | -} |
2609 | - |
2610 | -TEST_F(SecondExecTest, UnityTimeoutUriTest) |
2611 | -{ |
2612 | - this->resume_timeout = 200; |
2613 | - |
2614 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
2615 | - pause(100); /* Ensure all the events come through */ |
2616 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
2617 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
2618 | -} |
2619 | - |
2620 | -GDBusMessage * |
2621 | -filter_respawn (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
2622 | -{ |
2623 | - if (g_strcmp0(g_dbus_message_get_member(message), "UnityResumeResponse") == 0) { |
2624 | - g_object_unref(message); |
2625 | - return NULL; |
2626 | - } |
2627 | - |
2628 | - return message; |
2629 | -} |
2630 | - |
2631 | -TEST_F(SecondExecTest, UnityLostTest) |
2632 | -{ |
2633 | - upstart_app_launch_mock_set_primary_pid(getpid()); |
2634 | - |
2635 | - GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2636 | - guint filter = g_dbus_connection_add_filter(session, |
2637 | - filter_respawn, |
2638 | - NULL, |
2639 | - NULL); |
2640 | - |
2641 | - guint start = g_get_monotonic_time(); |
2642 | - |
2643 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
2644 | - |
2645 | - guint end = g_get_monotonic_time(); |
2646 | - |
2647 | - ASSERT_LT(end - start, 600 * 1000); |
2648 | - |
2649 | - pause(100); /* Ensure all the events come through */ |
2650 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
2651 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
2652 | - |
2653 | - g_dbus_connection_remove_filter(session, filter); |
2654 | - g_object_unref(session); |
2655 | -} |
2656 | - |
2657 | - |