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