Merge lp:~ted/ubuntu-app-launch/untrusted-helper into lp:ubuntu-app-launch/14.04

Proposed by Ted Gould
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
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.

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
127. By Ted Gould

Merge trunk

128. By Ted Gould

Grabbing the MR Policy branch

129. By Ted Gould

Add a verification step and a test case for untrusted helpers

130. By Ted Gould

Update to trunk

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
131. By Ted Gould

Update description for a better idea of where the AppArmor profile comes from

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
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-helper-type-end.c calls g_strv_length(instances) more often than necessary

review: Needs Fixing
Revision history for this message
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-helper-type-end.c calls g_strv_length(instances) more often than necessary

Fixed r134

Also, pulled through application-job-to-c changes to resolve conflicts.

132. By Ted Gould

Merging application-job-to-c to resolve conflicts

133. By Ted Gould

Make sure to free the created URIs join string

134. By Ted Gould

Save a count of the instances

Revision history for this message
Charles Kerr (charlesk) :
review: Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
135. By Ted Gould

Merge trusty-proposed

136. By Ted Gould

Helper GIR annotations enhancement

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
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

Subscribers

People subscribed via source and target branches