Merge lp:~ted/ubuntu-app-launch/gir-support into lp:ubuntu-app-launch/14.04
- gir-support
- Merge into trunk.14.04
Status: | Merged |
---|---|
Approved by: | Ted Gould |
Approved revision: | 118 |
Merged at revision: | 126 |
Proposed branch: | lp:~ted/ubuntu-app-launch/gir-support |
Merge into: | lp:ubuntu-app-launch/14.04 |
Diff against target: |
3978 lines (+2028/-908) 38 files modified
CMakeLists.txt (+31/-24) application-failed.c (+72/-0) application-failed.conf.in (+6/-0) application-job.c (+113/-0) application.conf.in (+1/-21) cmake/FindGObjectIntrospection.cmake (+61/-0) cmake/ListOperations.cmake (+18/-0) cmake/UseGObjectIntrospection.cmake (+102/-0) data/com.canonical.UpstartAppLaunch.xml (+4/-0) debian/changelog (+6/-0) debian/control (+17/-0) debian/gir1.2-upstart-app-launch-2.install (+1/-0) debian/libupstart-app-launch2-dev.install (+1/-0) debian/rules (+1/-1) 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 (+32/-0) libupstart-app-launch/second-exec-core.c (+145/-103) libupstart-app-launch/upstart-app-launch-trace.tp (+170/-0) libupstart-app-launch/upstart-app-launch.c (+533/-242) libupstart-app-launch/upstart-app-launch.h (+54/-48) second-exec-trace.tp (+0/-16) second-exec.c (+0/-40) tests/CMakeLists.txt (+10/-18) tests/applications/multiple.desktop (+8/-0) tests/applications/single.desktop (+8/-0) tests/failure-test.cc (+151/-0) tests/libual-test.cc (+318/-40) tests/link-farm/README (+3/-0) tests/link-farm/foo.desktop (+1/-0) tests/link-farm/foolike.desktop (+1/-0) tests/manual (+7/-0) tests/second-exec-test.cc (+0/-205) tests/zg-test.cc (+55/-0) upstart-app-watch.c (+1/-1) zg-report-app.c (+2/-2) |
To merge this branch: | bzr merge lp:~ted/ubuntu-app-launch/gir-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Thomi Richards (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+201681@code.launchpad.net |
Commit message
Add GIR support to libual
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:116
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:118
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
Hi,
My observers aren't being called. This is the test script I'm using:
http://
The observer for 'failed' fails to be added (but that's expected apparently), but none of the observers are ever called. gedit opens as expected, so at least the application launching works.
Ted Gould (ted) wrote : | # |
On Tue, 2014-01-21 at 23:44 +0000, Thomi Richards wrote:
> My observers aren't being called. This is the test script I'm using:
> http:��
Switching to have a mainloop and changing the prototype of the callback
seems to fix it for me:
http:��
Thomi Richards (thomir-deactivatedaccount) wrote : | # |
LGTM
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2014-01-06 15:21:25 +0000 |
3 | +++ CMakeLists.txt 2014-02-11 03:28:22 +0000 |
4 | @@ -9,6 +9,7 @@ |
5 | set(PACKAGE ${CMAKE_PROJECT_NAME}) |
6 | |
7 | find_package(PkgConfig REQUIRED) |
8 | +find_package(GObjectIntrospection REQUIRED) |
9 | include(GNUInstallDirs) |
10 | include(CheckIncludeFile) |
11 | include(CheckFunctionExists) |
12 | @@ -51,9 +52,12 @@ |
13 | pkg_check_modules(ZEITGEIST REQUIRED zeitgeist-2.0) |
14 | include_directories(${ZEITGEIST_INCLUDE_DIRS}) |
15 | |
16 | -pkg_check_modules(LIBUPSTART REQUIRED libupstart libnih libnih-dbus dbus-1) |
17 | +pkg_check_modules(LIBUPSTART REQUIRED libupstart) |
18 | include_directories(${LIBUPSTART_INCLUDE_DIRS}) |
19 | |
20 | +pkg_check_modules(DBUS REQUIRED dbus-1) |
21 | +include_directories(${DBUS_INCLUDE_DIRS}) |
22 | + |
23 | pkg_check_modules(DBUSTEST REQUIRED dbustest-1>=14.04.0) |
24 | include_directories(${DBUSTEST_INCLUDE_DIRS}) |
25 | |
26 | @@ -68,7 +72,7 @@ |
27 | # Helpers |
28 | #################### |
29 | |
30 | -add_library(helpers STATIC helpers.c) |
31 | +add_library(helpers STATIC helpers.c helpers-keyfile.c) |
32 | target_link_libraries(helpers ${GIO2_LIBRARIES} ${JSONGLIB_LIBRARIES}) |
33 | |
34 | #################### |
35 | @@ -146,16 +150,6 @@ |
36 | install(TARGETS desktop-hook RUNTIME DESTINATION "${pkglibexecdir}") |
37 | |
38 | #################### |
39 | -# desktop-single |
40 | -#################### |
41 | - |
42 | -add_lttng_gen_tp(NAME desktop-single-trace) |
43 | -add_executable(desktop-single desktop-single.c desktop-single-trace.c) |
44 | -set_target_properties(desktop-single PROPERTIES OUTPUT_NAME "desktop-single") |
45 | -target_link_libraries(desktop-single helpers ${LTTNG_LIBRARIES}) |
46 | -install(TARGETS desktop-single RUNTIME DESTINATION "${pkglibexecdir}") |
47 | - |
48 | -#################### |
49 | # exec-line-exec |
50 | #################### |
51 | |
52 | @@ -175,18 +169,23 @@ |
53 | target_link_libraries(zg-report-app ${ZEITGEIST_LIBRARIES} ${GOBJECT2_LIBRARIES} ${GLIB2_LIBRARIES}) |
54 | install(TARGETS zg-report-app RUNTIME DESTINATION "${pkglibexecdir}") |
55 | |
56 | -####################### |
57 | -# second-exec |
58 | -####################### |
59 | - |
60 | -add_lttng_gen_tp(NAME second-exec-trace) |
61 | -add_library(second-exec-core STATIC second-exec-core.c second-exec-trace.c) |
62 | -target_link_libraries(second-exec-core helpers upstart-launcher ${LTTNG_LIBRARIES}) |
63 | - |
64 | -add_executable(second-exec second-exec.c) |
65 | -set_target_properties(second-exec PROPERTIES OUTPUT_NAME "second-exec") |
66 | -target_link_libraries(second-exec second-exec-core) |
67 | -install(TARGETS second-exec RUNTIME DESTINATION "${pkglibexecdir}") |
68 | +#################### |
69 | +# application-job |
70 | +#################### |
71 | + |
72 | +add_executable(application-job application-job.c) |
73 | +set_target_properties(application-job PROPERTIES OUTPUT_NAME "application-job") |
74 | +target_link_libraries(application-job upstart-launcher) |
75 | +install(TARGETS application-job RUNTIME DESTINATION "${pkglibexecdir}") |
76 | + |
77 | +#################### |
78 | +# application-failed |
79 | +#################### |
80 | + |
81 | +add_executable(application-failed application-failed.c) |
82 | +set_target_properties(application-failed PROPERTIES OUTPUT_NAME "application-failed") |
83 | +target_link_libraries(application-failed ${GIO2_LIBRARIES}) |
84 | +install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}") |
85 | |
86 | #################### |
87 | # application.conf |
88 | @@ -213,6 +212,14 @@ |
89 | add_test(application-click.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf") |
90 | |
91 | #################### |
92 | +# application-failed.conf |
93 | +#################### |
94 | + |
95 | +configure_file("application-failed.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf" @ONLY) |
96 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
97 | +add_test(application-failed.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf") |
98 | + |
99 | +#################### |
100 | # upstart-app-launch-desktop.click-hook |
101 | #################### |
102 | |
103 | |
104 | === added file 'application-failed.c' |
105 | --- application-failed.c 1970-01-01 00:00:00 +0000 |
106 | +++ application-failed.c 2014-02-11 03:28:22 +0000 |
107 | @@ -0,0 +1,72 @@ |
108 | + |
109 | +/* |
110 | + * Copyright 2013 Canonical Ltd. |
111 | + * |
112 | + * This program is free software: you can redistribute it and/or modify it |
113 | + * under the terms of the GNU General Public License version 3, as published |
114 | + * by the Free Software Foundation. |
115 | + * |
116 | + * This program is distributed in the hope that it will be useful, but |
117 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
118 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
119 | + * PURPOSE. See the GNU General Public License for more details. |
120 | + * |
121 | + * You should have received a copy of the GNU General Public License along |
122 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
123 | + * |
124 | + * Authors: |
125 | + * Ted Gould <ted.gould@canonical.com> |
126 | + */ |
127 | + |
128 | +#include <gio/gio.h> |
129 | + |
130 | +int |
131 | +main (int argc, char * argv[]) |
132 | +{ |
133 | + const gchar * job = g_getenv("JOB"); |
134 | + g_return_val_if_fail(job != NULL, -1); |
135 | + |
136 | + const gchar * instance = g_getenv("INSTANCE"); |
137 | + g_return_val_if_fail(instance != NULL, -1); |
138 | + |
139 | + gboolean crashed = FALSE; |
140 | + if (g_getenv("EXIT_STATUS") != NULL || g_getenv("EXIT_SIGNAL") != NULL) { |
141 | + crashed = TRUE; |
142 | + } |
143 | + |
144 | + gchar * appid = g_strdup(instance); |
145 | + if (g_strcmp0(job, "application-legacy") == 0) { |
146 | + gchar * lasthyphenstanding = g_strrstr(appid, "-"); |
147 | + if (lasthyphenstanding != NULL) { |
148 | + lasthyphenstanding[0] = '\0'; |
149 | + } else { |
150 | + g_warning("Legacy job instance '%s' is missing a hyphen", appid); |
151 | + } |
152 | + } |
153 | + |
154 | + GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
155 | + g_return_val_if_fail(bus != NULL, -1); |
156 | + |
157 | + GError * error = NULL; |
158 | + g_dbus_connection_emit_signal(bus, |
159 | + NULL, /* destination */ |
160 | + "/", /* path */ |
161 | + "com.canonical.UpstartAppLaunch", |
162 | + "ApplicationFailed", |
163 | + g_variant_new("(ss)", appid, crashed ? "crash" : "start-failure"), |
164 | + &error); |
165 | + |
166 | + g_debug("Emitting failed event '%s' for app '%s'", crashed ? "crash" : "start-failure", appid); |
167 | + |
168 | + if (error != NULL) { |
169 | + g_warning("Unable to emit signal: %s", error->message); |
170 | + g_error_free(error); |
171 | + return -1; |
172 | + } |
173 | + |
174 | + g_dbus_connection_flush_sync(bus, NULL, NULL); |
175 | + g_object_unref(bus); |
176 | + g_free(appid); |
177 | + |
178 | + return 0; |
179 | +} |
180 | |
181 | === added file 'application-failed.conf.in' |
182 | --- application-failed.conf.in 1970-01-01 00:00:00 +0000 |
183 | +++ application-failed.conf.in 2014-02-11 03:28:22 +0000 |
184 | @@ -0,0 +1,6 @@ |
185 | +description "Application Failing" |
186 | + |
187 | +start on stopped application-legacy RESULT=failed or stopped application-click RESULT=failed |
188 | +task |
189 | + |
190 | +exec @pkglibexecdir@/application-failed |
191 | |
192 | === added file 'application-job.c' |
193 | --- application-job.c 1970-01-01 00:00:00 +0000 |
194 | +++ application-job.c 2014-02-11 03:28:22 +0000 |
195 | @@ -0,0 +1,113 @@ |
196 | +/* |
197 | + * Copyright 2013 Canonical Ltd. |
198 | + * |
199 | + * This program is free software: you can redistribute it and/or modify it |
200 | + * under the terms of the GNU General Public License version 3, as published |
201 | + * by the Free Software Foundation. |
202 | + * |
203 | + * This program is distributed in the hope that it will be useful, but |
204 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
205 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
206 | + * PURPOSE. See the GNU General Public License for more details. |
207 | + * |
208 | + * You should have received a copy of the GNU General Public License along |
209 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
210 | + * |
211 | + * Authors: |
212 | + * Ted Gould <ted.gould@canonical.com> |
213 | + */ |
214 | + |
215 | +#include <gio/gio.h> |
216 | +#include "libupstart-app-launch/upstart-app-launch.h" |
217 | + |
218 | +int retval = 0; |
219 | +const gchar * global_appid; |
220 | + |
221 | +static void |
222 | +app_started (const gchar * appid, gpointer user_data) |
223 | +{ |
224 | + if (g_strcmp0(appid, global_appid) != 0) |
225 | + return; |
226 | + g_debug("Application Started: %s", appid); |
227 | + g_main_loop_quit((GMainLoop *)user_data); |
228 | +} |
229 | + |
230 | +static void |
231 | +app_focus (const gchar * appid, gpointer user_data) |
232 | +{ |
233 | + if (g_strcmp0(appid, global_appid) != 0) |
234 | + return; |
235 | + g_debug("Application Focused"); |
236 | + g_main_loop_quit((GMainLoop *)user_data); |
237 | +} |
238 | + |
239 | +static void |
240 | +app_failed (const gchar * appid, upstart_app_launch_app_failed_t failure_type, gpointer user_data) |
241 | +{ |
242 | + if (g_strcmp0(appid, global_appid) != 0) |
243 | + return; |
244 | + g_warning("Application Startup Failed"); |
245 | + retval = 1; |
246 | + g_main_loop_quit((GMainLoop *)user_data); |
247 | +} |
248 | + |
249 | +/* A fallback so that we can see what is going on. The job can not always signal |
250 | + that it has been started, and thus we wouldn't quit. Which would be a bad thing. */ |
251 | +static gboolean |
252 | +timeout_check (gpointer user_data) |
253 | +{ |
254 | + g_debug("Timeout reached"); |
255 | + g_main_loop_quit((GMainLoop *)user_data); |
256 | + return TRUE; /* Keep the source connected to avoid the disconnect error */ |
257 | +} |
258 | + |
259 | +int |
260 | +main (int argc, char * argv[]) |
261 | +{ |
262 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
263 | + g_return_val_if_fail(con != NULL, 1); |
264 | + |
265 | + global_appid = g_getenv("APP_ID"); |
266 | + g_return_val_if_fail(global_appid != NULL, 1); |
267 | + |
268 | + const gchar * uris_str = g_getenv("APP_URIS"); |
269 | + gchar ** uris = NULL; |
270 | + if (uris_str != NULL) { |
271 | + GError * error = NULL; |
272 | + gint uri_count = 0; |
273 | + g_shell_parse_argv(uris_str, &uri_count, &uris, &error); |
274 | + |
275 | + if (error != NULL) { |
276 | + g_warning("Unable to parse uris '%s': %s", uris_str, error->message); |
277 | + g_error_free(error); |
278 | + } else { |
279 | + g_debug("Got %d URIs", uri_count); |
280 | + } |
281 | + } |
282 | + |
283 | + GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
284 | + |
285 | + upstart_app_launch_observer_add_app_started(app_started, mainloop); |
286 | + upstart_app_launch_observer_add_app_focus(app_focus, mainloop); |
287 | + upstart_app_launch_observer_add_app_failed(app_failed, mainloop); |
288 | + |
289 | + guint timer = g_timeout_add_seconds(1, timeout_check, mainloop); |
290 | + |
291 | + g_debug("Start Application: %s", global_appid); |
292 | + g_return_val_if_fail(upstart_app_launch_start_application(global_appid, (const gchar * const *)uris), -1); |
293 | + g_strfreev(uris); |
294 | + |
295 | + g_debug("Wait for results"); |
296 | + g_main_loop_run(mainloop); |
297 | + |
298 | + g_source_remove(timer); |
299 | + |
300 | + upstart_app_launch_observer_delete_app_started(app_started, mainloop); |
301 | + upstart_app_launch_observer_delete_app_focus(app_focus, mainloop); |
302 | + upstart_app_launch_observer_delete_app_failed(app_failed, mainloop); |
303 | + |
304 | + g_main_loop_unref(mainloop); |
305 | + g_object_unref(con); |
306 | + |
307 | + return retval; |
308 | +} |
309 | |
310 | === modified file 'application.conf.in' |
311 | --- application.conf.in 2014-01-22 22:48:58 +0000 |
312 | +++ application.conf.in 2014-02-11 03:28:22 +0000 |
313 | @@ -14,24 +14,4 @@ |
314 | env APP_URIS |
315 | export APP_URIS |
316 | |
317 | -script |
318 | - CLICK_PKG=`echo "${APP_ID}" | cut -d _ -f 1` |
319 | - |
320 | - if [ ! -z $CLICK_PKG ] ; then |
321 | - CLICK_DIR=`click pkgdir "${CLICK_PKG}" 2> /dev/null || true` |
322 | - fi |
323 | - |
324 | - if [ ! -z $CLICK_DIR ] && [ -d $CLICK_DIR ] ; then |
325 | - if ! start application-click APP_ID="${APP_ID}" APP_URIS="${APP_URIS}"; then |
326 | - @pkglibexecdir@/second-exec |
327 | - fi |
328 | - else |
329 | - if @pkglibexecdir@/desktop-single $APP_ID ; then |
330 | - if ! start application-legacy APP_ID="${APP_ID}" INSTANCE_ID="" APP_URIS="${APP_URIS}" ; then |
331 | - @pkglibexecdir@/second-exec |
332 | - fi |
333 | - else |
334 | - start application-legacy APP_ID="${APP_ID}" INSTANCE_ID=`date -u +%s` APP_URIS="${APP_URIS}" |
335 | - fi |
336 | - fi |
337 | -end script |
338 | +exec @pkglibexecdir@/application-job |
339 | |
340 | === added file 'cmake/FindGObjectIntrospection.cmake' |
341 | --- cmake/FindGObjectIntrospection.cmake 1970-01-01 00:00:00 +0000 |
342 | +++ cmake/FindGObjectIntrospection.cmake 2014-02-11 03:28:22 +0000 |
343 | @@ -0,0 +1,61 @@ |
344 | +# - try to find gobject-introspection |
345 | +# |
346 | +# Once done this will define |
347 | +# |
348 | +# INTROSPECTION_FOUND - system has gobject-introspection |
349 | +# INTROSPECTION_SCANNER - the gobject-introspection scanner, g-ir-scanner |
350 | +# INTROSPECTION_COMPILER - the gobject-introspection compiler, g-ir-compiler |
351 | +# INTROSPECTION_GENERATE - the gobject-introspection generate, g-ir-generate |
352 | +# INTROSPECTION_GIRDIR |
353 | +# INTROSPECTION_TYPELIBDIR |
354 | +# INTROSPECTION_CFLAGS |
355 | +# INTROSPECTION_LIBS |
356 | +# |
357 | +# Copyright (C) 2010, Pino Toscano, <pino@kde.org> |
358 | +# |
359 | +# Redistribution and use is allowed according to the terms of the BSD license. |
360 | +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. |
361 | + |
362 | +macro(_GIR_GET_PKGCONFIG_VAR _outvar _varname) |
363 | + execute_process( |
364 | + COMMAND ${PKG_CONFIG_EXECUTABLE} --variable=${_varname} gobject-introspection-1.0 |
365 | + OUTPUT_VARIABLE _result |
366 | + RESULT_VARIABLE _null |
367 | + ) |
368 | + |
369 | + if (_null) |
370 | + else() |
371 | + string(REGEX REPLACE "[\r\n]" " " _result "${_result}") |
372 | + string(REGEX REPLACE " +$" "" _result "${_result}") |
373 | + separate_arguments(_result) |
374 | + set(${_outvar} ${_result} CACHE INTERNAL "") |
375 | + endif() |
376 | +endmacro(_GIR_GET_PKGCONFIG_VAR) |
377 | + |
378 | +find_package(PkgConfig) |
379 | +if(PKG_CONFIG_FOUND) |
380 | + if(PACKAGE_FIND_VERSION_COUNT GREATER 0) |
381 | + set(_gir_version_cmp ">=${PACKAGE_FIND_VERSION}") |
382 | + endif() |
383 | + pkg_check_modules(_pc_gir gobject-introspection-1.0${_gir_version_cmp}) |
384 | + if(_pc_gir_FOUND) |
385 | + set(INTROSPECTION_FOUND TRUE) |
386 | + _gir_get_pkgconfig_var(INTROSPECTION_SCANNER "g_ir_scanner") |
387 | + _gir_get_pkgconfig_var(INTROSPECTION_COMPILER "g_ir_compiler") |
388 | + _gir_get_pkgconfig_var(INTROSPECTION_GENERATE "g_ir_generate") |
389 | + _gir_get_pkgconfig_var(INTROSPECTION_GIRDIR "girdir") |
390 | + _gir_get_pkgconfig_var(INTROSPECTION_TYPELIBDIR "typelibdir") |
391 | + set(INTROSPECTION_CFLAGS "${_pc_gir_CFLAGS}") |
392 | + set(INTROSPECTION_LIBS "${_pc_gir_LIBS}") |
393 | + endif() |
394 | +endif() |
395 | + |
396 | +mark_as_advanced( |
397 | + INTROSPECTION_SCANNER |
398 | + INTROSPECTION_COMPILER |
399 | + INTROSPECTION_GENERATE |
400 | + INTROSPECTION_GIRDIR |
401 | + INTROSPECTION_TYPELIBDIR |
402 | + INTROSPECTION_CFLAGS |
403 | + INTROSPECTION_LIBS |
404 | +) |
405 | |
406 | === added file 'cmake/ListOperations.cmake' |
407 | --- cmake/ListOperations.cmake 1970-01-01 00:00:00 +0000 |
408 | +++ cmake/ListOperations.cmake 2014-02-11 03:28:22 +0000 |
409 | @@ -0,0 +1,18 @@ |
410 | + |
411 | +macro(list_prefix _outvar _listvar _prefix) |
412 | + set(${_outvar}) |
413 | + foreach(_item IN LISTS ${_listvar}) |
414 | + list(APPEND ${_outvar} ${_prefix}${_item}) |
415 | + endforeach() |
416 | +endmacro(list_prefix) |
417 | + |
418 | +macro(list_make_absolute _outvar _listvar _prefix) |
419 | + set(${_outvar}) |
420 | + foreach(_item IN LISTS ${_listvar}) |
421 | + if(IS_ABSOLUTE ${_item}) |
422 | + list(APPEND ${_outvar} ${_item}) |
423 | + else() |
424 | + list(APPEND ${_outvar} ${_prefix}${_item}) |
425 | + endif() |
426 | + endforeach() |
427 | +endmacro(list_make_absolute) |
428 | |
429 | === added file 'cmake/UseGObjectIntrospection.cmake' |
430 | --- cmake/UseGObjectIntrospection.cmake 1970-01-01 00:00:00 +0000 |
431 | +++ cmake/UseGObjectIntrospection.cmake 2014-02-11 03:28:22 +0000 |
432 | @@ -0,0 +1,102 @@ |
433 | +# Copyright (C) 2010, Pino Toscano, <pino@kde.org> |
434 | +# |
435 | +# Redistribution and use is allowed according to the terms of the BSD license. |
436 | +# For details see the accompanying COPYING-CMAKE-SCRIPTS file. |
437 | + |
438 | +include(ListOperations) |
439 | + |
440 | +macro(_gir_list_prefix _outvar _listvar _prefix) |
441 | + set(${_outvar}) |
442 | + foreach(_item IN LISTS ${_listvar}) |
443 | + list(APPEND ${_outvar} ${_prefix}${_item}) |
444 | + endforeach() |
445 | +endmacro(_gir_list_prefix) |
446 | + |
447 | +macro(gir_add_introspections introspections_girs) |
448 | + |
449 | + foreach(gir IN LISTS ${introspections_girs}) |
450 | + |
451 | + set(_gir_name "${gir}") |
452 | + |
453 | + ## Transform the gir filename to something which can reference through a variable |
454 | + ## without automake/make complaining, eg Gtk-2.0.gir -> Gtk_2_0_gir |
455 | + string(REPLACE "-" "_" _gir_name "${_gir_name}") |
456 | + string(REPLACE "." "_" _gir_name "${_gir_name}") |
457 | + |
458 | + # Namespace and Version is either fetched from the gir filename |
459 | + # or the _NAMESPACE/_VERSION variable combo |
460 | + set(_gir_namespace "${${_gir_name}_NAMESPACE}") |
461 | + if (_gir_namespace STREQUAL "") |
462 | + string(REGEX REPLACE "([^-]+)-.*" "\\1" _gir_namespace "${gir}") |
463 | + endif () |
464 | + set(_gir_version "${${_gir_name}_VERSION}") |
465 | + if (_gir_version STREQUAL "") |
466 | + string(REGEX REPLACE ".*-([^-]+).gir" "\\1" _gir_version "${gir}") |
467 | + endif () |
468 | + |
469 | + # _PROGRAM is an optional variable which needs it's own --program argument |
470 | + set(_gir_program "${${_gir_name}_PROGRAM}") |
471 | + if (NOT _gir_program STREQUAL "") |
472 | + set(_gir_program "--program=${_gir_program}") |
473 | + endif () |
474 | + |
475 | + # Variables which provides a list of things |
476 | + _gir_list_prefix(_gir_libraries ${_gir_name}_LIBS "--library=") |
477 | + _gir_list_prefix(_gir_packages ${_gir_name}_PACKAGES "--pkg=") |
478 | + _gir_list_prefix(_gir_includes ${_gir_name}_INCLUDES "--include=") |
479 | + _gir_list_prefix(_gir_export_packages ${_gir_name}_EXPORT_PACKAGES "--pkg-export=") |
480 | + |
481 | + # Reuse the LIBTOOL variable from by automake if it's set |
482 | + set(_gir_libtool "--no-libtool") |
483 | + |
484 | + add_custom_command( |
485 | + COMMAND ${INTROSPECTION_SCANNER} |
486 | + ${INTROSPECTION_SCANNER_ARGS} |
487 | + --quiet |
488 | + --warn-all |
489 | + --namespace=${_gir_namespace} |
490 | + --nsversion=${_gir_version} |
491 | + ${_gir_libtool} |
492 | + ${_gir_program} |
493 | + ${_gir_libraries} |
494 | + ${_gir_packages} |
495 | + ${_gir_includes} |
496 | + ${_gir_export_packages} |
497 | + ${${_gir_name}_SCANNERFLAGS} |
498 | + ${${_gir_name}_CFLAGS} |
499 | + ${${_gir_name}_FILES} |
500 | + --output ${CMAKE_CURRENT_BINARY_DIR}/${gir} |
501 | + DEPENDS ${${_gir_name}_FILES} |
502 | + ${${_gir_name}_LIBS} |
503 | + OUTPUT ${gir} |
504 | + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
505 | + VERBATIM |
506 | + ) |
507 | + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${gir} DESTINATION share/gir-1.0) |
508 | + |
509 | + string(REPLACE ".gir" ".typelib" _typelib "${gir}") |
510 | + add_custom_command( |
511 | + COMMAND ${INTROSPECTION_COMPILER} |
512 | + ${INTROSPECTION_COMPILER_ARGS} |
513 | + --includedir=. |
514 | + ${CMAKE_CURRENT_BINARY_DIR}/${gir} |
515 | + -o ${CMAKE_CURRENT_BINARY_DIR}/${_typelib} |
516 | + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${gir} |
517 | + OUTPUT ${_typelib} |
518 | + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} |
519 | + ) |
520 | + install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${_typelib} DESTINATION ${CMAKE_INSTALL_LIBDIR}/girepository-1.0) |
521 | + |
522 | + add_custom_target(gir-${gir} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${gir}) |
523 | + add_custom_target(gir-typelibs-${_typelib} ALL DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${_typelib}) |
524 | + endforeach() |
525 | + |
526 | +endmacro(gir_add_introspections) |
527 | + |
528 | +macro(gir_get_cflags _output) |
529 | + get_directory_property(_tmp_includes INCLUDE_DIRECTORIES) |
530 | + list_prefix(_includes _tmp_includes "-I") |
531 | + get_directory_property(_tmp_compile_definitions COMPILE_DEFINITIONS) |
532 | + list_prefix(_compile_definitions _tmp_compile_definitions "-D") |
533 | + set(${_output} ${_includes} ${_compile_definitions}) |
534 | +endmacro(gir_get_cflags) |
535 | |
536 | === modified file 'data/com.canonical.UpstartAppLaunch.xml' |
537 | --- data/com.canonical.UpstartAppLaunch.xml 2013-12-06 10:48:02 +0000 |
538 | +++ data/com.canonical.UpstartAppLaunch.xml 2014-02-11 03:28:22 +0000 |
539 | @@ -16,5 +16,9 @@ |
540 | <signal name="UnityStartingSignal"> |
541 | <arg type="s" name="appid" /> |
542 | </signal> |
543 | + <signal name="ApplicationFailed"> |
544 | + <arg type="s" name="appid" /> |
545 | + <arg type="s" name="stage" /> |
546 | + </signal> |
547 | </interface> |
548 | </node> |
549 | |
550 | === modified file 'debian/changelog' |
551 | --- debian/changelog 2014-02-06 16:54:55 +0000 |
552 | +++ debian/changelog 2014-02-11 03:28:22 +0000 |
553 | @@ -1,3 +1,9 @@ |
554 | +upstart-app-launch (0.3+14.04.20140210-0ubuntu1) trusty; urgency=low |
555 | + |
556 | + * |
557 | + |
558 | + -- Ubuntu daily release <ps-jenkins@lists.canonical.com> Mon, 10 Feb 2014 10:25:19 +0000 |
559 | + |
560 | upstart-app-launch (0.3+14.04.20140206-0ubuntu1) trusty; urgency=low |
561 | |
562 | [ Ted Gould ] |
563 | |
564 | === modified file 'debian/control' |
565 | --- debian/control 2014-01-13 15:16:24 +0000 |
566 | +++ debian/control 2014-02-11 03:28:22 +0000 |
567 | @@ -9,6 +9,7 @@ |
568 | debhelper (>= 9), |
569 | libdbus-1-dev, |
570 | libdbustest1-dev (>= 14.04.0), |
571 | + libgirepository1.0-dev, |
572 | libglib2.0-dev, |
573 | libgtest-dev, |
574 | libjson-glib-dev, |
575 | @@ -17,6 +18,7 @@ |
576 | libnih-dev, |
577 | libupstart-dev, |
578 | libzeitgeist-2.0-dev, |
579 | + gobject-introspection, |
580 | python3-dbusmock, |
581 | upstart (>= 1.11), |
582 | Standards-Version: 3.9.4 |
583 | @@ -80,3 +82,18 @@ |
584 | . |
585 | This package contains files that are needed to build applications. |
586 | |
587 | +Package: gir1.2-upstart-app-launch-2 |
588 | +Section: libs |
589 | +Architecture: any |
590 | +Depends: ${shlibs:Depends}, |
591 | + ${misc:Depends}, |
592 | + libupstart-app-launch2 (= ${binary:Version}), |
593 | + ${gir:Depends}, |
594 | +Pre-Depends: ${misc:Pre-Depends} |
595 | +Recommends: upstart-app-launch (= ${binary:Version}) |
596 | +Description: typelib file for libupstart-app-launch2 |
597 | + Interface for starting apps and getting info on them. |
598 | + . |
599 | + This package can be used by other packages using the GIRepository format to |
600 | + generate dynamic bindings for libupstart-app-launch2. |
601 | + |
602 | |
603 | === added file 'debian/gir1.2-upstart-app-launch-2.install' |
604 | --- debian/gir1.2-upstart-app-launch-2.install 1970-01-01 00:00:00 +0000 |
605 | +++ debian/gir1.2-upstart-app-launch-2.install 2014-02-11 03:28:22 +0000 |
606 | @@ -0,0 +1,1 @@ |
607 | +usr/lib/*/girepository-1.0 /usr/lib |
608 | |
609 | === modified file 'debian/libupstart-app-launch2-dev.install' |
610 | --- debian/libupstart-app-launch2-dev.install 2013-12-05 17:19:45 +0000 |
611 | +++ debian/libupstart-app-launch2-dev.install 2014-02-11 03:28:22 +0000 |
612 | @@ -1,3 +1,4 @@ |
613 | usr/lib/*/libupstart-app-launch.so |
614 | usr/lib/*/pkgconfig/* |
615 | usr/include/* |
616 | +usr/share/gir-1.0/* |
617 | |
618 | === modified file 'debian/rules' |
619 | --- debian/rules 2013-07-24 16:57:23 +0000 |
620 | +++ debian/rules 2014-02-11 03:28:22 +0000 |
621 | @@ -5,7 +5,7 @@ |
622 | #export DH_VERBOSE=1 |
623 | |
624 | %: |
625 | - dh $@ --with click |
626 | + dh $@ --with click,gir |
627 | |
628 | override_dh_click: |
629 | dh_click --name upstart-app-launch-desktop |
630 | |
631 | === removed file 'desktop-single-trace.tp' |
632 | --- desktop-single-trace.tp 2013-12-04 17:10:57 +0000 |
633 | +++ desktop-single-trace.tp 1970-01-01 00:00:00 +0000 |
634 | @@ -1,5 +0,0 @@ |
635 | - |
636 | -TRACEPOINT_EVENT(upstart_app_launch, desktop_single_start, TP_ARGS(0), TP_FIELDS()) |
637 | -TRACEPOINT_EVENT(upstart_app_launch, desktop_single_found, TP_ARGS(0), TP_FIELDS()) |
638 | -TRACEPOINT_EVENT(upstart_app_launch, desktop_single_finished, TP_ARGS(0), TP_FIELDS()) |
639 | - |
640 | |
641 | === removed file 'desktop-single.c' |
642 | --- desktop-single.c 2013-12-05 17:08:13 +0000 |
643 | +++ desktop-single.c 1970-01-01 00:00:00 +0000 |
644 | @@ -1,68 +0,0 @@ |
645 | -/* |
646 | - * Copyright 2013 Canonical Ltd. |
647 | - * |
648 | - * This program is free software: you can redistribute it and/or modify it |
649 | - * under the terms of the GNU General Public License version 3, as published |
650 | - * by the Free Software Foundation. |
651 | - * |
652 | - * This program is distributed in the hope that it will be useful, but |
653 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
654 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
655 | - * PURPOSE. See the GNU General Public License for more details. |
656 | - * |
657 | - * You should have received a copy of the GNU General Public License along |
658 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
659 | - * |
660 | - * Authors: |
661 | - * Ted Gould <ted.gould@canonical.com> |
662 | - */ |
663 | - |
664 | -#include "helpers.h" |
665 | -#include "desktop-single-trace.h" |
666 | - |
667 | -int |
668 | -main (int argc, char * argv[]) |
669 | -{ |
670 | - /* Nothing is single instance yet */ |
671 | - if (argc != 2) { |
672 | - g_error("Should be called as: %s <app_id>", argv[0]); |
673 | - return 1; |
674 | - } |
675 | - |
676 | - g_setenv("LTTNG_UST_REGISTER_TIMEOUT", "0", FALSE); /* Set to zero if not set */ |
677 | - tracepoint(upstart_app_launch, desktop_single_start); |
678 | - |
679 | - GKeyFile * keyfile = keyfile_for_appid(argv[1], NULL); |
680 | - |
681 | - if (keyfile == NULL) { |
682 | - g_error("Unable to find keyfile for application '%s'", argv[0]); |
683 | - return 1; |
684 | - } |
685 | - |
686 | - tracepoint(upstart_app_launch, desktop_single_found); |
687 | - |
688 | - gboolean singleinstance = FALSE; |
689 | - |
690 | - if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", NULL)) { |
691 | - GError * error = NULL; |
692 | - |
693 | - singleinstance = g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", &error); |
694 | - |
695 | - if (error != NULL) { |
696 | - g_warning("Unable to get single instance key for app '%s': %s", argv[1], error->message); |
697 | - g_error_free(error); |
698 | - /* Ensure that if we got an error, we assume standard case */ |
699 | - singleinstance = FALSE; |
700 | - } |
701 | - } |
702 | - |
703 | - g_key_file_free(keyfile); |
704 | - |
705 | - tracepoint(upstart_app_launch, desktop_single_finished); |
706 | - |
707 | - if (singleinstance) { |
708 | - return 0; |
709 | - } else { |
710 | - return 1; |
711 | - } |
712 | -} |
713 | |
714 | === added file 'helpers-keyfile.c' |
715 | --- helpers-keyfile.c 1970-01-01 00:00:00 +0000 |
716 | +++ helpers-keyfile.c 2014-02-11 03:28:22 +0000 |
717 | @@ -0,0 +1,95 @@ |
718 | +/* |
719 | + * Copyright 2013 Canonical Ltd. |
720 | + * |
721 | + * This program is free software: you can redistribute it and/or modify it |
722 | + * under the terms of the GNU General Public License version 3, as published |
723 | + * by the Free Software Foundation. |
724 | + * |
725 | + * This program is distributed in the hope that it will be useful, but |
726 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
727 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
728 | + * PURPOSE. See the GNU General Public License for more details. |
729 | + * |
730 | + * You should have received a copy of the GNU General Public License along |
731 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
732 | + * |
733 | + * Authors: |
734 | + * Ted Gould <ted.gould@canonical.com> |
735 | + */ |
736 | + |
737 | +#include "helpers.h" |
738 | + |
739 | +/* Check to make sure we have the sections and keys we want */ |
740 | +static gboolean |
741 | +verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop) |
742 | +{ |
743 | + if (inkeyfile == NULL) return FALSE; |
744 | + |
745 | + if (!g_key_file_has_group(inkeyfile, "Desktop Entry")) { |
746 | + g_warning("Desktop file '%s' is missing the 'Desktop Entry' group", desktop); |
747 | + return FALSE; |
748 | + } |
749 | + |
750 | + if (!g_key_file_has_key(inkeyfile, "Desktop Entry", "Exec", NULL)) { |
751 | + g_warning("Desktop file '%s' is missing the 'Exec' key", desktop); |
752 | + return FALSE; |
753 | + } |
754 | + |
755 | + return TRUE; |
756 | +} |
757 | + |
758 | +/* Try to find a desktop file in a particular data directory */ |
759 | +static GKeyFile * |
760 | +try_dir (const char * dir, const gchar * desktop) |
761 | +{ |
762 | + gchar * fullpath = g_build_filename(dir, "applications", desktop, NULL); |
763 | + GKeyFile * keyfile = g_key_file_new(); |
764 | + |
765 | + /* NOTE: Leaving off the error here as we'll get a bunch of them, |
766 | + so individuals aren't really useful */ |
767 | + gboolean loaded = g_key_file_load_from_file(keyfile, fullpath, G_KEY_FILE_NONE, NULL); |
768 | + |
769 | + g_free(fullpath); |
770 | + |
771 | + if (!loaded) { |
772 | + g_key_file_free(keyfile); |
773 | + return NULL; |
774 | + } |
775 | + |
776 | + if (!verify_keyfile(keyfile, desktop)) { |
777 | + g_key_file_free(keyfile); |
778 | + return NULL; |
779 | + } |
780 | + |
781 | + return keyfile; |
782 | +} |
783 | + |
784 | +/* Find the keyfile that we need for a particular AppID and return it. |
785 | + Or NULL if we can't find it. */ |
786 | +GKeyFile * |
787 | +keyfile_for_appid (const gchar * appid, gchar ** desktopfile) |
788 | +{ |
789 | + gchar * desktop = g_strdup_printf("%s.desktop", appid); |
790 | + |
791 | + const char * const * data_dirs = g_get_system_data_dirs(); |
792 | + GKeyFile * keyfile = NULL; |
793 | + int i; |
794 | + |
795 | + keyfile = try_dir(g_get_user_data_dir(), desktop); |
796 | + if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
797 | + *desktopfile = g_build_filename(g_get_user_data_dir(), "applications", desktop, NULL); |
798 | + } |
799 | + |
800 | + for (i = 0; data_dirs[i] != NULL && keyfile == NULL; i++) { |
801 | + keyfile = try_dir(data_dirs[i], desktop); |
802 | + |
803 | + if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
804 | + *desktopfile = g_build_filename(data_dirs[i], "applications", desktop, NULL); |
805 | + } |
806 | + } |
807 | + |
808 | + g_free(desktop); |
809 | + |
810 | + return keyfile; |
811 | +} |
812 | + |
813 | |
814 | === modified file 'helpers.c' |
815 | --- helpers.c 2014-02-03 18:29:54 +0000 |
816 | +++ helpers.c 2014-02-11 03:28:22 +0000 |
817 | @@ -492,80 +492,6 @@ |
818 | return newargv; |
819 | } |
820 | |
821 | -/* Check to make sure we have the sections and keys we want */ |
822 | -static gboolean |
823 | -verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop) |
824 | -{ |
825 | - if (inkeyfile == NULL) return FALSE; |
826 | - |
827 | - if (!g_key_file_has_group(inkeyfile, "Desktop Entry")) { |
828 | - g_warning("Desktop file '%s' is missing the 'Desktop Entry' group", desktop); |
829 | - return FALSE; |
830 | - } |
831 | - |
832 | - if (!g_key_file_has_key(inkeyfile, "Desktop Entry", "Exec", NULL)) { |
833 | - g_warning("Desktop file '%s' is missing the 'Exec' key", desktop); |
834 | - return FALSE; |
835 | - } |
836 | - |
837 | - return TRUE; |
838 | -} |
839 | - |
840 | -/* Try to find a desktop file in a particular data directory */ |
841 | -static GKeyFile * |
842 | -try_dir (const char * dir, const gchar * desktop) |
843 | -{ |
844 | - gchar * fullpath = g_build_filename(dir, "applications", desktop, NULL); |
845 | - GKeyFile * keyfile = g_key_file_new(); |
846 | - |
847 | - /* NOTE: Leaving off the error here as we'll get a bunch of them, |
848 | - so individuals aren't really useful */ |
849 | - gboolean loaded = g_key_file_load_from_file(keyfile, fullpath, G_KEY_FILE_NONE, NULL); |
850 | - |
851 | - g_free(fullpath); |
852 | - |
853 | - if (!loaded) { |
854 | - g_key_file_free(keyfile); |
855 | - return NULL; |
856 | - } |
857 | - |
858 | - if (!verify_keyfile(keyfile, desktop)) { |
859 | - g_key_file_free(keyfile); |
860 | - return NULL; |
861 | - } |
862 | - |
863 | - return keyfile; |
864 | -} |
865 | - |
866 | -/* Find the keyfile that we need for a particular AppID and return it. |
867 | - Or NULL if we can't find it. */ |
868 | -GKeyFile * |
869 | -keyfile_for_appid (const gchar * appid, gchar ** desktopfile) |
870 | -{ |
871 | - gchar * desktop = g_strdup_printf("%s.desktop", appid); |
872 | - |
873 | - const char * const * data_dirs = g_get_system_data_dirs(); |
874 | - GKeyFile * keyfile = NULL; |
875 | - int i; |
876 | - |
877 | - keyfile = try_dir(g_get_user_data_dir(), desktop); |
878 | - if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
879 | - *desktopfile = g_build_filename(g_get_user_data_dir(), "applications", desktop, NULL); |
880 | - } |
881 | - |
882 | - for (i = 0; data_dirs[i] != NULL && keyfile == NULL; i++) { |
883 | - keyfile = try_dir(data_dirs[i], desktop); |
884 | - |
885 | - if (keyfile != NULL && desktopfile != NULL && *desktopfile == NULL) { |
886 | - *desktopfile = g_build_filename(data_dirs[i], "applications", desktop, NULL); |
887 | - } |
888 | - } |
889 | - |
890 | - g_free(desktop); |
891 | - |
892 | - return keyfile; |
893 | -} |
894 | - |
895 | /* Set environment various variables to make apps work under |
896 | * confinement according to: |
897 | * https://wiki.ubuntu.com/SecurityTeam/Specifications/ApplicationConfinement |
898 | |
899 | === modified file 'libupstart-app-launch/CMakeLists.txt' |
900 | --- libupstart-app-launch/CMakeLists.txt 2014-01-13 15:16:24 +0000 |
901 | +++ libupstart-app-launch/CMakeLists.txt 2014-02-11 03:28:22 +0000 |
902 | @@ -1,4 +1,7 @@ |
903 | |
904 | +include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
905 | +include_directories(${CMAKE_CURRENT_BINARY_DIR}) |
906 | + |
907 | ########################## |
908 | # Version Info |
909 | ########################## |
910 | @@ -11,6 +14,8 @@ |
911 | # Library |
912 | ########################## |
913 | |
914 | +add_lttng_gen_tp(NAME upstart-app-launch-trace) |
915 | + |
916 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") |
917 | |
918 | set(LAUNCHER_HEADERS |
919 | @@ -19,6 +24,9 @@ |
920 | |
921 | set(LAUNCHER_SOURCES |
922 | upstart-app-launch.c |
923 | +second-exec-core.c |
924 | +upstart-app-launch-trace.c |
925 | +"${CMAKE_SOURCE_DIR}/helpers-keyfile.c" |
926 | ) |
927 | |
928 | add_library(upstart-launcher SHARED ${LAUNCHER_SOURCES}) |
929 | @@ -34,6 +42,7 @@ |
930 | ${GOBJECT2_LIBRARIES} |
931 | ${LIBUPSTART_LIBRARIES} |
932 | ${GIO2_LIBRARIES} |
933 | + ${LTTNG_LIBRARIES} |
934 | ${JSONGLIB_LIBRARIES} |
935 | -Wl,--no-undefined |
936 | ) |
937 | @@ -63,3 +72,26 @@ |
938 | DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" |
939 | ) |
940 | |
941 | +########################## |
942 | +# Introspection |
943 | +########################## |
944 | + |
945 | +include(UseGObjectIntrospection) |
946 | + |
947 | +set(INTROSPECTION_GIRS) |
948 | +set(_introspection_files ${LAUNCHER_HEADERS}) |
949 | +set(UpstartAppLaunch_2_gir "upstart-app-launch") |
950 | +set(UpstartAppLaunch_2_gir_INCLUDES GObject-2.0) |
951 | + |
952 | +gir_get_cflags(_cflags) |
953 | +set(UpstartAppLaunch_2_gir_CFLAGS ${c_flags}) |
954 | +set(UpstartAppLaunch_2_gir_LIBS upstart-app-launch) |
955 | + |
956 | +list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/") |
957 | +set(UpstartAppLaunch_2_gir_FILES ${_abs_introspection_files}) |
958 | +set(UpstartAppLaunch_2_gir_SCANNERFLAGS --c-include "upstart-app-launch.h") |
959 | +set(UpstartAppLaunch_2_gir_EXPORT_PACKAGES "upstart-app-launch-${API_VERSION}") |
960 | + |
961 | +list(APPEND INTROSPECTION_GIRS UpstartAppLaunch-2.gir) |
962 | +gir_add_introspections(INTROSPECTION_GIRS) |
963 | + |
964 | |
965 | === renamed file 'second-exec-core.c' => 'libupstart-app-launch/second-exec-core.c' |
966 | --- second-exec-core.c 2013-12-06 10:38:35 +0000 |
967 | +++ libupstart-app-launch/second-exec-core.c 2014-02-11 03:28:22 +0000 |
968 | @@ -23,46 +23,49 @@ |
969 | #include "libupstart-app-launch/upstart-app-launch.h" |
970 | #include "helpers.h" |
971 | #include "second-exec-core.h" |
972 | -#include "second-exec-trace.h" |
973 | - |
974 | -/* Globals */ |
975 | -GPid app_pid = 0; |
976 | -GMainLoop * mainloop = NULL; |
977 | -guint connections_open = 0; |
978 | -const gchar * appid = NULL; |
979 | -const gchar * input_uris = NULL; |
980 | -GVariant * app_data = NULL; |
981 | -gchar * dbus_path = NULL; |
982 | -guint64 unity_starttime = 0; |
983 | -guint timer = 0; |
984 | +#include "upstart-app-launch-trace.h" |
985 | + |
986 | +typedef struct { |
987 | + GDBusConnection * bus; |
988 | + gchar * appid; |
989 | + gchar * input_uris; |
990 | + GPid app_pid; |
991 | + guint connections_open; |
992 | + GVariant * app_data; |
993 | + gchar * dbus_path; |
994 | + guint64 unity_starttime; |
995 | + guint timer; |
996 | +} second_exec_t; |
997 | + |
998 | +static void second_exec_complete (second_exec_t * data); |
999 | |
1000 | /* Unity didn't respond in time, continue on */ |
1001 | static gboolean |
1002 | timer_cb (gpointer user_data) |
1003 | { |
1004 | - tracepoint(upstart_app_launch, second_exec_resume_timeout); |
1005 | + tracepoint(upstart_app_launch, second_exec_resume_timeout, ((second_exec_t *)user_data)->appid); |
1006 | g_warning("Unity didn't respond in 500ms to resume the app"); |
1007 | - g_main_loop_quit(mainloop); |
1008 | + second_exec_complete(user_data); |
1009 | return G_SOURCE_REMOVE; |
1010 | } |
1011 | |
1012 | /* Lower the connection count and process if it gets to zero */ |
1013 | static void |
1014 | -connection_count_dec (void) |
1015 | +connection_count_dec (second_exec_t * data) |
1016 | { |
1017 | - tracepoint(upstart_app_launch, second_exec_connection_complete); |
1018 | - connections_open--; |
1019 | - if (connections_open == 0) { |
1020 | + tracepoint(upstart_app_launch, second_exec_connection_complete, data->appid); |
1021 | + data->connections_open--; |
1022 | + if (data->connections_open == 0) { |
1023 | g_debug("Finished finding connections"); |
1024 | /* Check time here, either we've already heard from |
1025 | Unity and we should send the data to the app (quit) or |
1026 | we should wait some more */ |
1027 | - guint64 timespent = g_get_monotonic_time() - unity_starttime; |
1028 | + guint64 timespent = g_get_monotonic_time() - data->unity_starttime; |
1029 | if (timespent > 500 /* ms */ * 1000 /* ms to us */) { |
1030 | - g_main_loop_quit(mainloop); |
1031 | + second_exec_complete(data); |
1032 | } else { |
1033 | g_debug("Timer Set"); |
1034 | - timer = g_timeout_add(500 - (timespent / 1000), timer_cb, NULL); |
1035 | + data->timer = g_timeout_add(500 - (timespent / 1000), timer_cb, data); |
1036 | } |
1037 | } |
1038 | return; |
1039 | @@ -73,18 +76,20 @@ |
1040 | static void |
1041 | unity_resume_cb (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
1042 | { |
1043 | + second_exec_t * data = (second_exec_t *)user_data; |
1044 | g_debug("Unity Completed Resume"); |
1045 | - tracepoint(upstart_app_launch, second_exec_resume_complete); |
1046 | + tracepoint(upstart_app_launch, second_exec_resume_complete, data->appid); |
1047 | |
1048 | - if (timer != 0) { |
1049 | - g_source_remove(timer); |
1050 | + if (data->timer != 0) { |
1051 | + g_source_remove(data->timer); |
1052 | + data->timer = 0; |
1053 | } |
1054 | |
1055 | - if (connections_open == 0) { |
1056 | - g_main_loop_quit(mainloop); |
1057 | + if (data->connections_open == 0) { |
1058 | + second_exec_complete(data); |
1059 | } else { |
1060 | /* Make it look like we started *forever* ago */ |
1061 | - unity_starttime = 0; |
1062 | + data->unity_starttime = 0; |
1063 | } |
1064 | |
1065 | return; |
1066 | @@ -92,9 +97,9 @@ |
1067 | |
1068 | /* Turn the input string into something we can send to apps */ |
1069 | static void |
1070 | -parse_uris (void) |
1071 | +parse_uris (second_exec_t * data) |
1072 | { |
1073 | - if (app_data != NULL) { |
1074 | + if (data->app_data != NULL) { |
1075 | /* Already done */ |
1076 | return; |
1077 | } |
1078 | @@ -103,11 +108,11 @@ |
1079 | gchar ** uri_split = NULL; |
1080 | GError * error = NULL; |
1081 | |
1082 | - g_shell_parse_argv(input_uris, NULL, &uri_split, &error); |
1083 | + g_shell_parse_argv(data->input_uris, NULL, &uri_split, &error); |
1084 | |
1085 | if (uri_split == NULL || uri_split[0] == NULL || error != NULL) { |
1086 | if (error != NULL) { |
1087 | - g_warning("Unable to parse URLs '%s': %s", input_uris, error->message); |
1088 | + g_warning("Unable to parse URLs '%s': %s", data->input_uris, error->message); |
1089 | g_error_free(error); |
1090 | } |
1091 | |
1092 | @@ -136,8 +141,8 @@ |
1093 | g_variant_builder_add_value(&tuple, uris); |
1094 | g_variant_builder_add_value(&tuple, platform); |
1095 | |
1096 | - app_data = g_variant_builder_end(&tuple); |
1097 | - g_variant_ref_sink(app_data); |
1098 | + data->app_data = g_variant_builder_end(&tuple); |
1099 | + g_variant_ref_sink(data->app_data); |
1100 | |
1101 | return; |
1102 | } |
1103 | @@ -149,14 +154,29 @@ |
1104 | http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#dbus |
1105 | */ |
1106 | static void |
1107 | -app_id_to_dbus_path (void) |
1108 | +app_id_to_dbus_path (second_exec_t * data) |
1109 | { |
1110 | - if (dbus_path != NULL) { |
1111 | + if (data->dbus_path != NULL) { |
1112 | return; |
1113 | } |
1114 | |
1115 | - dbus_path = nih_dbus_path(NULL, "", appid, NULL); |
1116 | - g_debug("DBus Path: %s", dbus_path); |
1117 | + GString * str = g_string_sized_new(strlen(data->appid) + 2); /* base case, we just need a / and a null */ |
1118 | + g_string_append_c(str, '/'); |
1119 | + |
1120 | + int i; |
1121 | + for (i = 0; data->appid[i] != '\0'; i++) { |
1122 | + if ((data->appid[i] >= 'a' && data->appid[i] <= 'z') || |
1123 | + (data->appid[i] >= 'A' && data->appid[i] <= 'Z') || |
1124 | + (data->appid[i] >= '0' && data->appid[i] <= '9' && i != 0)) { |
1125 | + g_string_append_c(str, data->appid[i]); |
1126 | + continue; |
1127 | + } |
1128 | + |
1129 | + g_string_append_printf(str, "_%2x", data->appid[i]); |
1130 | + } |
1131 | + |
1132 | + data->dbus_path = g_string_free(str, FALSE); |
1133 | + g_debug("DBus Path: %s", data->dbus_path); |
1134 | |
1135 | return; |
1136 | } |
1137 | @@ -167,68 +187,76 @@ |
1138 | { |
1139 | GError * error = NULL; |
1140 | |
1141 | - tracepoint(upstart_app_launch, second_exec_app_contacted); |
1142 | + tracepoint(upstart_app_launch, second_exec_app_contacted, ((second_exec_t *)user_data)->appid); |
1143 | |
1144 | g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); |
1145 | |
1146 | if (error != NULL) { |
1147 | - tracepoint(upstart_app_launch, second_exec_app_error); |
1148 | + tracepoint(upstart_app_launch, second_exec_app_error, ((second_exec_t *)user_data)->appid); |
1149 | /* Mostly just to free the error, but printing for debugging */ |
1150 | g_debug("Unable to send Open: %s", error->message); |
1151 | g_error_free(error); |
1152 | } |
1153 | |
1154 | - connection_count_dec(); |
1155 | + connection_count_dec(user_data); |
1156 | return; |
1157 | } |
1158 | |
1159 | /* Sends the Open message to the connection with the URIs we were given */ |
1160 | static void |
1161 | -contact_app (GDBusConnection * bus, const gchar * dbus_name) |
1162 | +contact_app (GDBusConnection * bus, const gchar * dbus_name, second_exec_t * data) |
1163 | { |
1164 | - tracepoint(upstart_app_launch, second_exec_contact_app); |
1165 | + tracepoint(upstart_app_launch, second_exec_contact_app, data->appid, dbus_name); |
1166 | |
1167 | - parse_uris(); |
1168 | - app_id_to_dbus_path(); |
1169 | + parse_uris(data); |
1170 | + app_id_to_dbus_path(data); |
1171 | |
1172 | /* Using the FD.o Application interface */ |
1173 | g_dbus_connection_call(bus, |
1174 | dbus_name, |
1175 | - dbus_path, |
1176 | + data->dbus_path, |
1177 | "org.freedesktop.Application", |
1178 | "Open", |
1179 | - app_data, |
1180 | + data->app_data, |
1181 | NULL, |
1182 | G_DBUS_CALL_FLAGS_NONE, |
1183 | -1, |
1184 | NULL, |
1185 | - send_open_cb, NULL); |
1186 | + send_open_cb, data); |
1187 | |
1188 | g_debug("Sending Open request to: %s", dbus_name); |
1189 | |
1190 | return; |
1191 | } |
1192 | |
1193 | +typedef struct { |
1194 | + gchar * name; |
1195 | + second_exec_t * data; |
1196 | +} get_pid_t; |
1197 | + |
1198 | /* Gets the PID for a connection, and if it matches the one we're looking |
1199 | for then it tries to send a message to that connection */ |
1200 | static void |
1201 | get_pid_cb (GObject * object, GAsyncResult * res, gpointer user_data) |
1202 | { |
1203 | - gchar * dbus_name = (gchar *)user_data; |
1204 | + get_pid_t * data = (get_pid_t *)user_data; |
1205 | GError * error = NULL; |
1206 | GVariant * vpid = NULL; |
1207 | |
1208 | - tracepoint(upstart_app_launch, second_exec_got_pid); |
1209 | + tracepoint(upstart_app_launch, second_exec_got_pid, data->data->appid, data->name); |
1210 | |
1211 | vpid = g_dbus_connection_call_finish(G_DBUS_CONNECTION(object), res, &error); |
1212 | |
1213 | if (error != NULL) { |
1214 | - g_warning("Unable to query PID for dbus name '%s': %s", dbus_name, error->message); |
1215 | + g_warning("Unable to query PID for dbus name '%s': %s", data->name, error->message); |
1216 | g_error_free(error); |
1217 | - g_free(dbus_name); |
1218 | |
1219 | /* Lowering the connection count, this one is terminal, even if in error */ |
1220 | - connection_count_dec(); |
1221 | + connection_count_dec(data->data); |
1222 | + |
1223 | + g_free(data->name); |
1224 | + g_free(data); |
1225 | + |
1226 | return; |
1227 | } |
1228 | |
1229 | @@ -236,22 +264,23 @@ |
1230 | g_variant_get(vpid, "(u)", &pid); |
1231 | g_variant_unref(vpid); |
1232 | |
1233 | - if (pid == app_pid) { |
1234 | + if (pid == data->data->app_pid) { |
1235 | /* Trying to send a message to the connection */ |
1236 | - contact_app(G_DBUS_CONNECTION(object), dbus_name); |
1237 | + contact_app(G_DBUS_CONNECTION(object), data->name, data->data); |
1238 | } else { |
1239 | /* See if we can quit now */ |
1240 | - connection_count_dec(); |
1241 | + connection_count_dec(data->data); |
1242 | } |
1243 | |
1244 | - g_free(dbus_name); |
1245 | + g_free(data->name); |
1246 | + g_free(data); |
1247 | |
1248 | return; |
1249 | } |
1250 | |
1251 | /* Starts to look for the PID and the connections for that PID */ |
1252 | void |
1253 | -find_appid_pid (GDBusConnection * session) |
1254 | +find_appid_pid (GDBusConnection * session, second_exec_t * data) |
1255 | { |
1256 | GError * error = NULL; |
1257 | |
1258 | @@ -276,19 +305,21 @@ |
1259 | return; |
1260 | } |
1261 | |
1262 | - tracepoint(upstart_app_launch, second_exec_got_dbus_names); |
1263 | + g_debug("Got bus names"); |
1264 | + tracepoint(upstart_app_launch, second_exec_got_dbus_names, data->appid); |
1265 | |
1266 | /* Next figure out what we're looking for (and if there is something to look for) */ |
1267 | /* NOTE: We're getting the PID *after* the list of connections so |
1268 | that some new process can't come in, be the same PID as it's |
1269 | connection will not be in teh list we just got. */ |
1270 | - app_pid = upstart_app_launch_get_primary_pid(appid); |
1271 | - if (app_pid == 0) { |
1272 | - g_warning("Unable to find pid for app id '%s'", appid); |
1273 | + data->app_pid = upstart_app_launch_get_primary_pid(data->appid); |
1274 | + if (data->app_pid == 0) { |
1275 | + g_warning("Unable to find pid for app id '%s'", data->appid); |
1276 | return; |
1277 | } |
1278 | |
1279 | - tracepoint(upstart_app_launch, second_exec_got_primary_pid); |
1280 | + g_debug("Primary PID: %d", data->app_pid); |
1281 | + tracepoint(upstart_app_launch, second_exec_got_primary_pid, data->appid); |
1282 | |
1283 | /* Get the names */ |
1284 | GVariant * names = g_variant_get_child_value(listnames, 0); |
1285 | @@ -301,8 +332,12 @@ |
1286 | if (!g_dbus_is_unique_name(name)) { |
1287 | continue; |
1288 | } |
1289 | + |
1290 | + get_pid_t * pid_data = g_new0(get_pid_t, 1); |
1291 | + pid_data->data = data; |
1292 | + pid_data->name = g_strdup(name); |
1293 | |
1294 | - tracepoint(upstart_app_launch, second_exec_request_pid); |
1295 | + tracepoint(upstart_app_launch, second_exec_request_pid, data->appid, pid_data->name); |
1296 | |
1297 | /* Get the PIDs */ |
1298 | g_dbus_connection_call(session, |
1299 | @@ -315,9 +350,9 @@ |
1300 | G_DBUS_CALL_FLAGS_NONE, |
1301 | -1, |
1302 | NULL, |
1303 | - get_pid_cb, g_strdup(name)); |
1304 | + get_pid_cb, pid_data); |
1305 | |
1306 | - connections_open++; |
1307 | + data->connections_open++; |
1308 | } |
1309 | |
1310 | g_variant_unref(names); |
1311 | @@ -329,10 +364,7 @@ |
1312 | gboolean |
1313 | second_exec (const gchar * app_id, const gchar * appuris) |
1314 | { |
1315 | - appid = app_id; |
1316 | - input_uris = appuris; |
1317 | - |
1318 | - tracepoint(upstart_app_launch, second_exec_start); |
1319 | + tracepoint(upstart_app_launch, second_exec_start, app_id, appuris); |
1320 | |
1321 | /* DBus tell us! */ |
1322 | GError * error = NULL; |
1323 | @@ -343,8 +375,11 @@ |
1324 | return FALSE; |
1325 | } |
1326 | |
1327 | - /* Allocate main loop */ |
1328 | - mainloop = g_main_loop_new(NULL, FALSE); |
1329 | + /* Setup our continuation data */ |
1330 | + second_exec_t * data = g_new0(second_exec_t, 1); |
1331 | + data->appid = g_strdup(app_id); |
1332 | + data->input_uris = g_strdup(appuris); |
1333 | + data->bus = session; |
1334 | |
1335 | /* Set up listening for the unfrozen signal from Unity */ |
1336 | g_dbus_connection_signal_subscribe(session, |
1337 | @@ -352,12 +387,13 @@ |
1338 | "com.canonical.UpstartAppLaunch", /* interface */ |
1339 | "UnityResumeResponse", /* signal */ |
1340 | "/", /* path */ |
1341 | - appid, /* arg0 */ |
1342 | + app_id, /* arg0 */ |
1343 | G_DBUS_SIGNAL_FLAGS_NONE, |
1344 | - unity_resume_cb, mainloop, |
1345 | + unity_resume_cb, data, |
1346 | NULL); /* user data destroy */ |
1347 | |
1348 | - tracepoint(upstart_app_launch, second_exec_emit_resume); |
1349 | + g_debug("Sending resume request"); |
1350 | + tracepoint(upstart_app_launch, second_exec_emit_resume, app_id); |
1351 | |
1352 | /* Send unfreeze to to Unity */ |
1353 | g_dbus_connection_emit_signal(session, |
1354 | @@ -365,43 +401,49 @@ |
1355 | "/", /* path */ |
1356 | "com.canonical.UpstartAppLaunch", /* interface */ |
1357 | "UnityResumeRequest", /* signal */ |
1358 | - g_variant_new("(s)", appid), |
1359 | + g_variant_new("(s)", app_id), |
1360 | &error); |
1361 | |
1362 | /* Now we start a race, we try to get to the point of knowing who |
1363 | to send things to, and Unity is unfrezing it. When both are |
1364 | done we can send something to the app */ |
1365 | - unity_starttime = g_get_monotonic_time(); |
1366 | + data->unity_starttime = g_get_monotonic_time(); |
1367 | |
1368 | if (error != NULL) { |
1369 | /* On error let's not wait for Unity */ |
1370 | g_warning("Unable to signal Unity: %s", error->message); |
1371 | g_error_free(error); |
1372 | error = NULL; |
1373 | - unity_starttime = 0; |
1374 | + data->unity_starttime = 0; |
1375 | } |
1376 | |
1377 | /* If we've got something to give out, start looking for how */ |
1378 | - if (input_uris != NULL) { |
1379 | - find_appid_pid(session); |
1380 | + if (data->input_uris != NULL) { |
1381 | + find_appid_pid(session, data); |
1382 | } |
1383 | |
1384 | /* Loop and wait for everything to align */ |
1385 | - if (connections_open > 0 || unity_starttime > 0) { |
1386 | - g_main_loop_run(mainloop); |
1387 | + if (data->connections_open == 0 && data->unity_starttime == 0) { |
1388 | + second_exec_complete(data); |
1389 | } |
1390 | - g_debug("Finishing main loop"); |
1391 | - |
1392 | - tracepoint(upstart_app_launch, second_exec_emit_focus); |
1393 | + |
1394 | + return TRUE; |
1395 | +} |
1396 | + |
1397 | +static void |
1398 | +second_exec_complete (second_exec_t * data) |
1399 | +{ |
1400 | + GError * error = NULL; |
1401 | + tracepoint(upstart_app_launch, second_exec_emit_focus, data->appid); |
1402 | |
1403 | /* Now that we're done sending the info to the app, we can ask |
1404 | Unity to focus the application. */ |
1405 | - g_dbus_connection_emit_signal(session, |
1406 | + g_dbus_connection_emit_signal(data->bus, |
1407 | NULL, /* destination */ |
1408 | "/", /* path */ |
1409 | "com.canonical.UpstartAppLaunch", /* interface */ |
1410 | "UnityFocusRequest", /* signal */ |
1411 | - g_variant_new("(s)", appid), |
1412 | + g_variant_new("(s)", data->appid), |
1413 | &error); |
1414 | |
1415 | if (error != NULL) { |
1416 | @@ -411,23 +453,23 @@ |
1417 | } |
1418 | |
1419 | /* Make sure the signal hits the bus */ |
1420 | - g_dbus_connection_flush_sync(session, NULL, NULL); |
1421 | + g_dbus_connection_flush_sync(data->bus, NULL, &error); |
1422 | + if (error != NULL) { |
1423 | + g_warning("Unable to flush session bus: %s", error->message); |
1424 | + g_error_free(error); |
1425 | + error = NULL; |
1426 | + } |
1427 | + |
1428 | + tracepoint(upstart_app_launch, second_exec_finish, data->appid); |
1429 | |
1430 | /* Clean up */ |
1431 | - if (app_data != NULL) { |
1432 | - g_variant_unref(app_data); |
1433 | - app_data = NULL; |
1434 | - } |
1435 | - |
1436 | - g_main_loop_unref(mainloop); |
1437 | - g_object_unref(session); |
1438 | - |
1439 | - if (dbus_path != NULL) { |
1440 | - nih_free(dbus_path); |
1441 | - dbus_path = NULL; |
1442 | - } |
1443 | - |
1444 | - tracepoint(upstart_app_launch, second_exec_finish); |
1445 | - |
1446 | - return TRUE; |
1447 | + g_object_unref(data->bus); |
1448 | + if (data->app_data != NULL) |
1449 | + g_variant_unref(data->app_data); |
1450 | + g_free(data->appid); |
1451 | + g_free(data->input_uris); |
1452 | + g_free(data->dbus_path); |
1453 | + g_free(data); |
1454 | + |
1455 | + return; |
1456 | } |
1457 | |
1458 | === renamed file 'second-exec-core.h' => 'libupstart-app-launch/second-exec-core.h' |
1459 | === added file 'libupstart-app-launch/upstart-app-launch-trace.tp' |
1460 | --- libupstart-app-launch/upstart-app-launch-trace.tp 1970-01-01 00:00:00 +0000 |
1461 | +++ libupstart-app-launch/upstart-app-launch-trace.tp 2014-02-11 03:28:22 +0000 |
1462 | @@ -0,0 +1,170 @@ |
1463 | + |
1464 | +/******************************* |
1465 | + LibUAL start function |
1466 | + *******************************/ |
1467 | +TRACEPOINT_EVENT(upstart_app_launch, libual_start, |
1468 | + TP_ARGS(const char *, appid), |
1469 | + TP_FIELDS( |
1470 | + ctf_string(appid, appid) |
1471 | + ) |
1472 | +) |
1473 | +TRACEPOINT_EVENT(upstart_app_launch, libual_determine_type, |
1474 | + TP_ARGS(const char *, appid, const char *, type), |
1475 | + TP_FIELDS( |
1476 | + ctf_string(appid, appid) |
1477 | + ctf_string(type, type) |
1478 | + ) |
1479 | +) |
1480 | +TRACEPOINT_EVENT(upstart_app_launch, libual_job_path_determined, |
1481 | + TP_ARGS(const char *, appid, const char *, job_path), |
1482 | + TP_FIELDS( |
1483 | + ctf_string(appid, appid) |
1484 | + ctf_string(job_path, job_path) |
1485 | + ) |
1486 | +) |
1487 | +TRACEPOINT_EVENT(upstart_app_launch, libual_start_message_sent, |
1488 | + TP_ARGS(const char *, appid), |
1489 | + TP_FIELDS( |
1490 | + ctf_string(appid, appid) |
1491 | + ) |
1492 | +) |
1493 | +TRACEPOINT_EVENT(upstart_app_launch, libual_start_message_callback, |
1494 | + TP_ARGS(const char *, appid), |
1495 | + TP_FIELDS( |
1496 | + ctf_string(appid, appid) |
1497 | + ) |
1498 | +) |
1499 | + |
1500 | +/******************************* |
1501 | + LibUAL observers |
1502 | + *******************************/ |
1503 | + |
1504 | +TRACEPOINT_EVENT(upstart_app_launch, observer_start, |
1505 | + TP_ARGS(const char *, type), |
1506 | + TP_FIELDS( |
1507 | + ctf_string(type, type) |
1508 | + ) |
1509 | +) |
1510 | +TRACEPOINT_EVENT(upstart_app_launch, observer_finish, |
1511 | + TP_ARGS(const char *, type), |
1512 | + TP_FIELDS( |
1513 | + ctf_string(type, type) |
1514 | + ) |
1515 | +) |
1516 | + |
1517 | + |
1518 | +/******************************* |
1519 | + Second Exec tracking |
1520 | + *******************************/ |
1521 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_start, |
1522 | + TP_ARGS(const char *, appid, const char *, appuris), |
1523 | + TP_FIELDS( |
1524 | + ctf_string(appid, appid) |
1525 | + ctf_string(appuris, appuris) |
1526 | + ) |
1527 | +) |
1528 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_resume, |
1529 | + TP_ARGS(const char *, appid), |
1530 | + TP_FIELDS( |
1531 | + ctf_string(appid, appid) |
1532 | + ) |
1533 | +) |
1534 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_complete, |
1535 | + TP_ARGS(const char *, appid), |
1536 | + TP_FIELDS( |
1537 | + ctf_string(appid, appid) |
1538 | + ) |
1539 | +) |
1540 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_timeout, |
1541 | + TP_ARGS(const char *, appid), |
1542 | + TP_FIELDS( |
1543 | + ctf_string(appid, appid) |
1544 | + ) |
1545 | +) |
1546 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_focus, |
1547 | + TP_ARGS(const char *, appid), |
1548 | + TP_FIELDS( |
1549 | + ctf_string(appid, appid) |
1550 | + ) |
1551 | +) |
1552 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_finish, |
1553 | + TP_ARGS(const char *, appid), |
1554 | + TP_FIELDS( |
1555 | + ctf_string(appid, appid) |
1556 | + ) |
1557 | +) |
1558 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_dbus_names, |
1559 | + TP_ARGS(const char *, appid), |
1560 | + TP_FIELDS( |
1561 | + ctf_string(appid, appid) |
1562 | + ) |
1563 | +) |
1564 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_primary_pid, |
1565 | + TP_ARGS(const char *, appid), |
1566 | + TP_FIELDS( |
1567 | + ctf_string(appid, appid) |
1568 | + ) |
1569 | +) |
1570 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_request_pid, |
1571 | + TP_ARGS(const char *, appid, const char *, dbus_name), |
1572 | + TP_FIELDS( |
1573 | + ctf_string(appid, appid) |
1574 | + ctf_string(dbus_name, dbus_name) |
1575 | + ) |
1576 | +) |
1577 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_pid, |
1578 | + TP_ARGS(const char *, appid, const char *, dbus_name), |
1579 | + TP_FIELDS( |
1580 | + ctf_string(appid, appid) |
1581 | + ctf_string(dbus_name, dbus_name) |
1582 | + ) |
1583 | +) |
1584 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_contact_app, |
1585 | + TP_ARGS(const char *, appid, const char *, dbus_name), |
1586 | + TP_FIELDS( |
1587 | + ctf_string(appid, appid) |
1588 | + ctf_string(dbus_name, dbus_name) |
1589 | + ) |
1590 | +) |
1591 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_contacted, |
1592 | + TP_ARGS(const char *, appid), |
1593 | + TP_FIELDS( |
1594 | + ctf_string(appid, appid) |
1595 | + ) |
1596 | +) |
1597 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_error, |
1598 | + TP_ARGS(const char *, appid), |
1599 | + TP_FIELDS( |
1600 | + ctf_string(appid, appid) |
1601 | + ) |
1602 | +) |
1603 | +TRACEPOINT_EVENT(upstart_app_launch, second_exec_connection_complete, |
1604 | + TP_ARGS(const char *, appid), |
1605 | + TP_FIELDS( |
1606 | + ctf_string(appid, appid) |
1607 | + ) |
1608 | +) |
1609 | + |
1610 | +/******************************* |
1611 | + Desktop File Single Instance |
1612 | + *******************************/ |
1613 | +TRACEPOINT_EVENT(upstart_app_launch, desktop_single_start, |
1614 | + TP_ARGS(const char *, appid), |
1615 | + TP_FIELDS( |
1616 | + ctf_string(appid, appid) |
1617 | + ) |
1618 | +) |
1619 | +TRACEPOINT_EVENT(upstart_app_launch, desktop_single_found, |
1620 | + TP_ARGS(const char *, appid), |
1621 | + TP_FIELDS( |
1622 | + ctf_string(appid, appid) |
1623 | + ) |
1624 | +) |
1625 | +TRACEPOINT_EVENT(upstart_app_launch, desktop_single_finished, |
1626 | + TP_ARGS(const char *, appid, const char *, apptype), |
1627 | + TP_FIELDS( |
1628 | + ctf_string(appid, appid) |
1629 | + ctf_string(apptype, apptype) |
1630 | + ) |
1631 | +) |
1632 | + |
1633 | |
1634 | === modified file 'libupstart-app-launch/upstart-app-launch.c' |
1635 | --- libupstart-app-launch/upstart-app-launch.c 2014-01-29 02:19:27 +0000 |
1636 | +++ libupstart-app-launch/upstart-app-launch.c 2014-02-11 03:28:22 +0000 |
1637 | @@ -20,53 +20,16 @@ |
1638 | #include "upstart-app-launch.h" |
1639 | #include <json-glib/json-glib.h> |
1640 | #include <upstart.h> |
1641 | -#include <nih/alloc.h> |
1642 | -#include <nih/error.h> |
1643 | #include <gio/gio.h> |
1644 | #include <string.h> |
1645 | |
1646 | -static void apps_for_job (NihDBusProxy * upstart, const gchar * name, GArray * apps, gboolean truncate_legacy); |
1647 | +#include "upstart-app-launch-trace.h" |
1648 | +#include "second-exec-core.h" |
1649 | +#include "../helpers.h" |
1650 | + |
1651 | +static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy); |
1652 | static void free_helper (gpointer value); |
1653 | |
1654 | -static NihDBusProxy * |
1655 | -nih_proxy_create (void) |
1656 | -{ |
1657 | - NihDBusProxy * upstart; |
1658 | - DBusConnection * conn; |
1659 | - DBusError error; |
1660 | - const gchar * bus_name = NULL; |
1661 | - |
1662 | - dbus_error_init(&error); |
1663 | - |
1664 | - conn = dbus_bus_get(DBUS_BUS_SESSION, &error); |
1665 | - bus_name = "com.ubuntu.Upstart"; |
1666 | - |
1667 | - if (conn == NULL) { |
1668 | - g_warning("Unable to connect to the Upstart Session: %s", error.message); |
1669 | - dbus_error_free(&error); |
1670 | - return NULL; |
1671 | - } |
1672 | - |
1673 | - dbus_error_free(&error); |
1674 | - |
1675 | - upstart = nih_dbus_proxy_new(NULL, conn, |
1676 | - bus_name, |
1677 | - DBUS_PATH_UPSTART, |
1678 | - NULL, NULL); |
1679 | - |
1680 | - if (upstart == NULL) { |
1681 | - g_warning("Unable to build proxy to Upstart"); |
1682 | - dbus_connection_unref(conn); |
1683 | - return NULL; |
1684 | - } |
1685 | - |
1686 | - dbus_connection_unref(conn); |
1687 | - |
1688 | - upstart->auto_start = FALSE; |
1689 | - |
1690 | - return upstart; |
1691 | -} |
1692 | - |
1693 | /* Function to take the urls and escape them so that they can be |
1694 | parsed on the other side correctly. */ |
1695 | static gchar * |
1696 | @@ -87,83 +50,261 @@ |
1697 | return urisjoin; |
1698 | } |
1699 | |
1700 | +typedef struct { |
1701 | + gchar * appid; |
1702 | + gchar * uris; |
1703 | +} app_start_t; |
1704 | + |
1705 | +static void |
1706 | +application_start_cb (GObject * obj, GAsyncResult * res, gpointer user_data) |
1707 | +{ |
1708 | + app_start_t * data = (app_start_t *)user_data; |
1709 | + GError * error = NULL; |
1710 | + GVariant * result = NULL; |
1711 | + |
1712 | + tracepoint(upstart_app_launch, libual_start_message_callback, data->appid); |
1713 | + g_debug("Started Message Callback: %s", data->appid); |
1714 | + |
1715 | + result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error); |
1716 | + |
1717 | + if (result != NULL) |
1718 | + g_variant_unref(result); |
1719 | + |
1720 | + if (error != NULL) { |
1721 | + if (g_dbus_error_is_remote_error(error)) { |
1722 | + gchar * remote_error = g_dbus_error_get_remote_error(error); |
1723 | + g_debug("Remote error: %s", remote_error); |
1724 | + if (g_strcmp0(remote_error, "com.ubuntu.Upstart0_6.Error.AlreadyStarted") == 0) { |
1725 | + second_exec(data->appid, data->uris); |
1726 | + } |
1727 | + |
1728 | + g_free(remote_error); |
1729 | + } else { |
1730 | + g_warning("Unable to emit event to start application: %s", error->message); |
1731 | + } |
1732 | + g_error_free(error); |
1733 | + } |
1734 | + |
1735 | + g_free(data->appid); |
1736 | + g_free(data->uris); |
1737 | + g_free(data); |
1738 | +} |
1739 | + |
1740 | +/* Get the path of the job from Upstart, if we've got it already, we'll just |
1741 | + use the cache of the value */ |
1742 | +static const gchar * |
1743 | +get_jobpath (GDBusConnection * con, const gchar * jobname) |
1744 | +{ |
1745 | + gchar * cachepath = g_strdup_printf("upstart-app-lauch-job-path-cache-%s", jobname); |
1746 | + gpointer cachedata = g_object_get_data(G_OBJECT(con), cachepath); |
1747 | + |
1748 | + if (cachedata != NULL) { |
1749 | + g_free(cachepath); |
1750 | + return cachedata; |
1751 | + } |
1752 | + |
1753 | + GError * error = NULL; |
1754 | + GVariant * job_path_variant = g_dbus_connection_call_sync(con, |
1755 | + DBUS_SERVICE_UPSTART, |
1756 | + DBUS_PATH_UPSTART, |
1757 | + DBUS_INTERFACE_UPSTART, |
1758 | + "GetJobByName", |
1759 | + g_variant_new("(s)", jobname), |
1760 | + G_VARIANT_TYPE("(o)"), |
1761 | + G_DBUS_CALL_FLAGS_NONE, |
1762 | + -1, /* timeout: default */ |
1763 | + NULL, /* cancelable */ |
1764 | + &error); |
1765 | + |
1766 | + if (error != NULL) { |
1767 | + g_warning("Unable to find job '%s': %s", jobname, error->message); |
1768 | + g_error_free(error); |
1769 | + g_free(cachepath); |
1770 | + return NULL; |
1771 | + } |
1772 | + |
1773 | + gchar * job_path = NULL; |
1774 | + g_variant_get(job_path_variant, "(o)", &job_path); |
1775 | + g_variant_unref(job_path_variant); |
1776 | + |
1777 | + g_object_set_data_full(G_OBJECT(con), cachepath, job_path, g_free); |
1778 | + g_free(cachepath); |
1779 | + |
1780 | + return job_path; |
1781 | +} |
1782 | + |
1783 | +/* Check to see if a legacy app wants us to manage whether they're |
1784 | + single instance or not */ |
1785 | +static gboolean |
1786 | +legacy_single_instance (const gchar * appid) |
1787 | +{ |
1788 | + tracepoint(upstart_app_launch, desktop_single_start, appid); |
1789 | + |
1790 | + GKeyFile * keyfile = keyfile_for_appid(appid, NULL); |
1791 | + |
1792 | + if (keyfile == NULL) { |
1793 | + g_error("Unable to find keyfile for application '%s'", appid); |
1794 | + return FALSE; |
1795 | + } |
1796 | + |
1797 | + tracepoint(upstart_app_launch, desktop_single_found, appid); |
1798 | + |
1799 | + gboolean singleinstance = FALSE; |
1800 | + |
1801 | + if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", NULL)) { |
1802 | + GError * error = NULL; |
1803 | + |
1804 | + singleinstance = g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-Single-Instance", &error); |
1805 | + |
1806 | + if (error != NULL) { |
1807 | + g_warning("Unable to get single instance key for app '%s': %s", appid, error->message); |
1808 | + g_error_free(error); |
1809 | + /* Ensure that if we got an error, we assume standard case */ |
1810 | + singleinstance = FALSE; |
1811 | + } |
1812 | + } |
1813 | + |
1814 | + g_key_file_free(keyfile); |
1815 | + |
1816 | + tracepoint(upstart_app_launch, desktop_single_finished, appid, singleinstance ? "single" : "unmanaged"); |
1817 | + |
1818 | + return singleinstance; |
1819 | +} |
1820 | + |
1821 | gboolean |
1822 | upstart_app_launch_start_application (const gchar * appid, const gchar * const * uris) |
1823 | { |
1824 | - NihDBusProxy * proxy = NULL; |
1825 | - |
1826 | - proxy = nih_proxy_create(); |
1827 | - if (proxy == NULL) { |
1828 | + g_return_val_if_fail(appid != NULL, FALSE); |
1829 | + |
1830 | + tracepoint(upstart_app_launch, libual_start, appid); |
1831 | + |
1832 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1833 | + g_return_val_if_fail(con != NULL, FALSE); |
1834 | + |
1835 | + /* Determine whether it's a click package by looking for the symlink |
1836 | + that is created by the desktop hook */ |
1837 | + gchar * appiddesktop = g_strdup_printf("%s.desktop", appid); |
1838 | + gchar * click_link = NULL; |
1839 | + const gchar * link_farm_dir = g_getenv("UPSTART_APP_LAUNCH_LINK_FARM"); |
1840 | + if (G_LIKELY(link_farm_dir == NULL)) { |
1841 | + click_link = g_build_filename(g_get_home_dir(), ".cache", "upstart-app-launch", "desktop", appiddesktop, NULL); |
1842 | + } else { |
1843 | + click_link = g_build_filename(link_farm_dir, appiddesktop, NULL); |
1844 | + } |
1845 | + g_free(appiddesktop); |
1846 | + gboolean click = g_file_test(click_link, G_FILE_TEST_EXISTS); |
1847 | + g_free(click_link); |
1848 | + |
1849 | + tracepoint(upstart_app_launch, libual_determine_type, appid, click ? "click" : "legacy"); |
1850 | + |
1851 | + /* Figure out the DBus path for the job */ |
1852 | + const gchar * jobpath = NULL; |
1853 | + if (click) { |
1854 | + jobpath = get_jobpath(con, "application-click"); |
1855 | + } else { |
1856 | + jobpath = get_jobpath(con, "application-legacy"); |
1857 | + } |
1858 | + |
1859 | + if (jobpath == NULL) |
1860 | return FALSE; |
1861 | - } |
1862 | - |
1863 | - gchar * env_appid = g_strdup_printf("APP_ID=%s", appid); |
1864 | - gchar * env_uris = NULL; |
1865 | + |
1866 | + tracepoint(upstart_app_launch, libual_job_path_determined, appid, jobpath); |
1867 | + |
1868 | + /* Callback data */ |
1869 | + app_start_t * app_start_data = g_new0(app_start_t, 1); |
1870 | + app_start_data->appid = g_strdup(appid); |
1871 | + |
1872 | + /* Build up our environment */ |
1873 | + GVariantBuilder builder; |
1874 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
1875 | + |
1876 | + g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
1877 | + |
1878 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appid))); |
1879 | |
1880 | if (uris != NULL) { |
1881 | gchar * urisjoin = app_uris_string(uris); |
1882 | - env_uris = g_strdup_printf("APP_URIS=%s", urisjoin); |
1883 | - g_free(urisjoin); |
1884 | - } |
1885 | - |
1886 | - gchar * env[3]; |
1887 | - env[0] = env_appid; |
1888 | - env[1] = env_uris; |
1889 | - env[2] = NULL; |
1890 | - |
1891 | - gboolean retval = TRUE; |
1892 | - if (upstart_emit_event_sync(NULL, proxy, "application-start", env, 0) != 0) { |
1893 | - g_warning("Unable to emit signal 'application-start'"); |
1894 | - retval = FALSE; |
1895 | - } |
1896 | - |
1897 | - g_free(env_appid); |
1898 | - g_free(env_uris); |
1899 | - nih_unref(proxy, NULL); |
1900 | - |
1901 | - return retval; |
1902 | + gchar * urienv = g_strdup_printf("APP_URIS=%s", urisjoin); |
1903 | + app_start_data->uris = urisjoin; |
1904 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(urienv)); |
1905 | + } |
1906 | + |
1907 | + if (!click) { |
1908 | + if (legacy_single_instance(appid)) { |
1909 | + g_variant_builder_add_value(&builder, g_variant_new_string("INSTANCE_ID=")); |
1910 | + } else { |
1911 | + gchar * instanceid = g_strdup_printf("INSTANCE_ID=%" G_GUINT64_FORMAT, g_get_real_time()); |
1912 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(instanceid)); |
1913 | + } |
1914 | + } |
1915 | + |
1916 | + g_variant_builder_close(&builder); |
1917 | + g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
1918 | + |
1919 | + /* Call the job start function */ |
1920 | + g_dbus_connection_call(con, |
1921 | + DBUS_SERVICE_UPSTART, |
1922 | + jobpath, |
1923 | + DBUS_INTERFACE_UPSTART_JOB, |
1924 | + "Start", |
1925 | + g_variant_builder_end(&builder), |
1926 | + NULL, |
1927 | + G_DBUS_CALL_FLAGS_NONE, |
1928 | + -1, |
1929 | + NULL, /* cancelable */ |
1930 | + application_start_cb, |
1931 | + app_start_data); |
1932 | + |
1933 | + tracepoint(upstart_app_launch, libual_start_message_sent, appid); |
1934 | + |
1935 | + g_object_unref(con); |
1936 | + |
1937 | + return TRUE; |
1938 | } |
1939 | |
1940 | static void |
1941 | -stop_job (NihDBusProxy * upstart, const gchar * jobname, const gchar * appname, const gchar * instanceid) |
1942 | +stop_job (GDBusConnection * con, const gchar * jobname, const gchar * appname, const gchar * instanceid) |
1943 | { |
1944 | g_debug("Stopping job %s app_id %s instance_id %s", jobname, appname, instanceid); |
1945 | - nih_local char * job_path = NULL; |
1946 | - if (upstart_get_job_by_name_sync(NULL, upstart, jobname, &job_path) != 0) { |
1947 | - g_warning("Unable to find job '%s'", jobname); |
1948 | - return; |
1949 | - } |
1950 | - |
1951 | - NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
1952 | - upstart->name, |
1953 | - job_path, |
1954 | - NULL, NULL); |
1955 | - |
1956 | - if (job_proxy == NULL) { |
1957 | - g_warning("Unable to build proxy to Job '%s'", jobname); |
1958 | - return; |
1959 | - } |
1960 | - |
1961 | - gchar * app = g_strdup_printf("APP_ID=%s", appname); |
1962 | - gchar * inst = NULL; |
1963 | + |
1964 | + const gchar * job_path = get_jobpath(con, jobname); |
1965 | + if (job_path == NULL) |
1966 | + return; |
1967 | + |
1968 | + GVariantBuilder builder; |
1969 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
1970 | + g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
1971 | + |
1972 | + g_variant_builder_add_value(&builder, |
1973 | + g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appname))); |
1974 | |
1975 | if (instanceid != NULL) { |
1976 | - inst = g_strdup_printf("INSTANCE_ID=%s", instanceid); |
1977 | - } |
1978 | - |
1979 | - gchar * env[3] = { |
1980 | - app, |
1981 | - inst, |
1982 | - NULL |
1983 | - }; |
1984 | - |
1985 | - if (job_class_stop_sync(NULL, job_proxy, env, 0) != 0) { |
1986 | - g_warning("Unable to stop job %s app %s instance %s", jobname, appname, instanceid); |
1987 | - } |
1988 | - |
1989 | - g_free(app); |
1990 | - g_free(inst); |
1991 | - nih_unref(job_proxy, NULL); |
1992 | + g_variant_builder_add_value(&builder, |
1993 | + g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instanceid))); |
1994 | + } |
1995 | + |
1996 | + g_variant_builder_close(&builder); |
1997 | + g_variant_builder_add_value(&builder, g_variant_new_boolean(FALSE)); /* wait */ |
1998 | + |
1999 | + GError * error = NULL; |
2000 | + GVariant * stop_variant = g_dbus_connection_call_sync(con, |
2001 | + DBUS_SERVICE_UPSTART, |
2002 | + job_path, |
2003 | + DBUS_INTERFACE_UPSTART_JOB, |
2004 | + "Stop", |
2005 | + g_variant_builder_end(&builder), |
2006 | + NULL, |
2007 | + G_DBUS_CALL_FLAGS_NONE, |
2008 | + -1, /* timeout: default */ |
2009 | + NULL, /* cancelable */ |
2010 | + &error); |
2011 | + |
2012 | + if (error != NULL) { |
2013 | + g_warning("Unable to stop job %s app_id %s instance_id %s: %s", jobname, appname, instanceid, error->message); |
2014 | + g_error_free(error); |
2015 | + } |
2016 | + |
2017 | + g_variant_unref(stop_variant); |
2018 | } |
2019 | |
2020 | static void |
2021 | @@ -176,25 +317,24 @@ |
2022 | gboolean |
2023 | upstart_app_launch_stop_application (const gchar * appid) |
2024 | { |
2025 | + g_return_val_if_fail(appid != NULL, FALSE); |
2026 | + |
2027 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2028 | + g_return_val_if_fail(con != NULL, FALSE); |
2029 | + |
2030 | gboolean found = FALSE; |
2031 | int i; |
2032 | - NihDBusProxy * proxy = NULL; |
2033 | - |
2034 | - proxy = nih_proxy_create(); |
2035 | - if (proxy == NULL) { |
2036 | - return FALSE; |
2037 | - } |
2038 | |
2039 | GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *)); |
2040 | g_array_set_clear_func(apps, free_helper); |
2041 | |
2042 | /* Look through the click jobs and see if any match. There can |
2043 | only be one instance for each ID in the click world */ |
2044 | - apps_for_job(proxy, "application-click", apps, FALSE); |
2045 | + apps_for_job(con, "application-click", apps, FALSE); |
2046 | for (i = 0; i < apps->len; i++) { |
2047 | const gchar * array_id = g_array_index(apps, const gchar *, i); |
2048 | if (g_strcmp0(array_id, appid) == 0) { |
2049 | - stop_job(proxy, "application-click", appid, NULL); |
2050 | + stop_job(con, "application-click", appid, NULL); |
2051 | found = TRUE; |
2052 | break; /* There can be only one with click */ |
2053 | } |
2054 | @@ -206,20 +346,20 @@ |
2055 | /* Look through the legacy apps. Trickier because we know that there |
2056 | can be many instances of the legacy jobs out there, so we might |
2057 | have to kill more than one of them. */ |
2058 | - apps_for_job(proxy, "application-legacy", apps, FALSE); |
2059 | + apps_for_job(con, "application-legacy", apps, FALSE); |
2060 | gchar * appiddash = g_strdup_printf("%s-", appid); /* Probably could go RegEx here, but let's start with just a prefix lookup */ |
2061 | for (i = 0; i < apps->len; i++) { |
2062 | const gchar * array_id = g_array_index(apps, const gchar *, i); |
2063 | if (g_str_has_prefix(array_id, appiddash)) { |
2064 | gchar * instanceid = g_strrstr(array_id, "-"); |
2065 | - stop_job(proxy, "application-legacy", appid, &(instanceid[1])); |
2066 | + stop_job(con, "application-legacy", appid, &(instanceid[1])); |
2067 | found = TRUE; |
2068 | } |
2069 | } |
2070 | g_free(appiddash); |
2071 | |
2072 | g_array_free(apps, TRUE); |
2073 | - nih_unref(proxy, NULL); |
2074 | + g_object_unref(con); |
2075 | |
2076 | return found; |
2077 | } |
2078 | @@ -255,18 +395,33 @@ |
2079 | gpointer user_data; |
2080 | }; |
2081 | |
2082 | +/* The data we keep for each failed observer */ |
2083 | +typedef struct _failed_observer_t failed_observer_t; |
2084 | +struct _failed_observer_t { |
2085 | + GDBusConnection * conn; |
2086 | + guint sighandle; |
2087 | + upstart_app_launch_app_failed_observer_t func; |
2088 | + gpointer user_data; |
2089 | +}; |
2090 | + |
2091 | /* The lists of Observers */ |
2092 | static GList * starting_array = NULL; |
2093 | static GList * started_array = NULL; |
2094 | static GList * stop_array = NULL; |
2095 | static GList * focus_array = NULL; |
2096 | static GList * resume_array = NULL; |
2097 | +static GList * failed_array = NULL; |
2098 | |
2099 | static void |
2100 | observer_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
2101 | { |
2102 | observer_t * observer = (observer_t *)user_data; |
2103 | |
2104 | + const gchar * signalname = NULL; |
2105 | + g_variant_get_child(params, 0, "&s", &signalname); |
2106 | + |
2107 | + tracepoint(upstart_app_launch, observer_start, signalname); |
2108 | + |
2109 | gchar * env = NULL; |
2110 | GVariant * envs = g_variant_get_child_value(params, 1); |
2111 | GVariantIter iter; |
2112 | @@ -300,6 +455,8 @@ |
2113 | observer->func(instance, observer->user_data); |
2114 | } |
2115 | |
2116 | + tracepoint(upstart_app_launch, observer_finish, signalname); |
2117 | + |
2118 | g_free(instance); |
2119 | } |
2120 | |
2121 | @@ -388,10 +545,14 @@ |
2122 | observer_t * observer = (observer_t *)user_data; |
2123 | const gchar * appid = NULL; |
2124 | |
2125 | + tracepoint(upstart_app_launch, observer_start, "focus"); |
2126 | + |
2127 | if (observer->func != NULL) { |
2128 | g_variant_get(params, "(&s)", &appid); |
2129 | observer->func(appid, observer->user_data); |
2130 | } |
2131 | + |
2132 | + tracepoint(upstart_app_launch, observer_finish, "focus"); |
2133 | } |
2134 | |
2135 | gboolean |
2136 | @@ -404,6 +565,8 @@ |
2137 | static void |
2138 | resume_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
2139 | { |
2140 | + tracepoint(upstart_app_launch, observer_start, "resume"); |
2141 | + |
2142 | focus_signal_cb(conn, sender, object, interface, signal, params, user_data); |
2143 | |
2144 | GError * error = NULL; |
2145 | @@ -419,6 +582,8 @@ |
2146 | g_warning("Unable to emit response signal: %s", error->message); |
2147 | g_error_free(error); |
2148 | } |
2149 | + |
2150 | + tracepoint(upstart_app_launch, observer_finish, "resume"); |
2151 | } |
2152 | |
2153 | gboolean |
2154 | @@ -431,6 +596,8 @@ |
2155 | static void |
2156 | starting_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
2157 | { |
2158 | + tracepoint(upstart_app_launch, observer_start, "starting"); |
2159 | + |
2160 | focus_signal_cb(conn, sender, object, interface, signal, params, user_data); |
2161 | |
2162 | GError * error = NULL; |
2163 | @@ -446,6 +613,8 @@ |
2164 | g_warning("Unable to emit response signal: %s", error->message); |
2165 | g_error_free(error); |
2166 | } |
2167 | + |
2168 | + tracepoint(upstart_app_launch, observer_finish, "starting"); |
2169 | } |
2170 | |
2171 | gboolean |
2172 | @@ -454,10 +623,63 @@ |
2173 | return add_session_generic(observer, user_data, "UnityStartingBroadcast", &starting_array, starting_signal_cb); |
2174 | } |
2175 | |
2176 | +/* Handle the failed signal when it occurs, call the observer */ |
2177 | +static void |
2178 | +failed_signal_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
2179 | +{ |
2180 | + failed_observer_t * observer = (failed_observer_t *)user_data; |
2181 | + const gchar * appid = NULL; |
2182 | + const gchar * typestr = NULL; |
2183 | + |
2184 | + tracepoint(upstart_app_launch, observer_start, "failed"); |
2185 | + |
2186 | + if (observer->func != NULL) { |
2187 | + upstart_app_launch_app_failed_t type = UPSTART_APP_LAUNCH_APP_FAILED_CRASH; |
2188 | + g_variant_get(params, "(&s&s)", &appid, &typestr); |
2189 | + |
2190 | + if (g_strcmp0("crash", typestr) == 0) { |
2191 | + type = UPSTART_APP_LAUNCH_APP_FAILED_CRASH; |
2192 | + } else if (g_strcmp0("start-failure", typestr) == 0) { |
2193 | + type = UPSTART_APP_LAUNCH_APP_FAILED_START_FAILURE; |
2194 | + } else { |
2195 | + g_warning("Application failure type '%s' unknown, reporting as a crash", typestr); |
2196 | + } |
2197 | + |
2198 | + observer->func(appid, type, observer->user_data); |
2199 | + } |
2200 | + |
2201 | + tracepoint(upstart_app_launch, observer_finish, "failed"); |
2202 | +} |
2203 | + |
2204 | gboolean |
2205 | upstart_app_launch_observer_add_app_failed (upstart_app_launch_app_failed_observer_t observer, gpointer user_data) |
2206 | { |
2207 | - return FALSE; |
2208 | + GDBusConnection * conn = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2209 | + |
2210 | + if (conn == NULL) { |
2211 | + return FALSE; |
2212 | + } |
2213 | + |
2214 | + failed_observer_t * observert = g_new0(failed_observer_t, 1); |
2215 | + |
2216 | + observert->conn = conn; |
2217 | + observert->func = observer; |
2218 | + observert->user_data = user_data; |
2219 | + |
2220 | + failed_array = g_list_prepend(failed_array, observert); |
2221 | + |
2222 | + observert->sighandle = g_dbus_connection_signal_subscribe(conn, |
2223 | + NULL, /* sender */ |
2224 | + "com.canonical.UpstartAppLaunch", /* interface */ |
2225 | + "ApplicationFailed", /* signal */ |
2226 | + "/", /* path */ |
2227 | + NULL, /* arg0 */ |
2228 | + G_DBUS_SIGNAL_FLAGS_NONE, |
2229 | + failed_signal_cb, |
2230 | + observert, |
2231 | + NULL); /* user data destroy */ |
2232 | + |
2233 | + return TRUE; |
2234 | } |
2235 | |
2236 | static gboolean |
2237 | @@ -520,167 +742,234 @@ |
2238 | gboolean |
2239 | upstart_app_launch_observer_delete_app_failed (upstart_app_launch_app_failed_observer_t observer, gpointer user_data) |
2240 | { |
2241 | - return FALSE; |
2242 | + failed_observer_t * observert = NULL; |
2243 | + GList * look; |
2244 | + |
2245 | + for (look = failed_array; look != NULL; look = g_list_next(look)) { |
2246 | + observert = (failed_observer_t *)look->data; |
2247 | + |
2248 | + if (observert->func == observer && observert->user_data == user_data) { |
2249 | + break; |
2250 | + } |
2251 | + } |
2252 | + |
2253 | + if (look == NULL) { |
2254 | + return FALSE; |
2255 | + } |
2256 | + |
2257 | + g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); |
2258 | + g_object_unref(observert->conn); |
2259 | + |
2260 | + g_free(observert); |
2261 | + failed_array = g_list_delete_link(failed_array, look); |
2262 | + |
2263 | + return TRUE; |
2264 | +} |
2265 | + |
2266 | +typedef void (*per_instance_func_t) (GDBusConnection * con, GVariant * prop_dict, gpointer user_data); |
2267 | + |
2268 | +static void |
2269 | +foreach_job_instance (GDBusConnection * con, const gchar * jobname, per_instance_func_t func, gpointer user_data) |
2270 | +{ |
2271 | + const gchar * job_path = get_jobpath(con, jobname); |
2272 | + if (job_path == NULL) |
2273 | + return; |
2274 | + |
2275 | + GError * error = NULL; |
2276 | + GVariant * instance_tuple = g_dbus_connection_call_sync(con, |
2277 | + DBUS_SERVICE_UPSTART, |
2278 | + job_path, |
2279 | + DBUS_INTERFACE_UPSTART_JOB, |
2280 | + "GetAllInstances", |
2281 | + NULL, |
2282 | + G_VARIANT_TYPE("(ao)"), |
2283 | + G_DBUS_CALL_FLAGS_NONE, |
2284 | + -1, /* timeout: default */ |
2285 | + NULL, /* cancelable */ |
2286 | + &error); |
2287 | + |
2288 | + if (error != NULL) { |
2289 | + g_warning("Unable to get instances of job '%s': %s", jobname, error->message); |
2290 | + g_error_free(error); |
2291 | + return; |
2292 | + } |
2293 | + |
2294 | + GVariant * instance_list = g_variant_get_child_value(instance_tuple, 0); |
2295 | + g_variant_unref(instance_tuple); |
2296 | + |
2297 | + GVariantIter instance_iter; |
2298 | + g_variant_iter_init(&instance_iter, instance_list); |
2299 | + const gchar * instance_path = NULL; |
2300 | + |
2301 | + while (g_variant_iter_loop(&instance_iter, "&o", &instance_path)) { |
2302 | + GVariant * props_tuple = g_dbus_connection_call_sync(con, |
2303 | + DBUS_SERVICE_UPSTART, |
2304 | + instance_path, |
2305 | + "org.freedesktop.DBus.Properties", |
2306 | + "GetAll", |
2307 | + g_variant_new("(s)", DBUS_INTERFACE_UPSTART_INSTANCE), |
2308 | + G_VARIANT_TYPE("(a{sv})"), |
2309 | + G_DBUS_CALL_FLAGS_NONE, |
2310 | + -1, /* timeout: default */ |
2311 | + NULL, /* cancelable */ |
2312 | + &error); |
2313 | + |
2314 | + if (error != NULL) { |
2315 | + g_warning("Unable to name of instance '%s': %s", instance_path, error->message); |
2316 | + g_error_free(error); |
2317 | + error = NULL; |
2318 | + continue; |
2319 | + } |
2320 | + |
2321 | + GVariant * props_dict = g_variant_get_child_value(props_tuple, 0); |
2322 | + |
2323 | + func(con, props_dict, user_data); |
2324 | + |
2325 | + g_variant_unref(props_dict); |
2326 | + g_variant_unref(props_tuple); |
2327 | + |
2328 | + } |
2329 | + |
2330 | + g_variant_unref(instance_list); |
2331 | +} |
2332 | + |
2333 | +typedef struct { |
2334 | + GArray * apps; |
2335 | + gboolean truncate_legacy; |
2336 | + const gchar * jobname; |
2337 | +} apps_for_job_t; |
2338 | + |
2339 | +static void |
2340 | +apps_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data) |
2341 | +{ |
2342 | + GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
2343 | + if (namev == NULL) { |
2344 | + return; |
2345 | + } |
2346 | + |
2347 | + apps_for_job_t * data = (apps_for_job_t *)user_data; |
2348 | + gchar * instance_name = g_variant_dup_string(namev, NULL); |
2349 | + g_variant_unref(namev); |
2350 | + |
2351 | + if (data->truncate_legacy && g_strcmp0(data->jobname, "application-legacy") == 0) { |
2352 | + gchar * last_dash = g_strrstr(instance_name, "-"); |
2353 | + if (last_dash != NULL) { |
2354 | + last_dash[0] = '\0'; |
2355 | + } |
2356 | + } |
2357 | + |
2358 | + g_array_append_val(data->apps, instance_name); |
2359 | } |
2360 | |
2361 | /* Get all the instances for a given job name */ |
2362 | static void |
2363 | -apps_for_job (NihDBusProxy * upstart, const gchar * name, GArray * apps, gboolean truncate_legacy) |
2364 | +apps_for_job (GDBusConnection * con, const gchar * jobname, GArray * apps, gboolean truncate_legacy) |
2365 | { |
2366 | - nih_local char * job_path = NULL; |
2367 | - if (upstart_get_job_by_name_sync(NULL, upstart, name, &job_path) != 0) { |
2368 | - g_warning("Unable to find job '%s'", name); |
2369 | - return; |
2370 | - } |
2371 | - |
2372 | - nih_local NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
2373 | - upstart->name, |
2374 | - job_path, |
2375 | - NULL, NULL); |
2376 | - |
2377 | - if (job_proxy == NULL) { |
2378 | - g_warning("Unable to build proxy to Job '%s'", name); |
2379 | - return; |
2380 | - } |
2381 | - |
2382 | - nih_local char ** instances; |
2383 | - if (job_class_get_all_instances_sync(NULL, job_proxy, &instances) != 0) { |
2384 | - NihError * error = nih_error_get(); |
2385 | - g_warning("Unable to get instances for job '%s': %s", name, error->message); |
2386 | - nih_free(error); |
2387 | - return; |
2388 | - } |
2389 | - |
2390 | - int jobnum; |
2391 | - for (jobnum = 0; instances[jobnum] != NULL; jobnum++) { |
2392 | - NihDBusProxy * instance_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
2393 | - upstart->name, |
2394 | - instances[jobnum], |
2395 | - NULL, NULL); |
2396 | - |
2397 | - nih_local char * instance_name = NULL; |
2398 | - if (job_get_name_sync(NULL, instance_proxy, &instance_name) == 0) { |
2399 | - gchar * dup = g_strdup(instance_name); |
2400 | - |
2401 | - if (truncate_legacy && g_strcmp0(name, "application-legacy") == 0) { |
2402 | - gchar * last_dash = g_strrstr(dup, "-"); |
2403 | - if (last_dash != NULL) { |
2404 | - last_dash[0] = '\0'; |
2405 | - } |
2406 | - } |
2407 | - |
2408 | - g_array_append_val(apps, dup); |
2409 | - } else { |
2410 | - g_warning("Unable to get name for instance '%s' of job '%s'", instances[jobnum], name); |
2411 | - } |
2412 | - |
2413 | - nih_unref(instance_proxy, NULL); |
2414 | - } |
2415 | + apps_for_job_t data = { |
2416 | + .jobname = jobname, |
2417 | + .apps = apps, |
2418 | + .truncate_legacy = truncate_legacy |
2419 | + }; |
2420 | + |
2421 | + foreach_job_instance(con, jobname, apps_for_job_instance, &data); |
2422 | } |
2423 | |
2424 | gchar ** |
2425 | upstart_app_launch_list_running_apps (void) |
2426 | { |
2427 | - NihDBusProxy * proxy = NULL; |
2428 | - |
2429 | - proxy = nih_proxy_create(); |
2430 | - if (proxy == NULL) { |
2431 | - return g_new0(gchar *, 1); |
2432 | - } |
2433 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2434 | + g_return_val_if_fail(con != NULL, g_new0(gchar *, 1)); |
2435 | |
2436 | GArray * apps = g_array_new(TRUE, TRUE, sizeof(gchar *)); |
2437 | |
2438 | - apps_for_job(proxy, "application-legacy", apps, TRUE); |
2439 | - apps_for_job(proxy, "application-click", apps, FALSE); |
2440 | + apps_for_job(con, "application-legacy", apps, TRUE); |
2441 | + apps_for_job(con, "application-click", apps, FALSE); |
2442 | |
2443 | - nih_unref(proxy, NULL); |
2444 | + g_object_unref(con); |
2445 | |
2446 | return (gchar **)g_array_free(apps, FALSE); |
2447 | } |
2448 | |
2449 | +typedef struct { |
2450 | + GPid pid; |
2451 | + const gchar * appid; |
2452 | + const gchar * jobname; |
2453 | +} pid_for_job_t; |
2454 | + |
2455 | +static void |
2456 | +pid_for_job_instance (GDBusConnection * con, GVariant * props_dict, gpointer user_data) |
2457 | +{ |
2458 | + GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
2459 | + if (namev == NULL) { |
2460 | + return; |
2461 | + } |
2462 | + |
2463 | + pid_for_job_t * data = (pid_for_job_t *)user_data; |
2464 | + gchar * instance_name = g_variant_dup_string(namev, NULL); |
2465 | + g_variant_unref(namev); |
2466 | + |
2467 | + if (g_strcmp0(data->jobname, "application-legacy") == 0) { |
2468 | + gchar * last_dash = g_strrstr(instance_name, "-"); |
2469 | + if (last_dash != NULL) { |
2470 | + last_dash[0] = '\0'; |
2471 | + } |
2472 | + } |
2473 | + |
2474 | + if (g_strcmp0(instance_name, data->appid) == 0) { |
2475 | + GVariant * processv = g_variant_lookup_value(props_dict, "processes", G_VARIANT_TYPE("a(si)")); |
2476 | + |
2477 | + if (processv != NULL) { |
2478 | + if (g_variant_n_children(processv) > 0) { |
2479 | + GVariant * first_entry = g_variant_get_child_value(processv, 0); |
2480 | + GVariant * pidv = g_variant_get_child_value(first_entry, 1); |
2481 | + |
2482 | + data->pid = g_variant_get_int32(pidv); |
2483 | + |
2484 | + g_variant_unref(pidv); |
2485 | + g_variant_unref(first_entry); |
2486 | + } |
2487 | + |
2488 | + g_variant_unref(processv); |
2489 | + } |
2490 | + } |
2491 | + |
2492 | + g_free(instance_name); |
2493 | +} |
2494 | + |
2495 | /* Look for the app for a job */ |
2496 | static GPid |
2497 | -pid_for_job (NihDBusProxy * upstart, const gchar * job, const gchar * appid) |
2498 | +pid_for_job (GDBusConnection * con, const gchar * jobname, const gchar * appid) |
2499 | { |
2500 | - nih_local char * job_path = NULL; |
2501 | - if (upstart_get_job_by_name_sync(NULL, upstart, job, &job_path) != 0) { |
2502 | - g_warning("Unable to find job '%s'", job); |
2503 | - return 0; |
2504 | - } |
2505 | - |
2506 | - NihDBusProxy * job_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
2507 | - upstart->name, |
2508 | - job_path, |
2509 | - NULL, NULL); |
2510 | - |
2511 | - if (job_proxy == NULL) { |
2512 | - g_warning("Unable to build proxy to Job '%s'", job); |
2513 | - return 0; |
2514 | - } |
2515 | - |
2516 | - nih_local char ** instances; |
2517 | - if (job_class_get_all_instances_sync(NULL, job_proxy, &instances) != 0) { |
2518 | - g_warning("Unable to get instances for job '%s'", job); |
2519 | - nih_unref(job_proxy, NULL); |
2520 | - return 0; |
2521 | - } |
2522 | - |
2523 | - GPid pid = 0; |
2524 | - int jobnum; |
2525 | - for (jobnum = 0; instances[jobnum] != NULL && pid == 0; jobnum++) { |
2526 | - NihDBusProxy * instance_proxy = nih_dbus_proxy_new(NULL, upstart->connection, |
2527 | - upstart->name, |
2528 | - instances[jobnum], |
2529 | - NULL, NULL); |
2530 | - |
2531 | - nih_local char * instance_name = NULL; |
2532 | - if (job_get_name_sync(NULL, instance_proxy, &instance_name) == 0) { |
2533 | - if (g_strcmp0(job, "application-legacy") == 0) { |
2534 | - gchar * last_dash = g_strrstr(instance_name, "-"); |
2535 | - if (last_dash != NULL) { |
2536 | - last_dash[0] = '\0'; |
2537 | - } |
2538 | - } |
2539 | - } else { |
2540 | - g_warning("Unable to get name for instance '%s' of job '%s'", instances[jobnum], job); |
2541 | - } |
2542 | - |
2543 | - if (g_strcmp0(instance_name, appid) == 0) { |
2544 | - nih_local JobProcessesElement ** elements; |
2545 | - if (job_get_processes_sync(NULL, instance_proxy, &elements) == 0) { |
2546 | - pid = elements[0]->item1; |
2547 | - } |
2548 | - } |
2549 | - |
2550 | - nih_unref(instance_proxy, NULL); |
2551 | - } |
2552 | - |
2553 | - nih_unref(job_proxy, NULL); |
2554 | - |
2555 | - return pid; |
2556 | + pid_for_job_t data = { |
2557 | + .jobname = jobname, |
2558 | + .appid = appid, |
2559 | + .pid = 0 |
2560 | + }; |
2561 | + |
2562 | + foreach_job_instance(con, jobname, pid_for_job_instance, &data); |
2563 | + |
2564 | + return data.pid; |
2565 | } |
2566 | |
2567 | GPid |
2568 | upstart_app_launch_get_primary_pid (const gchar * appid) |
2569 | { |
2570 | - NihDBusProxy * proxy = NULL; |
2571 | + g_return_val_if_fail(appid != NULL, 0); |
2572 | |
2573 | - proxy = nih_proxy_create(); |
2574 | - if (proxy == NULL) { |
2575 | - return 0; |
2576 | - } |
2577 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
2578 | + g_return_val_if_fail(con != NULL, 0); |
2579 | |
2580 | GPid pid = 0; |
2581 | |
2582 | if (pid == 0) { |
2583 | - pid = pid_for_job(proxy, "application-legacy", appid); |
2584 | + pid = pid_for_job(con, "application-legacy", appid); |
2585 | } |
2586 | |
2587 | if (pid == 0) { |
2588 | - pid = pid_for_job(proxy, "application-click", appid); |
2589 | + pid = pid_for_job(con, "application-click", appid); |
2590 | } |
2591 | |
2592 | - nih_unref(proxy, NULL); |
2593 | + g_object_unref(con); |
2594 | |
2595 | return pid; |
2596 | } |
2597 | @@ -688,6 +977,8 @@ |
2598 | gboolean |
2599 | upstart_app_launch_pid_in_app_id (GPid pid, const gchar * appid) |
2600 | { |
2601 | + g_return_val_if_fail(appid != NULL, FALSE); |
2602 | + |
2603 | if (pid == 0) { |
2604 | return FALSE; |
2605 | } |
2606 | |
2607 | === modified file 'libupstart-app-launch/upstart-app-launch.h' |
2608 | --- libupstart-app-launch/upstart-app-launch.h 2014-01-29 02:33:52 +0000 |
2609 | +++ libupstart-app-launch/upstart-app-launch.h 2014-02-11 03:28:22 +0000 |
2610 | @@ -29,35 +29,41 @@ |
2611 | #endif |
2612 | |
2613 | /** |
2614 | - * upstart_app_launch_app_failed_t: |
2615 | + * UpstartAppLaunchAppFailed: |
2616 | * |
2617 | * Types of failure that we report. |
2618 | */ |
2619 | -enum _upstart_app_launch_app_failed_t { |
2620 | - UPSTART_APP_LAUNCH_APP_FAILED_CRASH, |
2621 | - UPSTART_APP_LAUNCH_APP_FAILED_START_FAILURE, |
2622 | -}; |
2623 | -typedef enum _upstart_app_launch_app_failed_t upstart_app_launch_app_failed_t; |
2624 | +typedef enum { /*< prefix=UPSTART_APP_LAUNCH_APP_FAILED */ |
2625 | + UPSTART_APP_LAUNCH_APP_FAILED_CRASH, /*< nick=crash */ |
2626 | + UPSTART_APP_LAUNCH_APP_FAILED_START_FAILURE, /*< nick=start-failure */ |
2627 | +} UpstartAppLaunchAppFailed; |
2628 | +typedef UpstartAppLaunchAppFailed upstart_app_launch_app_failed_t; |
2629 | |
2630 | /** |
2631 | - * upstart_app_launch_app_observer_t: |
2632 | + * UpstartAppLaunchAppObserver: |
2633 | * |
2634 | * Function prototype for application observers. |
2635 | */ |
2636 | -typedef void (*upstart_app_launch_app_observer_t) (const gchar * appid, gpointer user_data); |
2637 | +typedef void (*UpstartAppLaunchAppObserver) (const gchar * appid, gpointer user_data); |
2638 | + |
2639 | +/* Backwards compatible. Drop when making API bump. */ |
2640 | +typedef UpstartAppLaunchAppObserver upstart_app_launch_app_observer_t; |
2641 | |
2642 | /** |
2643 | - * upstart_app_launch_app_failed_observer_t: |
2644 | + * UpstartAppLaunchAppFailedObserver: |
2645 | * |
2646 | * Function prototype for application failed observers. |
2647 | */ |
2648 | -typedef void (*upstart_app_launch_app_failed_observer_t) (const gchar * appid, upstart_app_launch_app_failed_t failure_type, gpointer user_data); |
2649 | +typedef void (*UpstartAppLaunchAppFailedObserver) (const gchar * appid, UpstartAppLaunchAppFailed failure_type, gpointer user_data); |
2650 | + |
2651 | +/* Backwards compatible. Drop when making API bump. */ |
2652 | +typedef UpstartAppLaunchAppFailedObserver upstart_app_launch_app_failed_observer_t; |
2653 | |
2654 | |
2655 | /** |
2656 | * upstart_app_launch_start_application: |
2657 | * @appid: ID of the application to launch |
2658 | - * @uris: (allow none): A NULL terminated list of URIs to send to the application |
2659 | + * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the application |
2660 | * |
2661 | * Asks upstart to launch an application. |
2662 | * |
2663 | @@ -81,8 +87,8 @@ |
2664 | |
2665 | /** |
2666 | * upstart_app_launch_observer_add_app_starting: |
2667 | - * @observer: Callback when an application is about to start |
2668 | - * @user_data: (allow none): Data to pass to the observer |
2669 | + * @observer: (scope notified): Callback when an application is about to start |
2670 | + * @user_data: (closure) (allow-none): Data to pass to the observer |
2671 | * |
2672 | * Sets up a callback to get called each time an application |
2673 | * is about to start. The application will not start until the |
2674 | @@ -90,50 +96,50 @@ |
2675 | * |
2676 | * Return value: Whether adding the observer was successful. |
2677 | */ |
2678 | -gboolean upstart_app_launch_observer_add_app_starting (upstart_app_launch_app_observer_t observer, |
2679 | +gboolean upstart_app_launch_observer_add_app_starting (UpstartAppLaunchAppObserver observer, |
2680 | gpointer user_data); |
2681 | /** |
2682 | * upstart_app_launch_observer_add_app_started: |
2683 | - * @observer: Callback when an application started |
2684 | - * @user_data: (allow none): Data to pass to the observer |
2685 | + * @observer: (scope notified): Callback when an application started |
2686 | + * @user_data: (closure) (allow-none): Data to pass to the observer |
2687 | * |
2688 | * Sets up a callback to get called each time an application |
2689 | * has been started. |
2690 | * |
2691 | * Return value: Whether adding the observer was successful. |
2692 | */ |
2693 | -gboolean upstart_app_launch_observer_add_app_started (upstart_app_launch_app_observer_t observer, |
2694 | +gboolean upstart_app_launch_observer_add_app_started (UpstartAppLaunchAppObserver observer, |
2695 | gpointer user_data); |
2696 | /** |
2697 | * upstart_app_launch_observer_add_app_stop: |
2698 | - * @observer: Callback when an application stops |
2699 | - * @user_data: (allow none): Data to pass to the observer |
2700 | + * @observer: (scope notified): Callback when an application stops |
2701 | + * @user_data: (closure) (allow-none): Data to pass to the observer |
2702 | * |
2703 | * Sets up a callback to get called each time an application |
2704 | * stops. |
2705 | * |
2706 | * Return value: Whether adding the observer was successful. |
2707 | */ |
2708 | -gboolean upstart_app_launch_observer_add_app_stop (upstart_app_launch_app_observer_t observer, |
2709 | +gboolean upstart_app_launch_observer_add_app_stop (UpstartAppLaunchAppObserver observer, |
2710 | gpointer user_data); |
2711 | |
2712 | /** |
2713 | * upstart_app_launch_observer_add_app_focus: |
2714 | - * @observer: Callback when an application is started for the second time |
2715 | - * @user_data: (allow none): Data to pass to the observer |
2716 | + * @observer: (scope notified): Callback when an application is started for the second time |
2717 | + * @user_data: (closure) (allow-none): Data to pass to the observer |
2718 | * |
2719 | * Sets up a callback to get called each time an app gets called |
2720 | * that is already running, so we request it to be focused again. |
2721 | * |
2722 | * Return value: Whether adding the observer was successful. |
2723 | */ |
2724 | -gboolean upstart_app_launch_observer_add_app_focus (upstart_app_launch_app_observer_t observer, |
2725 | +gboolean upstart_app_launch_observer_add_app_focus (UpstartAppLaunchAppObserver observer, |
2726 | gpointer user_data); |
2727 | |
2728 | /** |
2729 | * upstart_app_launch_observer_add_app_resume: |
2730 | - * @observer: Callback when an application is started and possibly asleep |
2731 | - * @user_data: (allow none): Data to pass to the observer |
2732 | + * @observer: (scope notified): Callback when an application is started and possibly asleep |
2733 | + * @user_data: (closure) (allow-none): Data to pass to the observer |
2734 | * |
2735 | * Sets up a callback to get called each time an app gets called |
2736 | * that is already running, so we request it to be given CPU time. |
2737 | @@ -141,96 +147,96 @@ |
2738 | * |
2739 | * Return value: Whether adding the observer was successful. |
2740 | */ |
2741 | -gboolean upstart_app_launch_observer_add_app_resume (upstart_app_launch_app_observer_t observer, |
2742 | +gboolean upstart_app_launch_observer_add_app_resume (UpstartAppLaunchAppObserver observer, |
2743 | gpointer user_data); |
2744 | |
2745 | /** |
2746 | * upstart_app_launch_observer_add_app_failed: |
2747 | - * @observer: Callback when an application fails |
2748 | - * @user_data: (allow none): Data to pass to the observer |
2749 | + * @observer: (scope notified): Callback when an application fails |
2750 | + * @user_data: (allow-none) (closure): Data to pass to the observer |
2751 | * |
2752 | * Sets up a callback to get called each time an application |
2753 | * stops via failure. |
2754 | * |
2755 | * Return value: Whether adding the observer was successful. |
2756 | */ |
2757 | -gboolean upstart_app_launch_observer_add_app_failed (upstart_app_launch_app_failed_observer_t observer, |
2758 | - gpointer user_data); |
2759 | +gboolean upstart_app_launch_observer_add_app_failed (UpstartAppLaunchAppFailedObserver observer, |
2760 | + gpointer user_data); |
2761 | |
2762 | /** |
2763 | * upstart_app_launch_observer_delete_app_starting: |
2764 | - * @observer: Callback to remove |
2765 | - * @user_data: (allow none): Data that was passed to the observer |
2766 | + * @observer: (scope notified): Callback to remove |
2767 | + * @user_data: (closure) (allow-none): Data that was passed to the observer |
2768 | * |
2769 | * Removes a previously registered callback to ensure it no longer |
2770 | * gets signaled. |
2771 | * |
2772 | * Return value: Whether deleting the observer was successful. |
2773 | */ |
2774 | -gboolean upstart_app_launch_observer_delete_app_starting (upstart_app_launch_app_observer_t observer, |
2775 | +gboolean upstart_app_launch_observer_delete_app_starting (UpstartAppLaunchAppObserver observer, |
2776 | gpointer user_data); |
2777 | /** |
2778 | * upstart_app_launch_observer_delete_app_started: |
2779 | - * @observer: Callback to remove |
2780 | - * @user_data: (allow none): Data that was passed to the observer |
2781 | + * @observer: (scope notified): Callback to remove |
2782 | + * @user_data: (closure) (allow-none): Data that was passed to the observer |
2783 | * |
2784 | * Removes a previously registered callback to ensure it no longer |
2785 | * gets signaled. |
2786 | * |
2787 | * Return value: Whether deleting the observer was successful. |
2788 | */ |
2789 | -gboolean upstart_app_launch_observer_delete_app_started (upstart_app_launch_app_observer_t observer, |
2790 | +gboolean upstart_app_launch_observer_delete_app_started (UpstartAppLaunchAppObserver observer, |
2791 | gpointer user_data); |
2792 | /** |
2793 | * upstart_app_launch_observer_delete_app_stop: |
2794 | - * @observer: Callback to remove |
2795 | - * @user_data: (allow none): Data that was passed to the observer |
2796 | + * @observer: (scope notified): Callback to remove |
2797 | + * @user_data: (closure) (allow-none): Data that was passed to the observer |
2798 | * |
2799 | * Removes a previously registered callback to ensure it no longer |
2800 | * gets signaled. |
2801 | * |
2802 | * Return value: Whether deleting the observer was successful. |
2803 | */ |
2804 | -gboolean upstart_app_launch_observer_delete_app_stop (upstart_app_launch_app_observer_t observer, |
2805 | +gboolean upstart_app_launch_observer_delete_app_stop (UpstartAppLaunchAppObserver observer, |
2806 | gpointer user_data); |
2807 | |
2808 | /** |
2809 | * upstart_app_launch_observer_delete_app_focus: |
2810 | - * @observer: Callback to remove |
2811 | - * @user_data: (allow none): Data that was passed to the observer |
2812 | + * @observer: (scope notified): Callback to remove |
2813 | + * @user_data: (closure) (allow-none): Data that was passed to the observer |
2814 | * |
2815 | * Removes a previously registered callback to ensure it no longer |
2816 | * gets signaled. |
2817 | * |
2818 | * Return value: Whether deleting the observer was successful. |
2819 | */ |
2820 | -gboolean upstart_app_launch_observer_delete_app_focus (upstart_app_launch_app_observer_t observer, |
2821 | +gboolean upstart_app_launch_observer_delete_app_focus (UpstartAppLaunchAppObserver observer, |
2822 | gpointer user_data); |
2823 | |
2824 | /** |
2825 | * upstart_app_launch_observer_delete_app_resume: |
2826 | - * @observer: Callback to remove |
2827 | - * @user_data: (allow none): Data that was passed to the observer |
2828 | + * @observer: (scope notified): Callback to remove |
2829 | + * @user_data: (closure) (allow-none): Data that was passed to the observer |
2830 | * |
2831 | * Removes a previously registered callback to ensure it no longer |
2832 | * gets signaled. |
2833 | * |
2834 | * Return value: Whether deleting the observer was successful. |
2835 | */ |
2836 | -gboolean upstart_app_launch_observer_delete_app_resume (upstart_app_launch_app_observer_t observer, |
2837 | +gboolean upstart_app_launch_observer_delete_app_resume (UpstartAppLaunchAppObserver observer, |
2838 | gpointer user_data); |
2839 | |
2840 | /** |
2841 | * upstart_app_launch_observer_delete_app_failed: |
2842 | - * @observer: Callback to remove |
2843 | - * @user_data: (allow none): Data to pass to the observer |
2844 | + * @observer: (scope notified): Callback to remove |
2845 | + * @user_data: (closure) (allow-none): Data to pass to the observer |
2846 | * |
2847 | * Removes a previously registered callback to ensure it no longer |
2848 | * gets signaled. |
2849 | * |
2850 | * Return value: Whether deleting the observer was successful. |
2851 | */ |
2852 | -gboolean upstart_app_launch_observer_delete_app_failed (upstart_app_launch_app_failed_observer_t observer, |
2853 | +gboolean upstart_app_launch_observer_delete_app_failed (UpstartAppLaunchAppFailedObserver observer, |
2854 | gpointer user_data); |
2855 | /** |
2856 | * upstart_app_launch_list_running_apps: |
2857 | |
2858 | === removed file 'second-exec-trace.tp' |
2859 | --- second-exec-trace.tp 2013-12-04 17:32:23 +0000 |
2860 | +++ second-exec-trace.tp 1970-01-01 00:00:00 +0000 |
2861 | @@ -1,16 +0,0 @@ |
2862 | - |
2863 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_start, TP_ARGS(0), TP_FIELDS()) |
2864 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_resume, TP_ARGS(0), TP_FIELDS()) |
2865 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_complete, TP_ARGS(0), TP_FIELDS()) |
2866 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_resume_timeout, TP_ARGS(0), TP_FIELDS()) |
2867 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_emit_focus, TP_ARGS(0), TP_FIELDS()) |
2868 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_finish, TP_ARGS(0), TP_FIELDS()) |
2869 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_dbus_names, TP_ARGS(0), TP_FIELDS()) |
2870 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_primary_pid, TP_ARGS(0), TP_FIELDS()) |
2871 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_request_pid, TP_ARGS(0), TP_FIELDS()) |
2872 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_got_pid, TP_ARGS(0), TP_FIELDS()) |
2873 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_contact_app, TP_ARGS(0), TP_FIELDS()) |
2874 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_contacted, TP_ARGS(0), TP_FIELDS()) |
2875 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_app_error, TP_ARGS(0), TP_FIELDS()) |
2876 | -TRACEPOINT_EVENT(upstart_app_launch, second_exec_connection_complete, TP_ARGS(0), TP_FIELDS()) |
2877 | - |
2878 | |
2879 | === removed file 'second-exec.c' |
2880 | --- second-exec.c 2013-12-05 17:08:13 +0000 |
2881 | +++ second-exec.c 1970-01-01 00:00:00 +0000 |
2882 | @@ -1,40 +0,0 @@ |
2883 | -/* |
2884 | - * Copyright 2013 Canonical Ltd. |
2885 | - * |
2886 | - * This program is free software: you can redistribute it and/or modify it |
2887 | - * under the terms of the GNU General Public License version 3, as published |
2888 | - * by the Free Software Foundation. |
2889 | - * |
2890 | - * This program is distributed in the hope that it will be useful, but |
2891 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
2892 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
2893 | - * PURPOSE. See the GNU General Public License for more details. |
2894 | - * |
2895 | - * You should have received a copy of the GNU General Public License along |
2896 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
2897 | - * |
2898 | - * Authors: |
2899 | - * Ted Gould <ted.gould@canonical.com> |
2900 | - */ |
2901 | - |
2902 | -#include "second-exec-core.h" |
2903 | - |
2904 | -int |
2905 | -main (int argc, char * argv[]) |
2906 | -{ |
2907 | - if (argc != 1) { |
2908 | - g_error("Should be called as: %s", argv[0]); |
2909 | - return 1; |
2910 | - } |
2911 | - |
2912 | - const gchar * appid = g_getenv("APP_ID"); |
2913 | - const gchar * appuris = g_getenv("APP_URIS"); |
2914 | - |
2915 | - g_setenv("LTTNG_UST_REGISTER_TIMEOUT", "0", FALSE); /* Set to zero if not set */ |
2916 | - |
2917 | - if (second_exec(appid, appuris)) { |
2918 | - return 0; |
2919 | - } else { |
2920 | - return 1; |
2921 | - } |
2922 | -} |
2923 | |
2924 | === modified file 'tests/CMakeLists.txt' |
2925 | --- tests/CMakeLists.txt 2014-01-13 15:16:24 +0000 |
2926 | +++ tests/CMakeLists.txt 2014-02-11 03:28:22 +0000 |
2927 | @@ -25,16 +25,6 @@ |
2928 | |
2929 | add_test (helper-handshake-test helper-handshake-test) |
2930 | |
2931 | -# Second Exec Test |
2932 | - |
2933 | -include_directories("${CMAKE_SOURCE_DIR}/libupstart-app-launch") |
2934 | - |
2935 | -add_executable (second-exec-test |
2936 | - second-exec-test.cc |
2937 | - upstart-app-launch-mock.c) |
2938 | -target_link_libraries (second-exec-test helpers gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} upstart-launcher second-exec-core) |
2939 | -add_test (second-exec-test second-exec-test) |
2940 | - |
2941 | # libUAL Test |
2942 | |
2943 | include_directories("${CMAKE_SOURCE_DIR}/libupstart-app-launch") |
2944 | @@ -43,14 +33,16 @@ |
2945 | libual-test.cc) |
2946 | target_link_libraries (libual-test helpers gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} upstart-launcher) |
2947 | |
2948 | -# NOTE: Tests are broken into individual runs to avoid problems with libdbus |
2949 | -add_test (NAME libual-test-start COMMAND libual-test --gtest_filter=*StartApplication) |
2950 | -add_test (NAME libual-test-stop COMMAND libual-test --gtest_filter=*StopApplication) |
2951 | -add_test (NAME libual-test-pid COMMAND libual-test --gtest_filter=*ApplicationPid) |
2952 | -add_test (NAME libual-test-app-id COMMAND libual-test --gtest_filter=*ApplicationId) |
2953 | -add_test (NAME libual-test-list COMMAND libual-test --gtest_filter=*ApplicationList) |
2954 | -add_test (NAME libual-test-observer COMMAND libual-test --gtest_filter=*StartStopObserver) |
2955 | -add_test (NAME libual-test-starting COMMAND libual-test --gtest_filter=*StartingResponses) |
2956 | +add_test (NAME libual-test COMMAND libual-test) |
2957 | + |
2958 | +# Failure Test |
2959 | + |
2960 | +add_definitions ( -DAPP_FAILED_TOOL="${CMAKE_BINARY_DIR}/application-failed" ) |
2961 | + |
2962 | +add_executable (failure-test |
2963 | + failure-test.cc) |
2964 | +target_link_libraries (failure-test gtest ${GTEST_LIBS} upstart-launcher) |
2965 | +add_test (failure-test failure-test) |
2966 | |
2967 | # ZG Test |
2968 | |
2969 | |
2970 | === added file 'tests/applications/multiple.desktop' |
2971 | --- tests/applications/multiple.desktop 1970-01-01 00:00:00 +0000 |
2972 | +++ tests/applications/multiple.desktop 2014-02-11 03:28:22 +0000 |
2973 | @@ -0,0 +1,8 @@ |
2974 | +[Desktop Entry] |
2975 | +Name=Multiple |
2976 | +Type=Application |
2977 | +Exec=multiple |
2978 | +NoDisplay=false |
2979 | +Hidden=false |
2980 | +Terminal=false |
2981 | +X-Ubuntu-Single-Instance=false |
2982 | |
2983 | === added file 'tests/applications/single.desktop' |
2984 | --- tests/applications/single.desktop 1970-01-01 00:00:00 +0000 |
2985 | +++ tests/applications/single.desktop 2014-02-11 03:28:22 +0000 |
2986 | @@ -0,0 +1,8 @@ |
2987 | +[Desktop Entry] |
2988 | +Name=Single |
2989 | +Type=Application |
2990 | +Exec=single |
2991 | +NoDisplay=false |
2992 | +Hidden=false |
2993 | +Terminal=false |
2994 | +X-Ubuntu-Single-Instance=true |
2995 | |
2996 | === added file 'tests/failure-test.cc' |
2997 | --- tests/failure-test.cc 1970-01-01 00:00:00 +0000 |
2998 | +++ tests/failure-test.cc 2014-02-11 03:28:22 +0000 |
2999 | @@ -0,0 +1,151 @@ |
3000 | +/* |
3001 | + * Copyright 2013 Canonical Ltd. |
3002 | + * |
3003 | + * This program is free software: you can redistribute it and/or modify it |
3004 | + * under the terms of the GNU General Public License version 3, as published |
3005 | + * by the Free Software Foundation. |
3006 | + * |
3007 | + * This program is distributed in the hope that it will be useful, but |
3008 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
3009 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3010 | + * PURPOSE. See the GNU General Public License for more details. |
3011 | + * |
3012 | + * You should have received a copy of the GNU General Public License along |
3013 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
3014 | + * |
3015 | + * Authors: |
3016 | + * Ted Gould <ted.gould@canonical.com> |
3017 | + */ |
3018 | + |
3019 | +#include <gtest/gtest.h> |
3020 | +#include <glib/gstdio.h> |
3021 | +#include <gio/gio.h> |
3022 | +#include <upstart-app-launch.h> |
3023 | + |
3024 | +class FailureTest : public ::testing::Test |
3025 | +{ |
3026 | + private: |
3027 | + GTestDBus * testbus = NULL; |
3028 | + |
3029 | + protected: |
3030 | + virtual void SetUp() { |
3031 | + testbus = g_test_dbus_new(G_TEST_DBUS_NONE); |
3032 | + g_test_dbus_up(testbus); |
3033 | + } |
3034 | + |
3035 | + virtual void TearDown() { |
3036 | + g_test_dbus_down(testbus); |
3037 | + g_clear_object(&testbus); |
3038 | + return; |
3039 | + } |
3040 | + |
3041 | + static gboolean pause_helper (gpointer pmainloop) { |
3042 | + g_main_loop_quit(static_cast<GMainLoop *>(pmainloop)); |
3043 | + return G_SOURCE_REMOVE; |
3044 | + } |
3045 | + |
3046 | + void pause (guint time) { |
3047 | + if (time > 0) { |
3048 | + GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
3049 | + g_timeout_add(time, pause_helper, mainloop); |
3050 | + |
3051 | + g_main_loop_run(mainloop); |
3052 | + |
3053 | + g_main_loop_unref(mainloop); |
3054 | + } |
3055 | + |
3056 | + while (g_main_pending()) { |
3057 | + g_main_iteration(TRUE); |
3058 | + } |
3059 | + } |
3060 | +}; |
3061 | + |
3062 | +static void |
3063 | +failed_observer (const gchar * appid, upstart_app_launch_app_failed_t reason, gpointer user_data) |
3064 | +{ |
3065 | + if (reason == UPSTART_APP_LAUNCH_APP_FAILED_CRASH) { |
3066 | + std::string * last = static_cast<std::string *>(user_data); |
3067 | + *last = appid; |
3068 | + } |
3069 | + return; |
3070 | +} |
3071 | + |
3072 | +TEST_F(FailureTest, CrashTest) |
3073 | +{ |
3074 | + g_setenv("EXIT_STATUS", "-100", TRUE); |
3075 | + g_setenv("JOB", "application-click", TRUE); |
3076 | + g_setenv("INSTANCE", "foo", TRUE); |
3077 | + |
3078 | + std::string last_observer; |
3079 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_failed(failed_observer, &last_observer)); |
3080 | + |
3081 | + /* Status based */ |
3082 | + ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3083 | + pause(100); |
3084 | + |
3085 | + EXPECT_EQ("foo", last_observer); |
3086 | + |
3087 | + last_observer.clear(); |
3088 | + g_unsetenv("EXIT_STATUS"); |
3089 | + g_setenv("EXIT_SIGNAL", "KILL", TRUE); |
3090 | + |
3091 | + /* Signal based */ |
3092 | + ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3093 | + pause(100); |
3094 | + |
3095 | + EXPECT_EQ("foo", last_observer); |
3096 | + |
3097 | + ASSERT_TRUE(upstart_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); |
3098 | + |
3099 | + return; |
3100 | +} |
3101 | + |
3102 | +TEST_F(FailureTest, LegacyTest) |
3103 | +{ |
3104 | + g_setenv("EXIT_STATUS", "-100", TRUE); |
3105 | + g_setenv("JOB", "application-legacy", TRUE); |
3106 | + g_setenv("INSTANCE", "foo-1234", TRUE); |
3107 | + |
3108 | + std::string last_observer; |
3109 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_failed(failed_observer, &last_observer)); |
3110 | + |
3111 | + /* Status based */ |
3112 | + ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3113 | + pause(100); |
3114 | + |
3115 | + EXPECT_EQ("foo", last_observer); |
3116 | + |
3117 | + ASSERT_TRUE(upstart_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); |
3118 | + |
3119 | + return; |
3120 | +} |
3121 | + |
3122 | +static void |
3123 | +failed_start_observer (const gchar * appid, upstart_app_launch_app_failed_t reason, gpointer user_data) |
3124 | +{ |
3125 | + if (reason == UPSTART_APP_LAUNCH_APP_FAILED_START_FAILURE) { |
3126 | + std::string * last = static_cast<std::string *>(user_data); |
3127 | + *last = appid; |
3128 | + } |
3129 | + return; |
3130 | +} |
3131 | + |
3132 | +TEST_F(FailureTest, StartTest) |
3133 | +{ |
3134 | + g_setenv("JOB", "application-click", TRUE); |
3135 | + g_setenv("INSTANCE", "foo", TRUE); |
3136 | + g_unsetenv("EXIT_STATUS"); |
3137 | + g_unsetenv("EXIT_SIGNAL"); |
3138 | + |
3139 | + std::string last_observer; |
3140 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_failed(failed_start_observer, &last_observer)); |
3141 | + |
3142 | + ASSERT_TRUE(g_spawn_command_line_sync(APP_FAILED_TOOL, NULL, NULL, NULL, NULL)); |
3143 | + pause(100); |
3144 | + |
3145 | + EXPECT_EQ("foo", last_observer); |
3146 | + |
3147 | + ASSERT_TRUE(upstart_app_launch_observer_delete_app_failed(failed_start_observer, &last_observer)); |
3148 | + |
3149 | + return; |
3150 | +} |
3151 | |
3152 | === modified file 'tests/libual-test.cc' |
3153 | --- tests/libual-test.cc 2014-01-29 02:24:06 +0000 |
3154 | +++ tests/libual-test.cc 2014-02-11 03:28:22 +0000 |
3155 | @@ -31,6 +31,26 @@ |
3156 | DbusTestService * service = NULL; |
3157 | DbusTestDbusMock * mock = NULL; |
3158 | GDBusConnection * bus = NULL; |
3159 | + std::string last_focus_appid; |
3160 | + std::string last_resume_appid; |
3161 | + guint resume_timeout = 0; |
3162 | + |
3163 | + private: |
3164 | + static void focus_cb (const gchar * appid, gpointer user_data) { |
3165 | + g_debug("Focus Callback: %s", appid); |
3166 | + LibUAL * _this = static_cast<LibUAL *>(user_data); |
3167 | + _this->last_focus_appid = appid; |
3168 | + } |
3169 | + |
3170 | + static void resume_cb (const gchar * appid, gpointer user_data) { |
3171 | + g_debug("Resume Callback: %s", appid); |
3172 | + LibUAL * _this = static_cast<LibUAL *>(user_data); |
3173 | + _this->last_resume_appid = appid; |
3174 | + |
3175 | + if (_this->resume_timeout > 0) { |
3176 | + _this->pause(_this->resume_timeout); |
3177 | + } |
3178 | + } |
3179 | |
3180 | protected: |
3181 | /* Useful debugging stuff, but not on by default. You really want to |
3182 | @@ -48,6 +68,12 @@ |
3183 | } |
3184 | |
3185 | virtual void SetUp() { |
3186 | + gchar * linkfarmpath = g_build_filename(CMAKE_SOURCE_DIR, "link-farm", NULL); |
3187 | + g_setenv("UPSTART_APP_LAUNCH_LINK_FARM", linkfarmpath, TRUE); |
3188 | + g_free(linkfarmpath); |
3189 | + |
3190 | + g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
3191 | + |
3192 | service = dbus_test_service_new(NULL); |
3193 | g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
3194 | const gchar * oldpath = g_getenv("PATH"); |
3195 | @@ -81,6 +107,14 @@ |
3196 | DbusTestDbusMockObject * jobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
3197 | |
3198 | dbus_test_dbus_mock_object_add_method(mock, jobobj, |
3199 | + "Start", |
3200 | + G_VARIANT_TYPE("(asb)"), |
3201 | + NULL, |
3202 | + "if args[0][0] == 'APP_ID=foo':" |
3203 | + " raise dbus.exceptions.DBusException('Foo running', name='com.ubuntu.Upstart0_6.Error.AlreadyStarted')", |
3204 | + NULL); |
3205 | + |
3206 | + dbus_test_dbus_mock_object_add_method(mock, jobobj, |
3207 | "Stop", |
3208 | G_VARIANT_TYPE("(asb)"), |
3209 | NULL, |
3210 | @@ -100,15 +134,24 @@ |
3211 | G_VARIANT_TYPE_STRING, |
3212 | g_variant_new_string("foo"), |
3213 | NULL); |
3214 | + gchar * process_var = g_strdup_printf("[('main', %d)]", getpid()); |
3215 | dbus_test_dbus_mock_object_add_property(mock, instobj, |
3216 | "processes", |
3217 | G_VARIANT_TYPE("a(si)"), |
3218 | - g_variant_new_parsed("[('main', 1234)]"), |
3219 | + g_variant_new_parsed(process_var), |
3220 | NULL); |
3221 | + g_free(process_var); |
3222 | |
3223 | DbusTestDbusMockObject * ljobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
3224 | |
3225 | dbus_test_dbus_mock_object_add_method(mock, ljobobj, |
3226 | + "Start", |
3227 | + G_VARIANT_TYPE("(asb)"), |
3228 | + NULL, |
3229 | + "", |
3230 | + NULL); |
3231 | + |
3232 | + dbus_test_dbus_mock_object_add_method(mock, ljobobj, |
3233 | "Stop", |
3234 | G_VARIANT_TYPE("(asb)"), |
3235 | NULL, |
3236 | @@ -140,9 +183,15 @@ |
3237 | bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3238 | g_dbus_connection_set_exit_on_close(bus, FALSE); |
3239 | g_object_add_weak_pointer(G_OBJECT(bus), (gpointer *)&bus); |
3240 | + |
3241 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_focus(focus_cb, this)); |
3242 | + ASSERT_TRUE(upstart_app_launch_observer_add_app_resume(resume_cb, this)); |
3243 | } |
3244 | |
3245 | virtual void TearDown() { |
3246 | + upstart_app_launch_observer_delete_app_focus(focus_cb, this); |
3247 | + upstart_app_launch_observer_delete_app_resume(resume_cb, this); |
3248 | + |
3249 | g_clear_object(&mock); |
3250 | g_clear_object(&service); |
3251 | |
3252 | @@ -150,12 +199,10 @@ |
3253 | |
3254 | unsigned int cleartry = 0; |
3255 | while (bus != NULL && cleartry < 100) { |
3256 | - g_usleep(100000); |
3257 | - while (g_main_pending()) { |
3258 | - g_main_iteration(TRUE); |
3259 | - } |
3260 | + pause(100); |
3261 | cleartry++; |
3262 | } |
3263 | + ASSERT_EQ(bus, nullptr); |
3264 | } |
3265 | |
3266 | bool check_env (GVariant * env_array, const gchar * var, const gchar * value) { |
3267 | @@ -189,18 +236,17 @@ |
3268 | } |
3269 | |
3270 | static gboolean pause_helper (gpointer pmainloop) { |
3271 | - g_main_loop_quit((GMainLoop *)pmainloop); |
3272 | + g_main_loop_quit(static_cast<GMainLoop *>(pmainloop)); |
3273 | return G_SOURCE_REMOVE; |
3274 | } |
3275 | |
3276 | void pause (guint time) { |
3277 | if (time > 0) { |
3278 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
3279 | - guint timer = g_timeout_add(time, pause_helper, mainloop); |
3280 | + g_timeout_add(time, pause_helper, mainloop); |
3281 | |
3282 | g_main_loop_run(mainloop); |
3283 | |
3284 | - g_source_remove(timer); |
3285 | g_main_loop_unref(mainloop); |
3286 | } |
3287 | |
3288 | @@ -212,35 +258,31 @@ |
3289 | |
3290 | TEST_F(LibUAL, StartApplication) |
3291 | { |
3292 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
3293 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
3294 | |
3295 | /* Basic make sure we can send the event */ |
3296 | - ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
3297 | - ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "EmitEvent", NULL, NULL), 1); |
3298 | + ASSERT_TRUE(upstart_app_launch_start_application("foolike", NULL)); |
3299 | + EXPECT_EQ(1, dbus_test_dbus_mock_object_check_method_call(mock, obj, "Start", NULL, NULL)); |
3300 | |
3301 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
3302 | |
3303 | /* Now look at the details of the call */ |
3304 | - ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
3305 | + ASSERT_TRUE(upstart_app_launch_start_application("foolike", NULL)); |
3306 | |
3307 | guint len = 0; |
3308 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "EmitEvent", &len, NULL); |
3309 | - ASSERT_NE(calls, nullptr); |
3310 | - ASSERT_EQ(len, 1); |
3311 | - |
3312 | - ASSERT_STREQ(calls->name, "EmitEvent"); |
3313 | - ASSERT_EQ(g_variant_n_children(calls->params), 3); |
3314 | - |
3315 | - GVariant * name = g_variant_get_child_value(calls->params, 0); |
3316 | - ASSERT_STREQ(g_variant_get_string(name, NULL), "application-start"); |
3317 | - g_variant_unref(name); |
3318 | - |
3319 | - GVariant * block = g_variant_get_child_value(calls->params, 2); |
3320 | - ASSERT_FALSE(g_variant_get_boolean(block)); |
3321 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
3322 | + EXPECT_NE(nullptr, calls); |
3323 | + EXPECT_EQ(1, len); |
3324 | + |
3325 | + EXPECT_STREQ("Start", calls->name); |
3326 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
3327 | + |
3328 | + GVariant * block = g_variant_get_child_value(calls->params, 1); |
3329 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
3330 | g_variant_unref(block); |
3331 | |
3332 | - GVariant * env = g_variant_get_child_value(calls->params, 1); |
3333 | - ASSERT_TRUE(check_env(env, "APP_ID", "foo")); |
3334 | + GVariant * env = g_variant_get_child_value(calls->params, 0); |
3335 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
3336 | g_variant_unref(env); |
3337 | |
3338 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
3339 | @@ -252,16 +294,16 @@ |
3340 | "file:///home/phablet/test.txt", |
3341 | NULL |
3342 | }; |
3343 | - ASSERT_TRUE(upstart_app_launch_start_application("foo", urls)); |
3344 | + ASSERT_TRUE(upstart_app_launch_start_application("foolike", urls)); |
3345 | |
3346 | len = 0; |
3347 | - calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "EmitEvent", &len, NULL); |
3348 | - ASSERT_NE(calls, nullptr); |
3349 | - ASSERT_EQ(len, 1); |
3350 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
3351 | + EXPECT_NE(nullptr, calls); |
3352 | + EXPECT_EQ(1, len); |
3353 | |
3354 | - env = g_variant_get_child_value(calls->params, 1); |
3355 | - ASSERT_TRUE(check_env(env, "APP_ID", "foo")); |
3356 | - ASSERT_TRUE(check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
3357 | + env = g_variant_get_child_value(calls->params, 0); |
3358 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
3359 | + EXPECT_TRUE(check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
3360 | g_variant_unref(env); |
3361 | |
3362 | return; |
3363 | @@ -279,10 +321,10 @@ |
3364 | |
3365 | TEST_F(LibUAL, ApplicationPid) |
3366 | { |
3367 | - ASSERT_EQ(upstart_app_launch_get_primary_pid("foo"), 1234); |
3368 | - ASSERT_EQ(upstart_app_launch_get_primary_pid("bar"), 5678); |
3369 | - ASSERT_TRUE(upstart_app_launch_pid_in_app_id(1234, "foo")); |
3370 | - ASSERT_FALSE(upstart_app_launch_pid_in_app_id(5678, "foo")); |
3371 | + EXPECT_EQ(upstart_app_launch_get_primary_pid("foo"), getpid()); |
3372 | + EXPECT_EQ(upstart_app_launch_get_primary_pid("bar"), 5678); |
3373 | + EXPECT_TRUE(upstart_app_launch_pid_in_app_id(getpid(), "foo")); |
3374 | + EXPECT_FALSE(upstart_app_launch_pid_in_app_id(5678, "foo")); |
3375 | } |
3376 | |
3377 | TEST_F(LibUAL, ApplicationId) |
3378 | @@ -363,7 +405,6 @@ |
3379 | |
3380 | ASSERT_TRUE(upstart_app_launch_observer_add_app_started(observer_cb, &start_data)); |
3381 | ASSERT_TRUE(upstart_app_launch_observer_add_app_stop(observer_cb, &stop_data)); |
3382 | - ASSERT_FALSE(upstart_app_launch_observer_add_app_failed(NULL, NULL)); /* Not yet implemented */ |
3383 | |
3384 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
3385 | |
3386 | @@ -473,7 +514,6 @@ |
3387 | /* Remove */ |
3388 | ASSERT_TRUE(upstart_app_launch_observer_delete_app_started(observer_cb, &start_data)); |
3389 | ASSERT_TRUE(upstart_app_launch_observer_delete_app_stop(observer_cb, &stop_data)); |
3390 | - ASSERT_FALSE(upstart_app_launch_observer_delete_app_failed(NULL, NULL)); /* Not yet implemented */ |
3391 | } |
3392 | |
3393 | static GDBusMessage * |
3394 | @@ -527,3 +567,241 @@ |
3395 | g_dbus_connection_remove_filter(session, filter); |
3396 | g_object_unref(session); |
3397 | } |
3398 | + |
3399 | +TEST_F(LibUAL, AppIdTest) |
3400 | +{ |
3401 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
3402 | + pause(50); /* Ensure all the events come through */ |
3403 | + EXPECT_EQ("foo", this->last_focus_appid); |
3404 | + EXPECT_EQ("foo", this->last_resume_appid); |
3405 | +} |
3406 | + |
3407 | +GDBusMessage * |
3408 | +filter_func_good (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
3409 | +{ |
3410 | + if (!incomming) { |
3411 | + return message; |
3412 | + } |
3413 | + |
3414 | + if (g_strcmp0(g_dbus_message_get_path(message), (gchar *)user_data) == 0) { |
3415 | + GDBusMessage * reply = g_dbus_message_new_method_reply(message); |
3416 | + g_dbus_connection_send_message(conn, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); |
3417 | + g_object_unref(message); |
3418 | + return NULL; |
3419 | + } |
3420 | + |
3421 | + return message; |
3422 | +} |
3423 | + |
3424 | +TEST_F(LibUAL, UrlSendTest) |
3425 | +{ |
3426 | + GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3427 | + guint filter = g_dbus_connection_add_filter(session, |
3428 | + filter_func_good, |
3429 | + (gpointer)"/foo", |
3430 | + NULL); |
3431 | + |
3432 | + const gchar * uris[] = { |
3433 | + "http://www.test.com", |
3434 | + NULL |
3435 | + }; |
3436 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
3437 | + pause(100); /* Ensure all the events come through */ |
3438 | + |
3439 | + EXPECT_EQ("foo", this->last_focus_appid); |
3440 | + EXPECT_EQ("foo", this->last_resume_appid); |
3441 | + |
3442 | + g_dbus_connection_remove_filter(session, filter); |
3443 | + g_object_unref(session); |
3444 | +} |
3445 | + |
3446 | +TEST_F(LibUAL, UrlSendNoObjectTest) |
3447 | +{ |
3448 | + const gchar * uris[] = { |
3449 | + "http://www.test.com", |
3450 | + NULL |
3451 | + }; |
3452 | + |
3453 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
3454 | + pause(100); /* Ensure all the events come through */ |
3455 | + |
3456 | + EXPECT_EQ("foo", this->last_focus_appid); |
3457 | + EXPECT_EQ("foo", this->last_resume_appid); |
3458 | +} |
3459 | + |
3460 | +TEST_F(LibUAL, UnityTimeoutTest) |
3461 | +{ |
3462 | + this->resume_timeout = 100; |
3463 | + |
3464 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", NULL)); |
3465 | + pause(1000); /* Ensure all the events come through */ |
3466 | + EXPECT_EQ("foo", this->last_focus_appid); |
3467 | + EXPECT_EQ("foo", this->last_resume_appid); |
3468 | +} |
3469 | + |
3470 | +TEST_F(LibUAL, UnityTimeoutUriTest) |
3471 | +{ |
3472 | + this->resume_timeout = 200; |
3473 | + |
3474 | + const gchar * uris[] = { |
3475 | + "http://www.test.com", |
3476 | + NULL |
3477 | + }; |
3478 | + |
3479 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
3480 | + pause(1000); /* Ensure all the events come through */ |
3481 | + EXPECT_EQ("foo", this->last_focus_appid); |
3482 | + EXPECT_EQ("foo", this->last_resume_appid); |
3483 | +} |
3484 | + |
3485 | +GDBusMessage * |
3486 | +filter_respawn (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
3487 | +{ |
3488 | + if (g_strcmp0(g_dbus_message_get_member(message), "UnityResumeResponse") == 0) { |
3489 | + g_object_unref(message); |
3490 | + return NULL; |
3491 | + } |
3492 | + |
3493 | + return message; |
3494 | +} |
3495 | + |
3496 | +TEST_F(LibUAL, UnityLostTest) |
3497 | +{ |
3498 | + GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3499 | + guint filter = g_dbus_connection_add_filter(session, |
3500 | + filter_respawn, |
3501 | + NULL, |
3502 | + NULL); |
3503 | + |
3504 | + guint start = g_get_monotonic_time(); |
3505 | + |
3506 | + const gchar * uris[] = { |
3507 | + "http://www.test.com", |
3508 | + NULL |
3509 | + }; |
3510 | + |
3511 | + ASSERT_TRUE(upstart_app_launch_start_application("foo", uris)); |
3512 | + |
3513 | + guint end = g_get_monotonic_time(); |
3514 | + |
3515 | + EXPECT_LT(end - start, 600 * 1000); |
3516 | + |
3517 | + pause(1000); /* Ensure all the events come through */ |
3518 | + |
3519 | + EXPECT_EQ("foo", this->last_focus_appid); |
3520 | + EXPECT_EQ("foo", this->last_resume_appid); |
3521 | + |
3522 | + g_dbus_connection_remove_filter(session, filter); |
3523 | + g_object_unref(session); |
3524 | +} |
3525 | + |
3526 | + |
3527 | +TEST_F(LibUAL, LegacySingleInstance) |
3528 | +{ |
3529 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
3530 | + |
3531 | + /* Check for a single-instance app */ |
3532 | + ASSERT_TRUE(upstart_app_launch_start_application("single", NULL)); |
3533 | + |
3534 | + guint len = 0; |
3535 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
3536 | + EXPECT_NE(nullptr, calls); |
3537 | + EXPECT_EQ(1, len); |
3538 | + |
3539 | + EXPECT_STREQ("Start", calls->name); |
3540 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
3541 | + |
3542 | + GVariant * block = g_variant_get_child_value(calls->params, 1); |
3543 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
3544 | + g_variant_unref(block); |
3545 | + |
3546 | + GVariant * env = g_variant_get_child_value(calls->params, 0); |
3547 | + EXPECT_TRUE(check_env(env, "APP_ID", "single")); |
3548 | + EXPECT_TRUE(check_env(env, "INSTANCE_ID", "")); |
3549 | + g_variant_unref(env); |
3550 | + |
3551 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
3552 | + |
3553 | + /* Check for a multi-instance app */ |
3554 | + ASSERT_TRUE(upstart_app_launch_start_application("multiple", NULL)); |
3555 | + |
3556 | + len = 0; |
3557 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
3558 | + EXPECT_NE(nullptr, calls); |
3559 | + EXPECT_EQ(1, len); |
3560 | + |
3561 | + EXPECT_STREQ("Start", calls->name); |
3562 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
3563 | + |
3564 | + block = g_variant_get_child_value(calls->params, 1); |
3565 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
3566 | + g_variant_unref(block); |
3567 | + |
3568 | + env = g_variant_get_child_value(calls->params, 0); |
3569 | + EXPECT_TRUE(check_env(env, "APP_ID", "multiple")); |
3570 | + EXPECT_FALSE(check_env(env, "INSTANCE_ID", "")); |
3571 | + g_variant_unref(env); |
3572 | +} |
3573 | + |
3574 | +static void |
3575 | +failed_observer (const gchar * appid, upstart_app_launch_app_failed_t reason, gpointer user_data) |
3576 | +{ |
3577 | + if (reason == UPSTART_APP_LAUNCH_APP_FAILED_CRASH) { |
3578 | + std::string * last = static_cast<std::string *>(user_data); |
3579 | + *last = appid; |
3580 | + } |
3581 | + return; |
3582 | +} |
3583 | + |
3584 | +TEST_F(LibUAL, FailingObserver) |
3585 | +{ |
3586 | + std::string last_observer; |
3587 | + GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3588 | + |
3589 | + EXPECT_TRUE(upstart_app_launch_observer_add_app_failed(failed_observer, &last_observer)); |
3590 | + |
3591 | + g_dbus_connection_emit_signal(session, |
3592 | + NULL, /* destination */ |
3593 | + "/", /* path */ |
3594 | + "com.canonical.UpstartAppLaunch", /* interface */ |
3595 | + "ApplicationFailed", /* signal */ |
3596 | + g_variant_new("(ss)", "foo", "crash"), /* params, the same */ |
3597 | + NULL); |
3598 | + |
3599 | + pause(100); |
3600 | + |
3601 | + EXPECT_EQ("foo", last_observer); |
3602 | + |
3603 | + last_observer.clear(); |
3604 | + |
3605 | + g_dbus_connection_emit_signal(session, |
3606 | + NULL, /* destination */ |
3607 | + "/", /* path */ |
3608 | + "com.canonical.UpstartAppLaunch", /* interface */ |
3609 | + "ApplicationFailed", /* signal */ |
3610 | + g_variant_new("(ss)", "foo", "blahblah"), /* params, the same */ |
3611 | + NULL); |
3612 | + |
3613 | + pause(100); |
3614 | + |
3615 | + EXPECT_EQ("foo", last_observer); |
3616 | + |
3617 | + last_observer.clear(); |
3618 | + |
3619 | + g_dbus_connection_emit_signal(session, |
3620 | + NULL, /* destination */ |
3621 | + "/", /* path */ |
3622 | + "com.canonical.UpstartAppLaunch", /* interface */ |
3623 | + "ApplicationFailed", /* signal */ |
3624 | + g_variant_new("(ss)", "foo", "start-failure"), /* params, the same */ |
3625 | + NULL); |
3626 | + |
3627 | + pause(100); |
3628 | + |
3629 | + EXPECT_TRUE(last_observer.empty()); |
3630 | + |
3631 | + EXPECT_TRUE(upstart_app_launch_observer_delete_app_failed(failed_observer, &last_observer)); |
3632 | + |
3633 | + g_object_unref(session); |
3634 | +} |
3635 | + |
3636 | |
3637 | === added directory 'tests/link-farm' |
3638 | === added file 'tests/link-farm/README' |
3639 | --- tests/link-farm/README 1970-01-01 00:00:00 +0000 |
3640 | +++ tests/link-farm/README 2014-02-11 03:28:22 +0000 |
3641 | @@ -0,0 +1,3 @@ |
3642 | +This directory is setup as our testing link farm. Anything that has a |
3643 | +desktop in here will be detected as a click package, something without |
3644 | +will be seen as a legacy package. |
3645 | |
3646 | === added file 'tests/link-farm/foo.desktop' |
3647 | --- tests/link-farm/foo.desktop 1970-01-01 00:00:00 +0000 |
3648 | +++ tests/link-farm/foo.desktop 2014-02-11 03:28:22 +0000 |
3649 | @@ -0,0 +1,1 @@ |
3650 | +Needs to exist |
3651 | |
3652 | === added file 'tests/link-farm/foolike.desktop' |
3653 | --- tests/link-farm/foolike.desktop 1970-01-01 00:00:00 +0000 |
3654 | +++ tests/link-farm/foolike.desktop 2014-02-11 03:28:22 +0000 |
3655 | @@ -0,0 +1,1 @@ |
3656 | +Needs to exist |
3657 | |
3658 | === modified file 'tests/manual' |
3659 | --- tests/manual 2014-01-30 22:13:28 +0000 |
3660 | +++ tests/manual 2014-02-11 03:28:22 +0000 |
3661 | @@ -27,3 +27,10 @@ |
3662 | <dt>Send a URL to the service: <tt>upstart-app-launch ubuntu-system-settings settings:///system/battery</tt></dt> |
3663 | <dd>The settings application should come back into focus and be on the power settings pane</dd> |
3664 | </dl> |
3665 | + |
3666 | +Test-case upstart-app-launch/security-app-launch |
3667 | +<dl> |
3668 | + <dt>Setup the security tests: https://wiki.ubuntu.com/Touch/Testing#Running_Security_tests</dt> |
3669 | + <dt>Execute the <tt>click-apparmor</tt> test to start and stop several confined applications</dt> |
3670 | + <dd>Ensure that all applications start and stop correctly</dd> |
3671 | +</dl> |
3672 | |
3673 | === removed file 'tests/second-exec-test.cc' |
3674 | --- tests/second-exec-test.cc 2013-12-06 11:44:25 +0000 |
3675 | +++ tests/second-exec-test.cc 1970-01-01 00:00:00 +0000 |
3676 | @@ -1,205 +0,0 @@ |
3677 | -/* |
3678 | - * Copyright 2013 Canonical Ltd. |
3679 | - * |
3680 | - * This program is free software: you can redistribute it and/or modify it |
3681 | - * under the terms of the GNU General Public License version 3, as published |
3682 | - * by the Free Software Foundation. |
3683 | - * |
3684 | - * This program is distributed in the hope that it will be useful, but |
3685 | - * WITHOUT ANY WARRANTY; without even the implied warranties of |
3686 | - * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
3687 | - * PURPOSE. See the GNU General Public License for more details. |
3688 | - * |
3689 | - * You should have received a copy of the GNU General Public License along |
3690 | - * with this program. If not, see <http://www.gnu.org/licenses/>. |
3691 | - * |
3692 | - * Authors: |
3693 | - * Ted Gould <ted.gould@canonical.com> |
3694 | - */ |
3695 | - |
3696 | -#include <gtest/gtest.h> |
3697 | -#include <gio/gio.h> |
3698 | - |
3699 | -extern "C" { |
3700 | -#include "../second-exec-core.h" |
3701 | -#include "upstart-app-launch.h" |
3702 | -#include "upstart-app-launch-mock.h" |
3703 | -} |
3704 | - |
3705 | -class SecondExecTest : public ::testing::Test |
3706 | -{ |
3707 | - private: |
3708 | - GTestDBus * testbus = NULL; |
3709 | - |
3710 | - protected: |
3711 | - std::string last_focus_appid; |
3712 | - std::string last_resume_appid; |
3713 | - guint resume_timeout = 0; |
3714 | - |
3715 | - private: |
3716 | - static void focus_cb (const gchar * appid, gpointer user_data) { |
3717 | - SecondExecTest * _this = static_cast<SecondExecTest *>(user_data); |
3718 | - _this->last_focus_appid = appid; |
3719 | - } |
3720 | - |
3721 | - static void resume_cb (const gchar * appid, gpointer user_data) { |
3722 | - SecondExecTest * _this = static_cast<SecondExecTest *>(user_data); |
3723 | - _this->last_resume_appid = appid; |
3724 | - |
3725 | - if (_this->resume_timeout > 0) { |
3726 | - _this->pause(_this->resume_timeout); |
3727 | - } |
3728 | - } |
3729 | - |
3730 | - protected: |
3731 | - virtual void SetUp() { |
3732 | - testbus = g_test_dbus_new(G_TEST_DBUS_NONE); |
3733 | - g_test_dbus_up(testbus); |
3734 | - |
3735 | - upstart_app_launch_observer_add_app_focus(focus_cb, this); |
3736 | - upstart_app_launch_observer_add_app_resume(resume_cb, this); |
3737 | - } |
3738 | - virtual void TearDown() { |
3739 | - upstart_app_launch_observer_delete_app_focus(focus_cb, this); |
3740 | - upstart_app_launch_observer_delete_app_resume(resume_cb, this); |
3741 | - |
3742 | - g_test_dbus_down(testbus); |
3743 | - g_object_unref(testbus); |
3744 | - } |
3745 | - |
3746 | - static gboolean pause_helper (gpointer pmainloop) { |
3747 | - g_main_loop_quit((GMainLoop *)pmainloop); |
3748 | - return G_SOURCE_REMOVE; |
3749 | - } |
3750 | - |
3751 | - void pause (guint time) { |
3752 | - if (time > 0) { |
3753 | - GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
3754 | - guint timer = g_timeout_add(time, pause_helper, mainloop); |
3755 | - |
3756 | - g_main_loop_run(mainloop); |
3757 | - |
3758 | - g_source_remove(timer); |
3759 | - g_main_loop_unref(mainloop); |
3760 | - } |
3761 | - |
3762 | - while (g_main_pending()) { |
3763 | - g_main_iteration(TRUE); |
3764 | - } |
3765 | - } |
3766 | -}; |
3767 | - |
3768 | -TEST_F(SecondExecTest, AppIdTest) |
3769 | -{ |
3770 | - ASSERT_TRUE(second_exec("foo", NULL)); |
3771 | - pause(50); /* Ensure all the events come through */ |
3772 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
3773 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
3774 | -} |
3775 | - |
3776 | -GDBusMessage * |
3777 | -filter_func_good (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
3778 | -{ |
3779 | - if (!incomming) { |
3780 | - return message; |
3781 | - } |
3782 | - |
3783 | - if (g_strcmp0(g_dbus_message_get_path(message), (gchar *)user_data) == 0) { |
3784 | - GDBusMessage * reply = g_dbus_message_new_method_reply(message); |
3785 | - g_dbus_connection_send_message(conn, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); |
3786 | - g_object_unref(message); |
3787 | - return NULL; |
3788 | - } |
3789 | - |
3790 | - return message; |
3791 | -} |
3792 | - |
3793 | -TEST_F(SecondExecTest, UrlSendTest) |
3794 | -{ |
3795 | - upstart_app_launch_mock_set_primary_pid(getpid()); |
3796 | - |
3797 | - GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3798 | - guint filter = g_dbus_connection_add_filter(session, |
3799 | - filter_func_good, |
3800 | - (gpointer)"/foo", |
3801 | - NULL); |
3802 | - |
3803 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
3804 | - pause(100); /* Ensure all the events come through */ |
3805 | - |
3806 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
3807 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
3808 | - |
3809 | - g_dbus_connection_remove_filter(session, filter); |
3810 | - g_object_unref(session); |
3811 | -} |
3812 | - |
3813 | -TEST_F(SecondExecTest, UrlSendNoObjectTest) |
3814 | -{ |
3815 | - upstart_app_launch_mock_set_primary_pid(getpid()); |
3816 | - |
3817 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
3818 | - pause(100); /* Ensure all the events come through */ |
3819 | - |
3820 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
3821 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
3822 | -} |
3823 | - |
3824 | -TEST_F(SecondExecTest, UnityTimeoutTest) |
3825 | -{ |
3826 | - this->resume_timeout = 100; |
3827 | - |
3828 | - ASSERT_TRUE(second_exec("foo", NULL)); |
3829 | - pause(100); /* Ensure all the events come through */ |
3830 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
3831 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
3832 | -} |
3833 | - |
3834 | -TEST_F(SecondExecTest, UnityTimeoutUriTest) |
3835 | -{ |
3836 | - this->resume_timeout = 200; |
3837 | - |
3838 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
3839 | - pause(100); /* Ensure all the events come through */ |
3840 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
3841 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
3842 | -} |
3843 | - |
3844 | -GDBusMessage * |
3845 | -filter_respawn (GDBusConnection * conn, GDBusMessage * message, gboolean incomming, gpointer user_data) |
3846 | -{ |
3847 | - if (g_strcmp0(g_dbus_message_get_member(message), "UnityResumeResponse") == 0) { |
3848 | - g_object_unref(message); |
3849 | - return NULL; |
3850 | - } |
3851 | - |
3852 | - return message; |
3853 | -} |
3854 | - |
3855 | -TEST_F(SecondExecTest, UnityLostTest) |
3856 | -{ |
3857 | - upstart_app_launch_mock_set_primary_pid(getpid()); |
3858 | - |
3859 | - GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
3860 | - guint filter = g_dbus_connection_add_filter(session, |
3861 | - filter_respawn, |
3862 | - NULL, |
3863 | - NULL); |
3864 | - |
3865 | - guint start = g_get_monotonic_time(); |
3866 | - |
3867 | - ASSERT_TRUE(second_exec("foo", "http://www.test.com")); |
3868 | - |
3869 | - guint end = g_get_monotonic_time(); |
3870 | - |
3871 | - ASSERT_LT(end - start, 600 * 1000); |
3872 | - |
3873 | - pause(100); /* Ensure all the events come through */ |
3874 | - ASSERT_STREQ(this->last_focus_appid.c_str(), "foo"); |
3875 | - ASSERT_STREQ(this->last_resume_appid.c_str(), "foo"); |
3876 | - |
3877 | - g_dbus_connection_remove_filter(session, filter); |
3878 | - g_object_unref(session); |
3879 | -} |
3880 | - |
3881 | - |
3882 | |
3883 | === modified file 'tests/zg-test.cc' |
3884 | --- tests/zg-test.cc 2013-11-08 18:48:33 +0000 |
3885 | +++ tests/zg-test.cc 2014-02-11 03:28:22 +0000 |
3886 | @@ -66,3 +66,58 @@ |
3887 | g_object_unref(mock); |
3888 | g_object_unref(service); |
3889 | } |
3890 | + |
3891 | +static void |
3892 | +zg_state_changed (DbusTestTask * task, DbusTestTaskState state, gpointer user_data) |
3893 | +{ |
3894 | + if (state != DBUS_TEST_TASK_STATE_FINISHED) |
3895 | + return; |
3896 | + |
3897 | + g_debug("ZG Event Task Finished"); |
3898 | + |
3899 | + GMainLoop * mainloop = static_cast<GMainLoop *>(user_data); |
3900 | + g_main_loop_quit(mainloop); |
3901 | +} |
3902 | + |
3903 | +TEST(ZGEvent, TimeoutTest) |
3904 | +{ |
3905 | + GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
3906 | + DbusTestService * service = dbus_test_service_new(NULL); |
3907 | + |
3908 | + DbusTestDbusMock * mock = dbus_test_dbus_mock_new("org.gnome.zeitgeist.Engine"); |
3909 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/org/gnome/zeitgeist/log/activity", "org.gnome.zeitgeist.Log", NULL); |
3910 | + |
3911 | + dbus_test_dbus_mock_object_add_method(mock, obj, |
3912 | + "InsertEvents", |
3913 | + G_VARIANT_TYPE("a(asaasay)"), |
3914 | + G_VARIANT_TYPE("au"), |
3915 | + "time.sleep(6)\n" |
3916 | + "ret = [ 0 ]", |
3917 | + NULL); |
3918 | + |
3919 | + dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); |
3920 | + |
3921 | + DbusTestProcess * zgevent = dbus_test_process_new(ZG_EVENT_TOOL); |
3922 | + dbus_test_process_append_param(zgevent, "close"); |
3923 | + g_setenv("APP_ID", "foo", 1); |
3924 | + dbus_test_task_set_wait_for(DBUS_TEST_TASK(zgevent), "org.gnome.zeitgeist.Engine"); |
3925 | + dbus_test_task_set_name(DBUS_TEST_TASK(zgevent), "ZGEvent"); |
3926 | + g_signal_connect(G_OBJECT(zgevent), DBUS_TEST_TASK_SIGNAL_STATE_CHANGED, G_CALLBACK(zg_state_changed), mainloop); |
3927 | + |
3928 | + dbus_test_service_add_task(service, DBUS_TEST_TASK(zgevent)); |
3929 | + |
3930 | + guint64 start = g_get_monotonic_time(); |
3931 | + |
3932 | + dbus_test_service_start_tasks(service); |
3933 | + |
3934 | + g_main_loop_run(mainloop); |
3935 | + |
3936 | + guint64 end = g_get_monotonic_time(); |
3937 | + |
3938 | + /* Four seconds to do a two second op -- ARM Jenkins is slow */ |
3939 | + EXPECT_LT(end - start, 4 * 1000 * 1000); |
3940 | + |
3941 | + g_object_unref(zgevent); |
3942 | + g_object_unref(service); |
3943 | + g_main_loop_unref(mainloop); |
3944 | +} |
3945 | |
3946 | === modified file 'upstart-app-watch.c' |
3947 | --- upstart-app-watch.c 2013-12-05 17:14:55 +0000 |
3948 | +++ upstart-app-watch.c 2014-02-11 03:28:22 +0000 |
3949 | @@ -67,7 +67,7 @@ |
3950 | break; |
3951 | } |
3952 | |
3953 | - g_print("Fail %s (%s)\n", appid, failstr); |
3954 | + g_print("Fail %s (%s)\n", appid, failstr); |
3955 | return; |
3956 | } |
3957 | |
3958 | |
3959 | === modified file 'zg-report-app.c' |
3960 | --- zg-report-app.c 2013-11-08 18:17:42 +0000 |
3961 | +++ zg-report-app.c 2014-02-11 03:28:22 +0000 |
3962 | @@ -23,7 +23,7 @@ |
3963 | static gboolean |
3964 | watchdog_timeout (gpointer user_data) |
3965 | { |
3966 | - g_error("Watchdog triggered, took too long to submit into Zeitgeist Database!"); |
3967 | + g_warning("Watchdog triggered, took too long to submit into Zeitgeist Database!"); |
3968 | g_main_loop_quit((GMainLoop *)user_data); |
3969 | |
3970 | return G_SOURCE_REMOVE; |
3971 | @@ -84,7 +84,7 @@ |
3972 | GMainLoop * main_loop = g_main_loop_new(NULL, FALSE); |
3973 | |
3974 | zeitgeist_log_insert_event(log, event, NULL, insert_complete, main_loop); |
3975 | - g_timeout_add_seconds(4, watchdog_timeout, main_loop); |
3976 | + g_timeout_add_seconds(2, watchdog_timeout, main_loop); |
3977 | |
3978 | g_main_loop_run(main_loop); |
3979 |
PASSED: Continuous integration, rev:115 jenkins. qa.ubuntu. com/job/ upstart- app-launch- ci/210/ jenkins. qa.ubuntu. com/job/ upstart- app-launch- trusty- amd64-ci/ 69 jenkins. qa.ubuntu. com/job/ upstart- app-launch- trusty- armhf-ci/ 69 jenkins. qa.ubuntu. com/job/ upstart- app-launch- trusty- i386-ci/ 70
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/upstart- app-launch- ci/210/ rebuild
http://