Merge lp:~ted/ubuntu-app-launch/untrusted-helper into lp:ubuntu-app-launch/14.04
- untrusted-helper
- Merge into trunk.14.04
Status: | Merged |
---|---|
Approved by: | Charles Kerr |
Approved revision: | 134 |
Merged at revision: | 130 |
Proposed branch: | lp:~ted/ubuntu-app-launch/untrusted-helper |
Merge into: | lp:ubuntu-app-launch/14.04 |
Prerequisite: | lp:~ted/ubuntu-app-launch/failure-is-an-option |
Diff against target: |
1623 lines (+1343/-81) 16 files modified
.bzrignore (+6/-1) CMakeLists.txt (+9/-75) MERGE-REVIEW (+2/-0) debian/libupstart-app-launch2.symbols (+10/-0) libupstart-app-launch/upstart-app-launch.c (+473/-0) libupstart-app-launch/upstart-app-launch.h (+152/-0) tests/libual-test.cc (+307/-5) tests/manual (+15/-0) tools/CMakeLists.txt (+73/-0) tools/upstart-helper-list.c (+50/-0) tools/upstart-helper-start.c (+46/-0) tools/upstart-helper-stop.c (+45/-0) untrusted-helper-type-end.c (+66/-0) upstart-jobs/CMakeLists.txt (+49/-0) upstart-jobs/untrusted-helper-type-end.conf.in (+9/-0) upstart-jobs/untrusted-helper.conf.in (+31/-0) |
To merge this branch: | bzr merge lp:~ted/ubuntu-app-launch/untrusted-helper |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot (community) | continuous-integration | Approve | |
Charles Kerr (community) | Approve | ||
Review via email: mp+202703@code.launchpad.net |
Commit message
Support for Untrusted Helpers
Description of the change
Adds support for a new job class nicknamed "untrusted helper" These are more freeform to be used by the infographic visualization work and others. It provides upstart to do the management and setup the PID while allowing the manager to install a plugin to find the exec line needed for their project.
Also did some reshuffling putting things into directories, probably need more, but this branch is a start.
PS Jenkins bot (ps-jenkins) wrote : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:130
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:131
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Looks pretty good, especially the documentation of the public API. Nice!
Only a couple of points:
Needs-fixing: start_helper_core() leaks the variable 'urisjoin'
Just-nagging: untrusted-
Ted Gould (ted) wrote : | # |
On Wed, 2014-02-05 at 18:54 +0000, Charles Kerr wrote:
> Needs-fixing: start_helper_core() leaks the variable 'urisjoin'
Fixed r133
> Just-nagging: untrusted-
Fixed r134
Also, pulled through application-
Charles Kerr (charlesk) : | # |
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:134
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2013-05-04 00:38:13 +0000 |
3 | +++ .bzrignore 2014-02-14 02:01:23 +0000 |
4 | @@ -1,1 +1,6 @@ |
5 | -desktop-exec |
6 | +CMakeCache.txt |
7 | +CMakeFiles/ |
8 | +CTestTestfile.cmake |
9 | +Makefile |
10 | +cmake_install.cmake |
11 | +*-trace.[ch] |
12 | |
13 | === modified file 'CMakeLists.txt' |
14 | --- CMakeLists.txt 2014-02-11 03:14:30 +0000 |
15 | +++ CMakeLists.txt 2014-02-14 02:01:23 +0000 |
16 | @@ -76,51 +76,6 @@ |
17 | target_link_libraries(helpers ${GIO2_LIBRARIES} ${JSONGLIB_LIBRARIES}) |
18 | |
19 | #################### |
20 | -# upstart-app-list |
21 | -#################### |
22 | - |
23 | -add_executable(upstart-app-list upstart-app-list.c) |
24 | -set_target_properties(upstart-app-list PROPERTIES OUTPUT_NAME "upstart-app-list") |
25 | -target_link_libraries(upstart-app-list upstart-launcher) |
26 | -install(TARGETS upstart-app-list RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
27 | - |
28 | -#################### |
29 | -# upstart-app-launch |
30 | -#################### |
31 | - |
32 | -add_executable(upstart-app-launch upstart-app-launch.c) |
33 | -set_target_properties(upstart-app-launch PROPERTIES OUTPUT_NAME "upstart-app-launch") |
34 | -target_link_libraries(upstart-app-launch upstart-launcher) |
35 | -install(TARGETS upstart-app-launch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
36 | - |
37 | -#################### |
38 | -# upstart-app-watch |
39 | -#################### |
40 | - |
41 | -add_executable(upstart-app-watch upstart-app-watch.c) |
42 | -set_target_properties(upstart-app-watch PROPERTIES OUTPUT_NAME "upstart-app-watch") |
43 | -target_link_libraries(upstart-app-watch upstart-launcher) |
44 | -install(TARGETS upstart-app-watch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
45 | - |
46 | -#################### |
47 | -# upstart-app-pid |
48 | -#################### |
49 | - |
50 | -add_executable(upstart-app-pid upstart-app-pid.c) |
51 | -set_target_properties(upstart-app-pid PROPERTIES OUTPUT_NAME "upstart-app-pid") |
52 | -target_link_libraries(upstart-app-pid upstart-launcher) |
53 | -install(TARGETS upstart-app-pid RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
54 | - |
55 | -#################### |
56 | -# upstart-app-stop |
57 | -#################### |
58 | - |
59 | -add_executable(upstart-app-stop upstart-app-stop.c) |
60 | -set_target_properties(upstart-app-stop PROPERTIES OUTPUT_NAME "upstart-app-stop") |
61 | -target_link_libraries(upstart-app-stop upstart-launcher) |
62 | -install(TARGETS upstart-app-stop RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
63 | - |
64 | -#################### |
65 | # desktop-exec |
66 | #################### |
67 | |
68 | @@ -188,36 +143,13 @@ |
69 | install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}") |
70 | |
71 | #################### |
72 | -# application.conf |
73 | -#################### |
74 | - |
75 | -configure_file("application.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application.conf" @ONLY) |
76 | -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
77 | -add_test(application.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application.conf") |
78 | - |
79 | -#################### |
80 | -# application-legacy.conf |
81 | -#################### |
82 | - |
83 | -configure_file("application-legacy.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-legacy.conf" @ONLY) |
84 | -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-legacy.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
85 | -add_test(application-legacy.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-legacy.conf") |
86 | - |
87 | -#################### |
88 | -# application-click.conf |
89 | -#################### |
90 | - |
91 | -configure_file("application-click.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf" @ONLY) |
92 | -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
93 | -add_test(application-click.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf") |
94 | - |
95 | -#################### |
96 | -# application-failed.conf |
97 | -#################### |
98 | - |
99 | -configure_file("application-failed.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf" @ONLY) |
100 | -install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
101 | -add_test(application-failed.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf") |
102 | +# untrusted-helper-type-end |
103 | +#################### |
104 | + |
105 | +add_executable(untrusted-helper-type-end untrusted-helper-type-end.c) |
106 | +set_target_properties(untrusted-helper-type-end PROPERTIES OUTPUT_NAME "untrusted-helper-type-end") |
107 | +target_link_libraries(untrusted-helper-type-end upstart-launcher) |
108 | +install(TARGETS untrusted-helper-type-end RUNTIME DESTINATION "${pkglibexecdir}") |
109 | |
110 | #################### |
111 | # upstart-app-launch-desktop.click-hook |
112 | @@ -226,6 +158,8 @@ |
113 | configure_file("upstart-app-launch-desktop.click-hook.in" "${CMAKE_CURRENT_SOURCE_DIR}/debian/upstart-app-launch-desktop.click-hook" @ONLY) |
114 | |
115 | add_subdirectory(libupstart-app-launch) |
116 | +add_subdirectory(upstart-jobs) |
117 | +add_subdirectory(tools) |
118 | |
119 | # testing & coverage |
120 | if (${enable_tests}) |
121 | |
122 | === modified file 'MERGE-REVIEW' |
123 | --- MERGE-REVIEW 2014-01-29 19:29:26 +0000 |
124 | +++ MERGE-REVIEW 2014-02-14 02:01:23 +0000 |
125 | @@ -15,4 +15,6 @@ |
126 | * Run test case: upstart-app-launch/click-app |
127 | * Run test case: upstart-app-launch/legacy-app |
128 | * Run test case: upstart-app-launch/secondary-activation |
129 | + * If this MR effect untrusted-helpers: |
130 | + * Run test case: upstart-app-launch/helper-run |
131 | |
132 | |
133 | === modified file 'debian/libupstart-app-launch2.symbols' |
134 | --- debian/libupstart-app-launch2.symbols 2014-02-13 13:14:48 +0000 |
135 | +++ debian/libupstart-app-launch2.symbols 2014-02-14 02:01:23 +0000 |
136 | @@ -1,6 +1,8 @@ |
137 | libupstart-app-launch.so.2 libupstart-app-launch2 #MINVER# |
138 | upstart_app_launch_application_log_path@Base 0.3+14.04.20140213 |
139 | upstart_app_launch_get_primary_pid@Base 0.2 |
140 | + upstart_app_launch_list_helper_instances@Base 0replaceme |
141 | + upstart_app_launch_list_helpers@Base 0replaceme |
142 | upstart_app_launch_list_running_apps@Base 0.2 |
143 | upstart_app_launch_observer_add_app_failed@Base 0.2 |
144 | upstart_app_launch_observer_add_app_focus@Base 0.2 |
145 | @@ -8,13 +10,21 @@ |
146 | upstart_app_launch_observer_add_app_started@Base 0.3+14.04.20131209 |
147 | upstart_app_launch_observer_add_app_starting@Base 0.3+14.04.20131209 |
148 | upstart_app_launch_observer_add_app_stop@Base 0.2 |
149 | + upstart_app_launch_observer_add_helper_started@Base 0replaceme |
150 | + upstart_app_launch_observer_add_helper_stop@Base 0replaceme |
151 | upstart_app_launch_observer_delete_app_failed@Base 0.2 |
152 | upstart_app_launch_observer_delete_app_focus@Base 0.2 |
153 | upstart_app_launch_observer_delete_app_resume@Base 0.2 |
154 | upstart_app_launch_observer_delete_app_started@Base 0.3+14.04.20131209 |
155 | upstart_app_launch_observer_delete_app_starting@Base 0.3+14.04.20131209 |
156 | upstart_app_launch_observer_delete_app_stop@Base 0.2 |
157 | + upstart_app_launch_observer_delete_helper_started@Base 0replaceme |
158 | + upstart_app_launch_observer_delete_helper_stop@Base 0replaceme |
159 | upstart_app_launch_pid_in_app_id@Base 0.2 |
160 | upstart_app_launch_start_application@Base 0.2 |
161 | + upstart_app_launch_start_helper@Base 0replaceme |
162 | + upstart_app_launch_start_multiple_helper@Base 0replaceme |
163 | upstart_app_launch_stop_application@Base 0.2 |
164 | + upstart_app_launch_stop_helper@Base 0replaceme |
165 | + upstart_app_launch_stop_multiple_helper@Base 0replaceme |
166 | upstart_app_launch_triplet_to_app_id@Base 0.3+14.04.20140129.1 |
167 | |
168 | === modified file 'libupstart-app-launch/upstart-app-launch.c' |
169 | --- libupstart-app-launch/upstart-app-launch.c 2014-02-11 03:04:26 +0000 |
170 | +++ libupstart-app-launch/upstart-app-launch.c 2014-02-14 02:01:23 +0000 |
171 | @@ -63,6 +63,7 @@ |
172 | GVariant * result = NULL; |
173 | |
174 | tracepoint(upstart_app_launch, libual_start_message_callback, data->appid); |
175 | + |
176 | g_debug("Started Message Callback: %s", data->appid); |
177 | |
178 | result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error); |
179 | @@ -1205,3 +1206,475 @@ |
180 | |
181 | return retval; |
182 | } |
183 | + |
184 | +/* Print an error if we couldn't start it */ |
185 | +static void |
186 | +start_helper_callback (GObject * obj, GAsyncResult * res, gpointer user_data) |
187 | +{ |
188 | + GError * error = NULL; |
189 | + GVariant * result = NULL; |
190 | + |
191 | + result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error); |
192 | + if (result != NULL) |
193 | + g_variant_unref(result); |
194 | + |
195 | + if (error != NULL) { |
196 | + g_warning("Unable to start helper: %s", error->message); |
197 | + g_error_free(error); |
198 | + } |
199 | +} |
200 | + |
201 | +/* Implements sending the "start" command to Upstart for the |
202 | + untrusted helper job with the various configuration options |
203 | + to define the instance. In the end there's only one job with |
204 | + an array of instances. */ |
205 | +static gboolean |
206 | +start_helper_core (const gchar * type, const gchar * appid, const gchar * const * uris, const gchar * instance) |
207 | +{ |
208 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
209 | + g_return_val_if_fail(con != NULL, FALSE); |
210 | + |
211 | + const gchar * jobpath = get_jobpath(con, "untrusted-helper"); |
212 | + |
213 | + /* Build up our environment */ |
214 | + GVariantBuilder builder; |
215 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
216 | + g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
217 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appid))); |
218 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("HELPER_TYPE=%s", type))); |
219 | + |
220 | + if (uris != NULL) { |
221 | + gchar * urisjoin = app_uris_string(uris); |
222 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_URIS=%s", urisjoin))); |
223 | + g_free(urisjoin); |
224 | + } |
225 | + |
226 | + if (instance != NULL) { |
227 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instance))); |
228 | + } |
229 | + |
230 | + g_variant_builder_close(&builder); |
231 | + g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
232 | + |
233 | + /* Call the job start function */ |
234 | + g_dbus_connection_call(con, |
235 | + DBUS_SERVICE_UPSTART, |
236 | + jobpath, |
237 | + DBUS_INTERFACE_UPSTART_JOB, |
238 | + "Start", |
239 | + g_variant_builder_end(&builder), |
240 | + NULL, |
241 | + G_DBUS_CALL_FLAGS_NONE, |
242 | + -1, |
243 | + NULL, /* cancelable */ |
244 | + start_helper_callback, |
245 | + NULL); |
246 | + |
247 | + g_object_unref(con); |
248 | + |
249 | + return TRUE; |
250 | +} |
251 | + |
252 | +gboolean |
253 | +upstart_app_launch_start_helper (const gchar * type, const gchar * appid, const gchar * const * uris) |
254 | +{ |
255 | + g_return_val_if_fail(type != NULL, FALSE); |
256 | + g_return_val_if_fail(appid != NULL, FALSE); |
257 | + g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE); |
258 | + |
259 | + return start_helper_core(type, appid, uris, NULL); |
260 | +} |
261 | + |
262 | +gchar * |
263 | +upstart_app_launch_start_multiple_helper (const gchar * type, const gchar * appid, const gchar * const * uris) |
264 | +{ |
265 | + g_return_val_if_fail(type != NULL, NULL); |
266 | + g_return_val_if_fail(appid != NULL, NULL); |
267 | + g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, NULL); |
268 | + |
269 | + gchar * instanceid = g_strdup_printf("%" G_GUINT64_FORMAT, g_get_real_time()); |
270 | + |
271 | + if (start_helper_core(type, appid, uris, instanceid)) { |
272 | + return instanceid; |
273 | + } |
274 | + |
275 | + g_free(instanceid); |
276 | + return NULL; |
277 | +} |
278 | + |
279 | +/* Print an error if we couldn't stop it */ |
280 | +static void |
281 | +stop_helper_callback (GObject * obj, GAsyncResult * res, gpointer user_data) |
282 | +{ |
283 | + GError * error = NULL; |
284 | + GVariant * result = NULL; |
285 | + |
286 | + result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(obj), res, &error); |
287 | + if (result != NULL) |
288 | + g_variant_unref(result); |
289 | + |
290 | + if (error != NULL) { |
291 | + g_warning("Unable to stop helper: %s", error->message); |
292 | + g_error_free(error); |
293 | + } |
294 | +} |
295 | + |
296 | +/* Implements the basis of sending the stop message to Upstart for |
297 | + an instance of the untrusted-helper job. That also can have an |
298 | + instance in that we allow for random instance ids to be used for |
299 | + helpers that are not unique */ |
300 | +static gboolean |
301 | +stop_helper_core (const gchar * type, const gchar * appid, const gchar * instanceid) |
302 | +{ |
303 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
304 | + g_return_val_if_fail(con != NULL, FALSE); |
305 | + |
306 | + const gchar * jobpath = get_jobpath(con, "untrusted-helper"); |
307 | + |
308 | + /* Build up our environment */ |
309 | + GVariantBuilder builder; |
310 | + g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); |
311 | + g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); |
312 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("APP_ID=%s", appid))); |
313 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("HELPER_TYPE=%s", type))); |
314 | + |
315 | + if (instanceid != NULL) { |
316 | + g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instanceid))); |
317 | + } |
318 | + |
319 | + g_variant_builder_close(&builder); |
320 | + g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
321 | + |
322 | + /* Call the job start function */ |
323 | + g_dbus_connection_call(con, |
324 | + DBUS_SERVICE_UPSTART, |
325 | + jobpath, |
326 | + DBUS_INTERFACE_UPSTART_JOB, |
327 | + "Stop", |
328 | + g_variant_builder_end(&builder), |
329 | + NULL, |
330 | + G_DBUS_CALL_FLAGS_NONE, |
331 | + -1, |
332 | + NULL, /* cancelable */ |
333 | + stop_helper_callback, |
334 | + NULL); |
335 | + |
336 | + g_object_unref(con); |
337 | + |
338 | + return TRUE; |
339 | +} |
340 | + |
341 | +gboolean |
342 | +upstart_app_launch_stop_helper (const gchar * type, const gchar * appid) |
343 | +{ |
344 | + g_return_val_if_fail(type != NULL, FALSE); |
345 | + g_return_val_if_fail(appid != NULL, FALSE); |
346 | + g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE); |
347 | + |
348 | + return stop_helper_core(type, appid, NULL); |
349 | +} |
350 | + |
351 | +gboolean |
352 | +upstart_app_launch_stop_multiple_helper (const gchar * type, const gchar * appid, const gchar * instanceid) |
353 | +{ |
354 | + g_return_val_if_fail(type != NULL, FALSE); |
355 | + g_return_val_if_fail(appid != NULL, FALSE); |
356 | + g_return_val_if_fail(instanceid != NULL, FALSE); |
357 | + g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE); |
358 | + |
359 | + return stop_helper_core(type, appid, instanceid); |
360 | +} |
361 | + |
362 | + |
363 | +typedef struct { |
364 | + gchar * type_prefix; /* Type with the colon sperator */ |
365 | + size_t type_len; /* Length in characters of the prefix */ |
366 | + GArray * retappids; /* Array of appids to return */ |
367 | +} helpers_helper_t; |
368 | + |
369 | +/* Look at each instance and see if it matches this type, if so |
370 | + add the appid portion to the array of appids */ |
371 | +static void |
372 | +list_helpers_helper (GDBusConnection * con, GVariant * props_dict, gpointer user_data) |
373 | +{ |
374 | + helpers_helper_t * data = (helpers_helper_t *)user_data; |
375 | + |
376 | + GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
377 | + if (namev == NULL) { |
378 | + return; |
379 | + } |
380 | + |
381 | + const gchar * name = g_variant_get_string(namev, NULL); |
382 | + if (g_str_has_prefix(name, data->type_prefix)) { |
383 | + /* Skip the type name */ |
384 | + name += data->type_len; |
385 | + |
386 | + /* Skip a possible instance ID */ |
387 | + name = g_strstr_len(name, -1, ":"); |
388 | + name++; |
389 | + |
390 | + /* Now copy the app id */ |
391 | + gchar * appid = g_strdup(name); |
392 | + g_array_append_val(data->retappids, appid); |
393 | + } |
394 | + |
395 | + g_variant_unref(namev); |
396 | + |
397 | + return; |
398 | +} |
399 | + |
400 | +gchar ** |
401 | +upstart_app_launch_list_helpers (const gchar * type) |
402 | +{ |
403 | + g_return_val_if_fail(type != NULL, FALSE); |
404 | + g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE); |
405 | + |
406 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
407 | + g_return_val_if_fail(con != NULL, FALSE); |
408 | + |
409 | + helpers_helper_t helpers_helper_data = { |
410 | + .type_prefix = g_strdup_printf("%s:", type), |
411 | + .type_len = strlen(type) + 1, /* 1 for the colon */ |
412 | + .retappids = g_array_new(TRUE, TRUE, sizeof(gchar *)) |
413 | + }; |
414 | + |
415 | + foreach_job_instance(con, "untrusted-helper", list_helpers_helper, &helpers_helper_data); |
416 | + |
417 | + g_object_unref(con); |
418 | + g_free(helpers_helper_data.type_prefix); |
419 | + |
420 | + return (gchar **)g_array_free(helpers_helper_data.retappids, FALSE); |
421 | +} |
422 | + |
423 | +typedef struct { |
424 | + gchar * type_prefix; /* Type with the colon sperator */ |
425 | + size_t type_len; /* Length in characters of the prefix */ |
426 | + GArray * retappids; /* Array of appids to return */ |
427 | + gchar * appid_suffix; /* The appid for the end */ |
428 | +} helper_instances_t; |
429 | + |
430 | +/* Look at each instance and see if it matches this type and appid. |
431 | + If so, add the instance ID to the array of instance IDs */ |
432 | +static void |
433 | +list_helper_instances (GDBusConnection * con, GVariant * props_dict, gpointer user_data) |
434 | +{ |
435 | + helper_instances_t * data = (helper_instances_t *)user_data; |
436 | + |
437 | + GVariant * namev = g_variant_lookup_value(props_dict, "name", G_VARIANT_TYPE_STRING); |
438 | + if (namev == NULL) { |
439 | + return; |
440 | + } |
441 | + |
442 | + const gchar * name = g_variant_get_string(namev, NULL); |
443 | + gchar * suffix_loc = NULL; |
444 | + if (g_str_has_prefix(name, data->type_prefix) && |
445 | + (suffix_loc = g_strrstr(name, data->appid_suffix)) != NULL) { |
446 | + /* Skip the type name */ |
447 | + name += data->type_len; |
448 | + |
449 | + /* Now copy the instance id */ |
450 | + gchar * instanceid = g_strndup(name, suffix_loc - name); |
451 | + g_array_append_val(data->retappids, instanceid); |
452 | + } |
453 | + |
454 | + g_variant_unref(namev); |
455 | + |
456 | + return; |
457 | +} |
458 | + |
459 | +gchar ** |
460 | +upstart_app_launch_list_helper_instances (const gchar * type, const gchar * appid) |
461 | +{ |
462 | + g_return_val_if_fail(type != NULL, FALSE); |
463 | + g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE); |
464 | + |
465 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
466 | + g_return_val_if_fail(con != NULL, FALSE); |
467 | + |
468 | + helper_instances_t helper_instances_data = { |
469 | + .type_prefix = g_strdup_printf("%s:", type), |
470 | + .type_len = strlen(type) + 1, /* 1 for the colon */ |
471 | + .retappids = g_array_new(TRUE, TRUE, sizeof(gchar *)), |
472 | + .appid_suffix = g_strdup_printf(":%s", appid) |
473 | + }; |
474 | + |
475 | + foreach_job_instance(con, "untrusted-helper", list_helper_instances, &helper_instances_data); |
476 | + |
477 | + g_object_unref(con); |
478 | + g_free(helper_instances_data.type_prefix); |
479 | + g_free(helper_instances_data.appid_suffix); |
480 | + |
481 | + return (gchar **)g_array_free(helper_instances_data.retappids, FALSE); |
482 | +} |
483 | + |
484 | +/* The data we keep for each observer */ |
485 | +typedef struct _helper_observer_t helper_observer_t; |
486 | +struct _helper_observer_t { |
487 | + GDBusConnection * conn; |
488 | + guint sighandle; |
489 | + gchar * type; |
490 | + UpstartAppLaunchHelperObserver func; |
491 | + gpointer user_data; |
492 | +}; |
493 | + |
494 | +/* The lists of helper observers */ |
495 | +static GList * helper_started_obs = NULL; |
496 | +static GList * helper_stopped_obs = NULL; |
497 | + |
498 | +static void |
499 | +helper_observer_cb (GDBusConnection * conn, const gchar * sender, const gchar * object, const gchar * interface, const gchar * signal, GVariant * params, gpointer user_data) |
500 | +{ |
501 | + helper_observer_t * observer = (helper_observer_t *)user_data; |
502 | + |
503 | + gchar * env = NULL; |
504 | + GVariant * envs = g_variant_get_child_value(params, 1); |
505 | + GVariantIter iter; |
506 | + g_variant_iter_init(&iter, envs); |
507 | + |
508 | + gboolean job_found = FALSE; |
509 | + gchar * instance = NULL; |
510 | + |
511 | + while (g_variant_iter_loop(&iter, "s", &env)) { |
512 | + if (g_strcmp0(env, "JOB=untrusted-helper") == 0) { |
513 | + job_found = TRUE; |
514 | + } else if (g_str_has_prefix(env, "INSTANCE=")) { |
515 | + instance = g_strdup(env + strlen("INSTANCE=")); |
516 | + } |
517 | + } |
518 | + |
519 | + g_variant_unref(envs); |
520 | + |
521 | + if (instance != NULL && !g_str_has_prefix(instance, observer->type)) { |
522 | + g_free(instance); |
523 | + instance = NULL; |
524 | + } |
525 | + |
526 | + gchar * appid = NULL; |
527 | + gchar * instanceid = NULL; |
528 | + gchar * type = NULL; |
529 | + |
530 | + if (instance != NULL) { |
531 | + gchar ** split = g_strsplit(instance, ":", 3); |
532 | + type = split[0]; |
533 | + instanceid = split[1]; |
534 | + appid = split[2]; |
535 | + g_free(split); |
536 | + } |
537 | + g_free(instance); |
538 | + |
539 | + if (instanceid != NULL && instanceid[0] == '\0') { |
540 | + g_free(instanceid); |
541 | + instanceid = NULL; |
542 | + } |
543 | + |
544 | + if (job_found && appid != NULL) { |
545 | + observer->func(appid, instanceid, type, observer->user_data); |
546 | + } |
547 | + |
548 | + g_free(appid); |
549 | + g_free(instanceid); |
550 | + g_free(type); |
551 | +} |
552 | + |
553 | +/* Creates the observer structure and registers for the signal with |
554 | + GDBus so that we can get a callback */ |
555 | +static gboolean |
556 | +add_helper_generic (UpstartAppLaunchHelperObserver observer, const gchar * helper_type, gpointer user_data, const gchar * signal, GList ** list) |
557 | +{ |
558 | + GDBusConnection * conn = gdbus_upstart_ref(); |
559 | + |
560 | + if (conn == NULL) { |
561 | + return FALSE; |
562 | + } |
563 | + |
564 | + helper_observer_t * observert = g_new0(helper_observer_t, 1); |
565 | + |
566 | + observert->conn = conn; |
567 | + observert->func = observer; |
568 | + observert->user_data = user_data; |
569 | + observert->type = g_strdup_printf("%s:", helper_type); |
570 | + |
571 | + *list = g_list_prepend(*list, observert); |
572 | + |
573 | + observert->sighandle = g_dbus_connection_signal_subscribe(conn, |
574 | + NULL, /* sender */ |
575 | + DBUS_INTERFACE_UPSTART, /* interface */ |
576 | + "EventEmitted", /* signal */ |
577 | + DBUS_PATH_UPSTART, /* path */ |
578 | + signal, /* arg0 */ |
579 | + G_DBUS_SIGNAL_FLAGS_NONE, |
580 | + helper_observer_cb, |
581 | + observert, |
582 | + NULL); /* user data destroy */ |
583 | + |
584 | + return TRUE; |
585 | +} |
586 | + |
587 | +static gboolean |
588 | +delete_helper_generic (UpstartAppLaunchHelperObserver observer, const gchar * type, gpointer user_data, GList ** list) |
589 | +{ |
590 | + helper_observer_t * observert = NULL; |
591 | + GList * look; |
592 | + |
593 | + for (look = *list; look != NULL; look = g_list_next(look)) { |
594 | + observert = (helper_observer_t *)look->data; |
595 | + |
596 | + if (observert->func == observer && observert->user_data == user_data && g_str_has_prefix(observert->type, type)) { |
597 | + break; |
598 | + } |
599 | + } |
600 | + |
601 | + if (look == NULL) { |
602 | + return FALSE; |
603 | + } |
604 | + |
605 | + g_dbus_connection_signal_unsubscribe(observert->conn, observert->sighandle); |
606 | + g_object_unref(observert->conn); |
607 | + |
608 | + g_free(observert->type); |
609 | + g_free(observert); |
610 | + *list = g_list_delete_link(*list, look); |
611 | + |
612 | + return TRUE; |
613 | +} |
614 | + |
615 | +gboolean |
616 | +upstart_app_launch_observer_add_helper_started (UpstartAppLaunchHelperObserver observer, const gchar * helper_type, gpointer user_data) |
617 | +{ |
618 | + g_return_val_if_fail(observer != NULL, FALSE); |
619 | + g_return_val_if_fail(helper_type != NULL, FALSE); |
620 | + g_return_val_if_fail(g_strstr_len(helper_type, -1, ":") == NULL, FALSE); |
621 | + |
622 | + return add_helper_generic(observer, helper_type, user_data, "started", &helper_started_obs); |
623 | +} |
624 | + |
625 | +gboolean |
626 | +upstart_app_launch_observer_add_helper_stop (UpstartAppLaunchHelperObserver observer, const gchar * helper_type, gpointer user_data) |
627 | +{ |
628 | + g_return_val_if_fail(observer != NULL, FALSE); |
629 | + g_return_val_if_fail(helper_type != NULL, FALSE); |
630 | + g_return_val_if_fail(g_strstr_len(helper_type, -1, ":") == NULL, FALSE); |
631 | + |
632 | + return add_helper_generic(observer, helper_type, user_data, "stopped", &helper_stopped_obs); |
633 | +} |
634 | + |
635 | +gboolean |
636 | +upstart_app_launch_observer_delete_helper_started (UpstartAppLaunchHelperObserver observer, const gchar * helper_type, gpointer user_data) |
637 | +{ |
638 | + g_return_val_if_fail(observer != NULL, FALSE); |
639 | + g_return_val_if_fail(helper_type != NULL, FALSE); |
640 | + g_return_val_if_fail(g_strstr_len(helper_type, -1, ":") == NULL, FALSE); |
641 | + |
642 | + return delete_helper_generic(observer, helper_type, user_data, &helper_started_obs); |
643 | +} |
644 | + |
645 | +gboolean |
646 | +upstart_app_launch_observer_delete_helper_stop (UpstartAppLaunchHelperObserver observer, const gchar * helper_type, gpointer user_data) |
647 | +{ |
648 | + g_return_val_if_fail(observer != NULL, FALSE); |
649 | + g_return_val_if_fail(helper_type != NULL, FALSE); |
650 | + g_return_val_if_fail(g_strstr_len(helper_type, -1, ":") == NULL, FALSE); |
651 | + |
652 | + return delete_helper_generic(observer, helper_type, user_data, &helper_stopped_obs); |
653 | +} |
654 | + |
655 | |
656 | === modified file 'libupstart-app-launch/upstart-app-launch.h' |
657 | --- libupstart-app-launch/upstart-app-launch.h 2014-02-13 13:14:26 +0000 |
658 | +++ libupstart-app-launch/upstart-app-launch.h 2014-02-14 02:01:23 +0000 |
659 | @@ -59,6 +59,12 @@ |
660 | /* Backwards compatible. Drop when making API bump. */ |
661 | typedef UpstartAppLaunchAppFailedObserver upstart_app_launch_app_failed_observer_t; |
662 | |
663 | +/** |
664 | + * UpstartAppLaunchHelperObserver: |
665 | + * |
666 | + * Function to watch for helpers that are starting and stopping |
667 | + */ |
668 | +typedef void (*UpstartAppLaunchHelperObserver) (const gchar * appid, const gchar * instanceid, const gchar * helpertype, gpointer user_data); |
669 | |
670 | /** |
671 | * upstart_app_launch_start_application: |
672 | @@ -313,6 +319,152 @@ |
673 | const gchar * app, |
674 | const gchar * version); |
675 | |
676 | +/** |
677 | + * upstart_app_launch_start_helper: |
678 | + * @type: Type of helper |
679 | + * @appid: App ID of the helper |
680 | + * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper |
681 | + * |
682 | + * Start an untrusted helper for a specific @type on a given |
683 | + * @appid. We don't know how that is done specifically, as Upstart |
684 | + * will call a helper for that type. And then execute it under the |
685 | + * AppArmor profile for the helper as defined in its manifest. |
686 | + * |
687 | + * Return value: Whether the helper was able to be started |
688 | + */ |
689 | +gboolean upstart_app_launch_start_helper (const gchar * type, |
690 | + const gchar * appid, |
691 | + const gchar * const * uris); |
692 | + |
693 | +/** |
694 | + * upstart_app_launch_start_multiple_helper: |
695 | + * @type: Type of helper |
696 | + * @appid: App ID of the helper |
697 | + * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper |
698 | + * |
699 | + * Start an untrusted helper for a specific @type on a given |
700 | + * @appid. We don't know how that is done specifically, as Upstart |
701 | + * will call a helper for that type. And then execute it under the |
702 | + * Apparmor profile for that helper type. This function is different |
703 | + * from @upstart_app_launch_start_helper in that it works for helpers |
704 | + * that aren't single instance and the manager will be managing the |
705 | + * instances as well. |
706 | + * |
707 | + * Return value: The generated instance ID or NULL on failure |
708 | + */ |
709 | +gchar * upstart_app_launch_start_multiple_helper (const gchar * type, |
710 | + const gchar * appid, |
711 | + const gchar * const * uris); |
712 | + |
713 | +/** |
714 | + * upstart_app_launch_stop_helper: |
715 | + * @type: Type of helper |
716 | + * @appid: App ID of the helper |
717 | + * |
718 | + * Asks Upstart to kill a helper. In general, this should be a last resort |
719 | + * as we should ask the helper a better way probably with an in-band protocol |
720 | + * of use. |
721 | + * |
722 | + * Return value: Whether the helper is stopped |
723 | + */ |
724 | +gboolean upstart_app_launch_stop_helper (const gchar * type, |
725 | + const gchar * appid); |
726 | + |
727 | +/** |
728 | + * upstart_app_launch_stop_multiple_helper: |
729 | + * @type: Type of helper |
730 | + * @appid: App ID of the helper |
731 | + * @instanceid: The instance ID returned when starting the helper |
732 | + * |
733 | + * Asks Upstart to kill a helper. In general, this should be a last resort |
734 | + * as we should ask the helper a better way probably with an in-band protocol |
735 | + * of use. |
736 | + * |
737 | + * Return value: Whether the helper is stopped |
738 | + */ |
739 | +gboolean upstart_app_launch_stop_multiple_helper (const gchar * type, |
740 | + const gchar * appid, |
741 | + const gchar * instanceid); |
742 | + |
743 | +/** |
744 | + * upstart_app_launch_list_helpers: |
745 | + * @type: Type of helper |
746 | + * |
747 | + * List all App IDs of helpers of a given @type. |
748 | + * |
749 | + * Return value: (transfer full): List of application IDs |
750 | + */ |
751 | +gchar ** upstart_app_launch_list_helpers (const gchar * type); |
752 | + |
753 | +/** |
754 | + * upstart_app_launch_list_helper_instances: |
755 | + * @type: Type of helper |
756 | + * @appid: AppID of helper |
757 | + * |
758 | + * List all the instances for a particular AppID |
759 | + * |
760 | + * Return value: (transfer full): List of instance IDs |
761 | + */ |
762 | +gchar ** upstart_app_launch_list_helper_instances (const gchar * type, |
763 | + const gchar * appid); |
764 | + |
765 | + |
766 | +/** |
767 | + * upstart_app_launch_observer_add_helper_started: |
768 | + * @observer: (scope notified): Callback when a helper started |
769 | + * @helper_type: (closure) (allow-none): Type of helpers to look for |
770 | + * @user_data: (allow-none): Data to pass to the observer |
771 | + * |
772 | + * Sets up a callback to get called each time a helper of |
773 | + * @helper_type has been started. |
774 | + * |
775 | + * Return value: Whether adding the observer was successful. |
776 | + */ |
777 | +gboolean upstart_app_launch_observer_add_helper_started (UpstartAppLaunchHelperObserver observer, |
778 | + const gchar * helper_type, |
779 | + gpointer user_data); |
780 | +/** |
781 | + * upstart_app_launch_observer_add_helper_stop: |
782 | + * @observer: (scope notified): Callback when a helper stops |
783 | + * @helper_type: (closure) (allow-none): Type of helpers to look for |
784 | + * @user_data: (allow-none): Data to pass to the observer |
785 | + * |
786 | + * Sets up a callback to get called each time a helper of |
787 | + * @helper_type stops. |
788 | + * |
789 | + * Return value: Whether adding the observer was successful. |
790 | + */ |
791 | +gboolean upstart_app_launch_observer_add_helper_stop (UpstartAppLaunchHelperObserver observer, |
792 | + const gchar * helper_type, |
793 | + gpointer user_data); |
794 | +/** |
795 | + * upstart_app_launch_observer_delete_helper_started: |
796 | + * @observer: (scope notified): Callback to remove |
797 | + * @helper_type: (closure) (allow-none): Type of helpers it looked for |
798 | + * @user_data: (allow-none): Data that was passed to the observer |
799 | + * |
800 | + * Removes a previously registered callback to ensure it no longer |
801 | + * gets signaled. |
802 | + * |
803 | + * Return value: Whether deleting the observer was successful. |
804 | + */ |
805 | +gboolean upstart_app_launch_observer_delete_helper_started (UpstartAppLaunchHelperObserver observer, |
806 | + const gchar * helper_type, |
807 | + gpointer user_data); |
808 | +/** |
809 | + * upstart_app_launch_observer_delete_helper_stop: |
810 | + * @observer: (scope notified): Callback to remove |
811 | + * @helper_type: (closure) (allow-none): Type of helpers it looked for |
812 | + * @user_data: (allow-none): Data that was passed to the observer |
813 | + * |
814 | + * Removes a previously registered callback to ensure it no longer |
815 | + * gets signaled. |
816 | + * |
817 | + * Return value: Whether deleting the observer was successful. |
818 | + */ |
819 | +gboolean upstart_app_launch_observer_delete_helper_stop (UpstartAppLaunchHelperObserver observer, |
820 | + const gchar * helper_type, |
821 | + gpointer user_data); |
822 | |
823 | #ifdef __cplusplus |
824 | } |
825 | |
826 | === modified file 'tests/libual-test.cc' |
827 | --- tests/libual-test.cc 2014-02-13 13:14:14 +0000 |
828 | +++ tests/libual-test.cc 2014-02-14 02:01:23 +0000 |
829 | @@ -101,10 +101,13 @@ |
830 | G_VARIANT_TYPE("o"), |
831 | "if args[0] == 'application-click':\n" |
832 | " ret = dbus.ObjectPath('/com/test/application_click')\n" |
833 | - "else:\n" |
834 | - " ret = dbus.ObjectPath('/com/test/application_legacy')\n", |
835 | + "elif args[0] == 'application-legacy':\n" |
836 | + " ret = dbus.ObjectPath('/com/test/application_legacy')\n" |
837 | + "elif args[0] == 'untrusted-helper':\n" |
838 | + " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", |
839 | NULL); |
840 | |
841 | + /* Click App */ |
842 | DbusTestDbusMockObject * jobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL); |
843 | |
844 | dbus_test_dbus_mock_object_add_method(mock, jobobj, |
845 | @@ -143,6 +146,7 @@ |
846 | NULL); |
847 | g_free(process_var); |
848 | |
849 | + /* Legacy App */ |
850 | DbusTestDbusMockObject * ljobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_legacy", "com.ubuntu.Upstart0_6.Job", NULL); |
851 | |
852 | dbus_test_dbus_mock_object_add_method(mock, ljobobj, |
853 | @@ -178,6 +182,45 @@ |
854 | g_variant_new_parsed("[('main', 5678)]"), |
855 | NULL); |
856 | |
857 | + /* Untrusted Helper */ |
858 | + DbusTestDbusMockObject * uhelperobj = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
859 | + |
860 | + dbus_test_dbus_mock_object_add_method(mock, uhelperobj, |
861 | + "Start", |
862 | + G_VARIANT_TYPE("(asb)"), |
863 | + NULL, |
864 | + "", |
865 | + NULL); |
866 | + |
867 | + dbus_test_dbus_mock_object_add_method(mock, uhelperobj, |
868 | + "Stop", |
869 | + G_VARIANT_TYPE("(asb)"), |
870 | + NULL, |
871 | + "", |
872 | + NULL); |
873 | + |
874 | + dbus_test_dbus_mock_object_add_method(mock, uhelperobj, |
875 | + "GetAllInstances", |
876 | + NULL, |
877 | + G_VARIANT_TYPE("ao"), |
878 | + "ret = [ dbus.ObjectPath('/com/test/untrusted/helper/instance'), dbus.ObjectPath('/com/test/untrusted/helper/multi_instance') ]", |
879 | + NULL); |
880 | + |
881 | + DbusTestDbusMockObject * uhelperinstance = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper/instance", "com.ubuntu.Upstart0_6.Instance", NULL); |
882 | + dbus_test_dbus_mock_object_add_property(mock, uhelperinstance, |
883 | + "name", |
884 | + G_VARIANT_TYPE_STRING, |
885 | + g_variant_new_string("untrusted-type::com.foo_bar_43.23.12"), |
886 | + NULL); |
887 | + |
888 | + DbusTestDbusMockObject * unhelpermulti = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper/multi_instance", "com.ubuntu.Upstart0_6.Instance", NULL); |
889 | + dbus_test_dbus_mock_object_add_property(mock, unhelpermulti, |
890 | + "name", |
891 | + G_VARIANT_TYPE_STRING, |
892 | + g_variant_new_string("untrusted-type:24034582324132:com.bar_foo_8432.13.1"), |
893 | + NULL); |
894 | + |
895 | + /* Put it together */ |
896 | dbus_test_service_add_task(service, DBUS_TEST_TASK(mock)); |
897 | dbus_test_service_start_tasks(service); |
898 | |
899 | @@ -219,11 +262,15 @@ |
900 | return false; |
901 | } |
902 | |
903 | - gchar * combined = g_strdup_printf("%s=%s", var, value); |
904 | - if (g_strcmp0(envvar, combined) == 0) { |
905 | + if (value != NULL) { |
906 | + gchar * combined = g_strdup_printf("%s=%s", var, value); |
907 | + if (g_strcmp0(envvar, combined) == 0) { |
908 | + found = true; |
909 | + } |
910 | + g_free(combined); |
911 | + } else { |
912 | found = true; |
913 | } |
914 | - g_free(combined); |
915 | } |
916 | } |
917 | |
918 | @@ -838,3 +885,258 @@ |
919 | g_object_unref(session); |
920 | } |
921 | |
922 | +TEST_F(LibUAL, StartHelper) |
923 | +{ |
924 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
925 | + |
926 | + /* Basic make sure we can send the event */ |
927 | + ASSERT_TRUE(upstart_app_launch_start_helper("untrusted-type", "foolike", NULL)); |
928 | + EXPECT_EQ(1, dbus_test_dbus_mock_object_check_method_call(mock, obj, "Start", NULL, NULL)); |
929 | + |
930 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
931 | + |
932 | + /* Now look at the details of the call */ |
933 | + ASSERT_TRUE(upstart_app_launch_start_helper("untrusted-type", "foolike", NULL)); |
934 | + |
935 | + guint len = 0; |
936 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
937 | + EXPECT_NE(nullptr, calls); |
938 | + EXPECT_EQ(1, len); |
939 | + |
940 | + EXPECT_STREQ("Start", calls->name); |
941 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
942 | + |
943 | + GVariant * block = g_variant_get_child_value(calls->params, 1); |
944 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
945 | + g_variant_unref(block); |
946 | + |
947 | + GVariant * env = g_variant_get_child_value(calls->params, 0); |
948 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
949 | + EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
950 | + EXPECT_FALSE(check_env(env, "INSTANCE_ID", NULL)); |
951 | + g_variant_unref(env); |
952 | + |
953 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
954 | + |
955 | + /* Now check a multi out */ |
956 | + gchar * instance_id = upstart_app_launch_start_multiple_helper("untrusted-type", "foolike", NULL); |
957 | + ASSERT_NE(nullptr, instance_id); |
958 | + g_debug("Multi-instance ID: %s", instance_id); |
959 | + |
960 | + len = 0; |
961 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
962 | + EXPECT_NE(nullptr, calls); |
963 | + EXPECT_EQ(1, len); |
964 | + |
965 | + EXPECT_STREQ("Start", calls->name); |
966 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
967 | + |
968 | + block = g_variant_get_child_value(calls->params, 1); |
969 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
970 | + g_variant_unref(block); |
971 | + |
972 | + env = g_variant_get_child_value(calls->params, 0); |
973 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
974 | + EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
975 | + EXPECT_TRUE(check_env(env, "INSTANCE_ID", instance_id)); |
976 | + g_variant_unref(env); |
977 | + g_free(instance_id); |
978 | + |
979 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
980 | + |
981 | + /* Let's pass some URLs */ |
982 | + const gchar * urls[] = { |
983 | + "http://ubuntu.com/", |
984 | + "https://ubuntu.com/", |
985 | + "file:///home/phablet/test.txt", |
986 | + NULL |
987 | + }; |
988 | + ASSERT_TRUE(upstart_app_launch_start_helper("untrusted-type", "foolike", urls)); |
989 | + |
990 | + len = 0; |
991 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
992 | + EXPECT_NE(nullptr, calls); |
993 | + EXPECT_EQ(1, len); |
994 | + |
995 | + env = g_variant_get_child_value(calls->params, 0); |
996 | + EXPECT_TRUE(check_env(env, "APP_ID", "foolike")); |
997 | + EXPECT_TRUE(check_env(env, "APP_URIS", "'http://ubuntu.com/' 'https://ubuntu.com/' 'file:///home/phablet/test.txt'")); |
998 | + EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
999 | + EXPECT_FALSE(check_env(env, "INSTANCE_ID", NULL)); |
1000 | + g_variant_unref(env); |
1001 | + |
1002 | + return; |
1003 | +} |
1004 | + |
1005 | +TEST_F(LibUAL, StopHelper) |
1006 | +{ |
1007 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); |
1008 | + |
1009 | + /* Basic helper */ |
1010 | + ASSERT_TRUE(upstart_app_launch_stop_helper("untrusted-type", "foo")); |
1011 | + |
1012 | + ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "Stop", NULL, NULL), 1); |
1013 | + |
1014 | + guint len = 0; |
1015 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Stop", &len, NULL); |
1016 | + EXPECT_NE(nullptr, calls); |
1017 | + EXPECT_EQ(1, len); |
1018 | + |
1019 | + EXPECT_STREQ("Stop", calls->name); |
1020 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
1021 | + |
1022 | + GVariant * block = g_variant_get_child_value(calls->params, 1); |
1023 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
1024 | + g_variant_unref(block); |
1025 | + |
1026 | + GVariant * env = g_variant_get_child_value(calls->params, 0); |
1027 | + EXPECT_TRUE(check_env(env, "APP_ID", "foo")); |
1028 | + EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
1029 | + EXPECT_FALSE(check_env(env, "INSTANCE_ID", NULL)); |
1030 | + g_variant_unref(env); |
1031 | + |
1032 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
1033 | + |
1034 | + /* Multi helper */ |
1035 | + ASSERT_TRUE(upstart_app_launch_stop_multiple_helper("untrusted-type", "foo", "instance-me")); |
1036 | + |
1037 | + ASSERT_EQ(dbus_test_dbus_mock_object_check_method_call(mock, obj, "Stop", NULL, NULL), 1); |
1038 | + |
1039 | + len = 0; |
1040 | + calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Stop", &len, NULL); |
1041 | + EXPECT_NE(nullptr, calls); |
1042 | + EXPECT_EQ(1, len); |
1043 | + |
1044 | + EXPECT_STREQ("Stop", calls->name); |
1045 | + EXPECT_EQ(2, g_variant_n_children(calls->params)); |
1046 | + |
1047 | + block = g_variant_get_child_value(calls->params, 1); |
1048 | + EXPECT_TRUE(g_variant_get_boolean(block)); |
1049 | + g_variant_unref(block); |
1050 | + |
1051 | + env = g_variant_get_child_value(calls->params, 0); |
1052 | + EXPECT_TRUE(check_env(env, "APP_ID", "foo")); |
1053 | + EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); |
1054 | + EXPECT_TRUE(check_env(env, "INSTANCE_ID", "instance-me")); |
1055 | + g_variant_unref(env); |
1056 | + |
1057 | + ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); |
1058 | + |
1059 | + return; |
1060 | +} |
1061 | + |
1062 | +TEST_F(LibUAL, HelperList) |
1063 | +{ |
1064 | + gchar ** blanktype = upstart_app_launch_list_helpers("not-a-type"); |
1065 | + |
1066 | + EXPECT_NE(nullptr, blanktype); |
1067 | + EXPECT_EQ(0, g_strv_length(blanktype)); |
1068 | + |
1069 | + g_strfreev(blanktype); |
1070 | + |
1071 | + gchar ** goodtype = upstart_app_launch_list_helpers("untrusted-type"); |
1072 | + |
1073 | + EXPECT_NE(nullptr, goodtype); |
1074 | + EXPECT_EQ(2, g_strv_length(goodtype)); |
1075 | + |
1076 | + if (g_strcmp0(goodtype[0], "com.foo_bar_43.23.12") == 0) { |
1077 | + EXPECT_STREQ("com.foo_bar_43.23.12", goodtype[0]); |
1078 | + EXPECT_STREQ("com.bar_foo_8432.13.1", goodtype[1]); |
1079 | + } else { |
1080 | + EXPECT_STREQ("com.foo_bar_43.23.12", goodtype[1]); |
1081 | + EXPECT_STREQ("com.bar_foo_8432.13.1", goodtype[0]); |
1082 | + } |
1083 | + |
1084 | + g_strfreev(goodtype); |
1085 | +} |
1086 | + |
1087 | +TEST_F(LibUAL, HelperInstanceList) |
1088 | +{ |
1089 | + gchar ** blanktype = upstart_app_launch_list_helper_instances("not-a-type", "com.bar_foo_8432.13.1"); |
1090 | + |
1091 | + EXPECT_NE(nullptr, blanktype); |
1092 | + EXPECT_EQ(0, g_strv_length(blanktype)); |
1093 | + |
1094 | + g_strfreev(blanktype); |
1095 | + |
1096 | + gchar ** goodtype = upstart_app_launch_list_helper_instances("untrusted-type", "com.bar_foo_8432.13.1"); |
1097 | + |
1098 | + EXPECT_NE(nullptr, goodtype); |
1099 | + EXPECT_EQ(1, g_strv_length(goodtype)); |
1100 | + EXPECT_STREQ("24034582324132", goodtype[0]); |
1101 | + |
1102 | + g_strfreev(goodtype); |
1103 | +} |
1104 | + |
1105 | + |
1106 | +typedef struct { |
1107 | + unsigned int count; |
1108 | + const gchar * appid; |
1109 | + const gchar * type; |
1110 | + const gchar * instance; |
1111 | +} helper_observer_data_t; |
1112 | + |
1113 | +static void |
1114 | +helper_observer_cb (const gchar * appid, const gchar * instance, const gchar * type, gpointer user_data) |
1115 | +{ |
1116 | + helper_observer_data_t * data = (helper_observer_data_t *)user_data; |
1117 | + |
1118 | + if (g_strcmp0(data->appid, appid) == 0 && |
1119 | + g_strcmp0(data->type, type) == 0 && |
1120 | + g_strcmp0(data->instance, instance) == 0) { |
1121 | + data->count++; |
1122 | + } |
1123 | +} |
1124 | + |
1125 | +TEST_F(LibUAL, StartStopHelperObserver) |
1126 | +{ |
1127 | + helper_observer_data_t start_data = { |
1128 | + .count = 0, |
1129 | + .appid = "com.foo_foo_1.2.3", |
1130 | + .type = "my-type-is-scorpio", |
1131 | + .instance = nullptr |
1132 | + }; |
1133 | + helper_observer_data_t stop_data = { |
1134 | + .count = 0, |
1135 | + .appid = "com.bar_bar_44.32", |
1136 | + .type = "my-type-is-libra", |
1137 | + .instance = "1234" |
1138 | + }; |
1139 | + |
1140 | + ASSERT_TRUE(upstart_app_launch_observer_add_helper_started(helper_observer_cb, "my-type-is-scorpio", &start_data)); |
1141 | + ASSERT_TRUE(upstart_app_launch_observer_add_helper_stop(helper_observer_cb, "my-type-is-libra", &stop_data)); |
1142 | + |
1143 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); |
1144 | + |
1145 | + /* Basic start */ |
1146 | + dbus_test_dbus_mock_object_emit_signal(mock, obj, |
1147 | + "EventEmitted", |
1148 | + G_VARIANT_TYPE("(sas)"), |
1149 | + g_variant_new_parsed("('started', ['JOB=untrusted-helper', 'INSTANCE=my-type-is-scorpio::com.foo_foo_1.2.3'])"), |
1150 | + NULL |
1151 | + ); |
1152 | + |
1153 | + g_usleep(100000); |
1154 | + while (g_main_pending()) |
1155 | + g_main_iteration(TRUE); |
1156 | + |
1157 | + ASSERT_EQ(start_data.count, 1); |
1158 | + |
1159 | + /* Basic stop */ |
1160 | + dbus_test_dbus_mock_object_emit_signal(mock, obj, |
1161 | + "EventEmitted", |
1162 | + G_VARIANT_TYPE("(sas)"), |
1163 | + g_variant_new_parsed("('stopped', ['JOB=untrusted-helper', 'INSTANCE=my-type-is-libra:1234:com.bar_bar_44.32'])"), |
1164 | + NULL |
1165 | + ); |
1166 | + |
1167 | + g_usleep(100000); |
1168 | + while (g_main_pending()) |
1169 | + g_main_iteration(TRUE); |
1170 | + |
1171 | + ASSERT_EQ(stop_data.count, 1); |
1172 | + |
1173 | + /* Remove */ |
1174 | + ASSERT_TRUE(upstart_app_launch_observer_delete_helper_started(helper_observer_cb, "my-type-is-scorpio", &start_data)); |
1175 | + ASSERT_TRUE(upstart_app_launch_observer_delete_helper_stop(helper_observer_cb, "my-type-is-libra", &stop_data)); |
1176 | +} |
1177 | |
1178 | === modified file 'tests/manual' |
1179 | --- tests/manual 2014-02-04 21:24:12 +0000 |
1180 | +++ tests/manual 2014-02-14 02:01:23 +0000 |
1181 | @@ -28,6 +28,21 @@ |
1182 | <dd>The settings application should come back into focus and be on the power settings pane</dd> |
1183 | </dl> |
1184 | |
1185 | +Test-case upstart-app-launch/helper-run |
1186 | +<dl> |
1187 | + <dt>NOTE: Test is theoretical today, needs other components to be written</dt> |
1188 | + <dt>Get a device that supports sending SMS</dt> |
1189 | + <dd>Typically this is a phone</dd> |
1190 | + <dt>Note the SMS sent count visible on the lock screen infographic for this user</dt> |
1191 | + <dt>Start the messaging app</dt> |
1192 | + <dt>Send an SMS</dt> |
1193 | + <dd>SMS should report as being sent successfully</dd> |
1194 | + <dt>Wait approximately 1 minute</dt> |
1195 | + <dd>Screen should lock</dd> |
1196 | + <dt>Look at the lock screen infographic for the SMS sent count</dt> |
1197 | + <dd>Count should have incremented by 1</dd> |
1198 | +</dl> |
1199 | + |
1200 | Test-case upstart-app-launch/security-app-launch |
1201 | <dl> |
1202 | <dt>Setup the security tests: https://wiki.ubuntu.com/Touch/Testing#Running_Security_tests</dt> |
1203 | |
1204 | === added directory 'tools' |
1205 | === added file 'tools/CMakeLists.txt' |
1206 | --- tools/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1207 | +++ tools/CMakeLists.txt 2014-02-14 02:01:23 +0000 |
1208 | @@ -0,0 +1,73 @@ |
1209 | + |
1210 | +######################## |
1211 | +# upstart-app-list |
1212 | +######################## |
1213 | + |
1214 | +add_executable(upstart-app-list upstart-app-list.c) |
1215 | +set_target_properties(upstart-app-list PROPERTIES OUTPUT_NAME "upstart-app-list") |
1216 | +target_link_libraries(upstart-app-list upstart-launcher) |
1217 | +install(TARGETS upstart-app-list RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1218 | + |
1219 | +######################## |
1220 | +# upstart-app-launch |
1221 | +######################## |
1222 | + |
1223 | +add_executable(upstart-app-launch upstart-app-launch.c) |
1224 | +set_target_properties(upstart-app-launch PROPERTIES OUTPUT_NAME "upstart-app-launch") |
1225 | +target_link_libraries(upstart-app-launch upstart-launcher) |
1226 | +install(TARGETS upstart-app-launch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1227 | + |
1228 | +######################## |
1229 | +# upstart-app-watch |
1230 | +######################## |
1231 | + |
1232 | +add_executable(upstart-app-watch upstart-app-watch.c) |
1233 | +set_target_properties(upstart-app-watch PROPERTIES OUTPUT_NAME "upstart-app-watch") |
1234 | +target_link_libraries(upstart-app-watch upstart-launcher) |
1235 | +install(TARGETS upstart-app-watch RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1236 | + |
1237 | +######################## |
1238 | +# upstart-app-pid |
1239 | +######################## |
1240 | + |
1241 | +add_executable(upstart-app-pid upstart-app-pid.c) |
1242 | +set_target_properties(upstart-app-pid PROPERTIES OUTPUT_NAME "upstart-app-pid") |
1243 | +target_link_libraries(upstart-app-pid upstart-launcher) |
1244 | +install(TARGETS upstart-app-pid RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1245 | + |
1246 | +######################## |
1247 | +# upstart-app-stop |
1248 | +######################## |
1249 | + |
1250 | +add_executable(upstart-app-stop upstart-app-stop.c) |
1251 | +set_target_properties(upstart-app-stop PROPERTIES OUTPUT_NAME "upstart-app-stop") |
1252 | +target_link_libraries(upstart-app-stop upstart-launcher) |
1253 | +install(TARGETS upstart-app-stop RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1254 | + |
1255 | +######################## |
1256 | +# upstart-helper-start |
1257 | +######################## |
1258 | + |
1259 | +add_executable(upstart-helper-start upstart-helper-start.c) |
1260 | +set_target_properties(upstart-helper-start PROPERTIES OUTPUT_NAME "upstart-helper-start") |
1261 | +target_link_libraries(upstart-helper-start upstart-launcher) |
1262 | +install(TARGETS upstart-helper-start RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1263 | + |
1264 | +######################## |
1265 | +# upstart-helper-stop |
1266 | +######################## |
1267 | + |
1268 | +add_executable(upstart-helper-stop upstart-helper-stop.c) |
1269 | +set_target_properties(upstart-helper-stop PROPERTIES OUTPUT_NAME "upstart-helper-stop") |
1270 | +target_link_libraries(upstart-helper-stop upstart-launcher) |
1271 | +install(TARGETS upstart-helper-stop RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1272 | + |
1273 | +######################## |
1274 | +# upstart-helper-list |
1275 | +######################## |
1276 | + |
1277 | +add_executable(upstart-helper-list upstart-helper-list.c) |
1278 | +set_target_properties(upstart-helper-list PROPERTIES OUTPUT_NAME "upstart-helper-list") |
1279 | +target_link_libraries(upstart-helper-list upstart-launcher) |
1280 | +install(TARGETS upstart-helper-list RUNTIME DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}") |
1281 | + |
1282 | |
1283 | === renamed file 'upstart-app-launch.c' => 'tools/upstart-app-launch.c' |
1284 | === renamed file 'upstart-app-list.c' => 'tools/upstart-app-list.c' |
1285 | === renamed file 'upstart-app-pid.c' => 'tools/upstart-app-pid.c' |
1286 | === renamed file 'upstart-app-stop.c' => 'tools/upstart-app-stop.c' |
1287 | === renamed file 'upstart-app-watch.c' => 'tools/upstart-app-watch.c' |
1288 | === added file 'tools/upstart-helper-list.c' |
1289 | --- tools/upstart-helper-list.c 1970-01-01 00:00:00 +0000 |
1290 | +++ tools/upstart-helper-list.c 2014-02-14 02:01:23 +0000 |
1291 | @@ -0,0 +1,50 @@ |
1292 | +/* |
1293 | + * Copyright © 2014 Canonical Ltd. |
1294 | + * |
1295 | + * This program is free software: you can redistribute it and/or modify it |
1296 | + * under the terms of the GNU General Public License version 3, as published |
1297 | + * by the Free Software Foundation. |
1298 | + * |
1299 | + * This program is distributed in the hope that it will be useful, but |
1300 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1301 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1302 | + * PURPOSE. See the GNU General Public License for more details. |
1303 | + * |
1304 | + * You should have received a copy of the GNU General Public License along |
1305 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1306 | + * |
1307 | + * Authors: |
1308 | + * Ted Gould <ted.gould@canonical.com> |
1309 | + */ |
1310 | + |
1311 | +#include "libupstart-app-launch/upstart-app-launch.h" |
1312 | +#include <gio/gio.h> |
1313 | + |
1314 | +int |
1315 | +main (int argc, gchar * argv[]) { |
1316 | + if (argc != 2) { |
1317 | + g_printerr("Usage: %s <helper type>\n", argv[0]); |
1318 | + return 1; |
1319 | + } |
1320 | + |
1321 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1322 | + g_return_val_if_fail(con != NULL, -1); |
1323 | + |
1324 | + gchar ** appids = upstart_app_launch_list_helpers(argv[1]); |
1325 | + if (appids == NULL) { |
1326 | + g_warning("Error getting App IDs for helper type '%s'", argv[1]); |
1327 | + return -1; |
1328 | + } |
1329 | + |
1330 | + int i; |
1331 | + for (i = 0; appids[i] != NULL; i++) { |
1332 | + g_print("%s\n", appids[i]); |
1333 | + } |
1334 | + |
1335 | + g_strfreev(appids); |
1336 | + |
1337 | + g_dbus_connection_flush_sync(con, NULL, NULL); |
1338 | + g_object_unref(con); |
1339 | + |
1340 | + return 0; |
1341 | +} |
1342 | |
1343 | === added file 'tools/upstart-helper-start.c' |
1344 | --- tools/upstart-helper-start.c 1970-01-01 00:00:00 +0000 |
1345 | +++ tools/upstart-helper-start.c 2014-02-14 02:01:23 +0000 |
1346 | @@ -0,0 +1,46 @@ |
1347 | +/* |
1348 | + * Copyright © 2014 Canonical Ltd. |
1349 | + * |
1350 | + * This program is free software: you can redistribute it and/or modify it |
1351 | + * under the terms of the GNU General Public License version 3, as published |
1352 | + * by the Free Software Foundation. |
1353 | + * |
1354 | + * This program is distributed in the hope that it will be useful, but |
1355 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1356 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1357 | + * PURPOSE. See the GNU General Public License for more details. |
1358 | + * |
1359 | + * You should have received a copy of the GNU General Public License along |
1360 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1361 | + * |
1362 | + * Authors: |
1363 | + * Ted Gould <ted.gould@canonical.com> |
1364 | + */ |
1365 | + |
1366 | +#include "libupstart-app-launch/upstart-app-launch.h" |
1367 | +#include <gio/gio.h> |
1368 | + |
1369 | +int |
1370 | +main (int argc, gchar * argv[]) { |
1371 | + if (argc != 3) { |
1372 | + g_printerr("Usage: %s <helper type> <app id>\n", argv[0]); |
1373 | + return 1; |
1374 | + } |
1375 | + |
1376 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1377 | + g_return_val_if_fail(con != NULL, -1); |
1378 | + |
1379 | + int retval = -1; |
1380 | + |
1381 | + /* TODO: Allow URIs */ |
1382 | + if (upstart_app_launch_start_helper(argv[1], argv[2], NULL)) { |
1383 | + retval = 0; |
1384 | + } else { |
1385 | + g_debug("Unable to start app id '%s' of type '%s'", argv[2], argv[1]); |
1386 | + } |
1387 | + |
1388 | + g_dbus_connection_flush_sync(con, NULL, NULL); |
1389 | + g_object_unref(con); |
1390 | + |
1391 | + return retval; |
1392 | +} |
1393 | |
1394 | === added file 'tools/upstart-helper-stop.c' |
1395 | --- tools/upstart-helper-stop.c 1970-01-01 00:00:00 +0000 |
1396 | +++ tools/upstart-helper-stop.c 2014-02-14 02:01:23 +0000 |
1397 | @@ -0,0 +1,45 @@ |
1398 | +/* |
1399 | + * Copyright © 2014 Canonical Ltd. |
1400 | + * |
1401 | + * This program is free software: you can redistribute it and/or modify it |
1402 | + * under the terms of the GNU General Public License version 3, as published |
1403 | + * by the Free Software Foundation. |
1404 | + * |
1405 | + * This program is distributed in the hope that it will be useful, but |
1406 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1407 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1408 | + * PURPOSE. See the GNU General Public License for more details. |
1409 | + * |
1410 | + * You should have received a copy of the GNU General Public License along |
1411 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1412 | + * |
1413 | + * Authors: |
1414 | + * Ted Gould <ted.gould@canonical.com> |
1415 | + */ |
1416 | + |
1417 | +#include "libupstart-app-launch/upstart-app-launch.h" |
1418 | +#include <gio/gio.h> |
1419 | + |
1420 | +int |
1421 | +main (int argc, gchar * argv[]) { |
1422 | + if (argc != 3) { |
1423 | + g_printerr("Usage: %s <helper type> <app id>\n", argv[0]); |
1424 | + return 1; |
1425 | + } |
1426 | + |
1427 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1428 | + g_return_val_if_fail(con != NULL, -1); |
1429 | + |
1430 | + int retval = -1; |
1431 | + |
1432 | + if (upstart_app_launch_stop_helper(argv[1], argv[2])) { |
1433 | + retval = 0; |
1434 | + } else { |
1435 | + g_debug("Unable to stop app id '%s' of type '%s'", argv[2], argv[1]); |
1436 | + } |
1437 | + |
1438 | + g_dbus_connection_flush_sync(con, NULL, NULL); |
1439 | + g_object_unref(con); |
1440 | + |
1441 | + return retval; |
1442 | +} |
1443 | |
1444 | === added file 'untrusted-helper-type-end.c' |
1445 | --- untrusted-helper-type-end.c 1970-01-01 00:00:00 +0000 |
1446 | +++ untrusted-helper-type-end.c 2014-02-14 02:01:23 +0000 |
1447 | @@ -0,0 +1,66 @@ |
1448 | +/* |
1449 | + * Copyright © 2014 Canonical Ltd. |
1450 | + * |
1451 | + * This program is free software: you can redistribute it and/or modify it |
1452 | + * under the terms of the GNU General Public License version 3, as published |
1453 | + * by the Free Software Foundation. |
1454 | + * |
1455 | + * This program is distributed in the hope that it will be useful, but |
1456 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
1457 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
1458 | + * PURPOSE. See the GNU General Public License for more details. |
1459 | + * |
1460 | + * You should have received a copy of the GNU General Public License along |
1461 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
1462 | + * |
1463 | + * Authors: |
1464 | + * Ted Gould <ted.gould@canonical.com> |
1465 | + */ |
1466 | + |
1467 | +#include "libupstart-app-launch/upstart-app-launch.h" |
1468 | +#include <gio/gio.h> |
1469 | + |
1470 | +int |
1471 | +main (int argc, gchar * argv[]) { |
1472 | + const gchar * type = g_getenv("HELPER_TYPE"); |
1473 | + g_return_val_if_fail(type != NULL, -1); |
1474 | + |
1475 | + GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); |
1476 | + g_return_val_if_fail(con != NULL, -1); |
1477 | + |
1478 | + gchar ** appids = upstart_app_launch_list_helpers(type); |
1479 | + if (appids == NULL) { |
1480 | + g_warning("Error getting App IDs for helper type '%s'", argv[1]); |
1481 | + return -1; |
1482 | + } |
1483 | + |
1484 | + int i; |
1485 | + for (i = 0; appids[i] != NULL; i++) { |
1486 | + gchar ** instances = upstart_app_launch_list_helper_instances(type, appids[i]); |
1487 | + guint instance_cnt = g_strv_length(instances); |
1488 | + |
1489 | + if (instance_cnt == 0) { |
1490 | + g_debug("Stopping %s", appids[i]); |
1491 | + if (!upstart_app_launch_stop_helper(type, appids[i])) { |
1492 | + g_warning("Unable to stop '%s'", appids[i]); |
1493 | + } |
1494 | + } else { |
1495 | + int j; |
1496 | + for (j = 0; j < instance_cnt; j++) { |
1497 | + g_debug("Stopping %s (%s)", appids[i], instances[j]); |
1498 | + if (!upstart_app_launch_stop_multiple_helper(type, appids[i], instances[j])) { |
1499 | + g_warning("Unable to stop '%s' instance '%s'", appids[i], instances[j]); |
1500 | + } |
1501 | + } |
1502 | + } |
1503 | + |
1504 | + g_strfreev(instances); |
1505 | + } |
1506 | + |
1507 | + g_strfreev(appids); |
1508 | + |
1509 | + g_dbus_connection_flush_sync(con, NULL, NULL); |
1510 | + g_object_unref(con); |
1511 | + |
1512 | + return 0; |
1513 | +} |
1514 | |
1515 | === added directory 'upstart-jobs' |
1516 | === added file 'upstart-jobs/CMakeLists.txt' |
1517 | --- upstart-jobs/CMakeLists.txt 1970-01-01 00:00:00 +0000 |
1518 | +++ upstart-jobs/CMakeLists.txt 2014-02-14 02:01:23 +0000 |
1519 | @@ -0,0 +1,49 @@ |
1520 | + |
1521 | +#################### |
1522 | +# application.conf |
1523 | +#################### |
1524 | + |
1525 | +configure_file("application.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application.conf" @ONLY) |
1526 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
1527 | +add_test(application.conf.test "${CMAKE_CURRENT_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application.conf") |
1528 | + |
1529 | +#################### |
1530 | +# application-legacy.conf |
1531 | +#################### |
1532 | + |
1533 | +configure_file("application-legacy.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-legacy.conf" @ONLY) |
1534 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-legacy.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
1535 | +add_test(application-legacy.conf.test "${CMAKE_CURRENT_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-legacy.conf") |
1536 | + |
1537 | +#################### |
1538 | +# application-click.conf |
1539 | +#################### |
1540 | + |
1541 | +configure_file("application-click.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf" @ONLY) |
1542 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
1543 | +add_test(application-click.conf.test "${CMAKE_CURRENT_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-click.conf") |
1544 | + |
1545 | +#################### |
1546 | +# application-failed.conf |
1547 | +#################### |
1548 | + |
1549 | +configure_file("application-failed.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf" @ONLY) |
1550 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
1551 | +add_test(application-failed.conf.test "${CMAKE_CURRENT_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/application-failed.conf") |
1552 | + |
1553 | +#################### |
1554 | +# untrusted-helper.conf |
1555 | +#################### |
1556 | + |
1557 | +configure_file("untrusted-helper.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/untrusted-helper.conf" @ONLY) |
1558 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/untrusted-helper.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
1559 | +add_test(untrusted-helper.conf.test "${CMAKE_CURRENT_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/untrusted-helper.conf") |
1560 | + |
1561 | +#################### |
1562 | +# untrusted-helper-type-end.conf |
1563 | +#################### |
1564 | + |
1565 | +configure_file("untrusted-helper-type-end.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/untrusted-helper-type-end.conf" @ONLY) |
1566 | +install(FILES "${CMAKE_CURRENT_BINARY_DIR}/untrusted-helper-type-end.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions") |
1567 | +add_test(untrusted-helper-type-end.conf.test "${CMAKE_CURRENT_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/untrusted-helper-type-end.conf") |
1568 | + |
1569 | |
1570 | === renamed file 'application-click.conf.in' => 'upstart-jobs/application-click.conf.in' |
1571 | === renamed file 'application-failed.conf.in' => 'upstart-jobs/application-failed.conf.in' |
1572 | === renamed file 'application-legacy.conf.in' => 'upstart-jobs/application-legacy.conf.in' |
1573 | === renamed file 'application.conf.in' => 'upstart-jobs/application.conf.in' |
1574 | === renamed file 'test-conffile.sh' => 'upstart-jobs/test-conffile.sh' |
1575 | === added file 'upstart-jobs/untrusted-helper-type-end.conf.in' |
1576 | --- upstart-jobs/untrusted-helper-type-end.conf.in 1970-01-01 00:00:00 +0000 |
1577 | +++ upstart-jobs/untrusted-helper-type-end.conf.in 2014-02-14 02:01:23 +0000 |
1578 | @@ -0,0 +1,9 @@ |
1579 | +description "End all untrusted helpers of a particular type, usually when the manager ends" |
1580 | + |
1581 | +start on untrusted-helper-type-end |
1582 | + |
1583 | +instance ${HELPER_TYPE} |
1584 | + |
1585 | +emits untrusted-helper-end |
1586 | + |
1587 | +exec @pkglibexecdir@/untrusted-helper-type-end |
1588 | |
1589 | === added file 'upstart-jobs/untrusted-helper.conf.in' |
1590 | --- upstart-jobs/untrusted-helper.conf.in 1970-01-01 00:00:00 +0000 |
1591 | +++ upstart-jobs/untrusted-helper.conf.in 2014-02-14 02:01:23 +0000 |
1592 | @@ -0,0 +1,31 @@ |
1593 | +description "Untrusted Helpers installed from Click Packages" |
1594 | + |
1595 | +start on untrusted-helper-start |
1596 | +stop on untrusted-helper-end or desktop-end |
1597 | + |
1598 | +instance ${HELPER_TYPE}:${INSTANCE_ID}:${APP_ID} |
1599 | + |
1600 | +env APP_ID |
1601 | +env APP_EXEC="echo Error" |
1602 | +env HELPER_TYPE |
1603 | +env INSTANCE_ID="" |
1604 | +env APP_URIS |
1605 | + |
1606 | +env UPSTART_APP_LAUNCH_ARCH="@upstart_app_launch_arch@" |
1607 | +export UPSTART_APP_LAUNCH_ARCH |
1608 | + |
1609 | +apparmor switch ${APP_ID} |
1610 | +oom score 800 |
1611 | + |
1612 | +# This is unconfined |
1613 | +pre-start script |
1614 | + if [ -x "@pkglibexecdir@/${HELPER_TYPE}/exec-tool" ] ; then |
1615 | + @pkglibexecdir@/${HELPER_TYPE}/exec-tool |
1616 | + else |
1617 | + echo "Unable to find exec tool for ${HELPER_TYPE}" |
1618 | + exit -1 |
1619 | + fi |
1620 | +end script |
1621 | + |
1622 | +# Remember, this is confined |
1623 | +exec @pkglibexecdir@/exec-line-exec |
PASSED: Continuous integration, rev:126 jenkins. qa.ubuntu. com/job/ upstart- app-launch- ci/218/ jenkins. qa.ubuntu. com/job/ upstart- app-launch- trusty- amd64-ci/ 77 jenkins. qa.ubuntu. com/job/ upstart- app-launch- trusty- armhf-ci/ 77 jenkins. qa.ubuntu. com/job/ upstart- app-launch- trusty- i386-ci/ 78
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/218/ rebuild
http://