Merge lp:~ted/ubuntu-app-launch/libual-desktop-file into lp:ubuntu-app-launch/15.04

Proposed by Ted Gould
Status: Superseded
Proposed branch: lp:~ted/ubuntu-app-launch/libual-desktop-file
Merge into: lp:ubuntu-app-launch/15.04
Diff against target: 2534 lines (+1778/-88) (has conflicts)
42 files modified
CMakeLists.txt (+22/-2)
cmake/UseGdbusCodegen.cmake (+21/-20)
data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml (+8/-0)
debian/changelog (+22/-0)
debian/control (+2/-1)
debian/libubuntu-app-launch2.symbols (+2/-0)
exec-line-exec-trace.tp (+6/-0)
exec-line-exec.c (+14/-0)
helpers-shared.c (+1/-1)
helpers.h (+2/-0)
libubuntu-app-launch/CMakeLists.txt (+12/-3)
libubuntu-app-launch/click-exec.c (+8/-0)
libubuntu-app-launch/desktop-exec.c (+95/-2)
libubuntu-app-launch/desktop-exec.h (+3/-1)
libubuntu-app-launch/ubuntu-app-launch-trace.tp (+7/-0)
libubuntu-app-launch/ubuntu-app-launch.c (+534/-13)
libubuntu-app-launch/ubuntu-app-launch.h (+56/-1)
libubuntu-app-launch/ubuntu-app-launch.pc.in (+1/-1)
socket-demangler.c (+124/-0)
tests/CMakeLists.txt (+15/-1)
tests/applications/noxmir.desktop (+8/-0)
tests/applications/xmir.desktop (+8/-0)
tests/click-app-dir/.click/info/com.test.mir.manifest (+11/-0)
tests/click-app-dir/noxmir.desktop (+8/-0)
tests/click-app-dir/xmir.desktop (+8/-0)
tests/exec-util-test.cc (+257/-0)
tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop (+4/-0)
tests/libual-test.cc (+197/-27)
tests/link-farm/com.test.mir_mir_1.desktop (+1/-0)
tests/link-farm/com.test.mir_nomir_1.desktop (+1/-0)
tests/mir-mock.cpp (+106/-0)
tests/mir-mock.h (+12/-0)
tests/socket-tool.c (+28/-0)
tests/xmir-helper-exec.sh (+3/-0)
tests/xmir-helper-test.in (+25/-0)
tests/xmir-mock.sh (+22/-0)
ubuntu-app-test/CMakeLists.txt (+0/-8)
ubuntu-app-test/ubuntu-app-test (+0/-6)
upstart-jobs/application-click.conf.in (+3/-0)
upstart-jobs/application-legacy.conf.in (+3/-0)
xmir-helper.c (+117/-0)
zg-report-app.c (+1/-1)
Text conflict in debian/changelog
To merge this branch: bzr merge lp:~ted/ubuntu-app-launch/libual-desktop-file
Reviewer Review Type Date Requested Status
Indicator Applet Developers Pending
Review via email: mp+255841@code.launchpad.net

This proposal has been superseded by a proposal from 2015-08-07.

To post a comment you must log in.
196. By Ted Gould

Grab the libertine detection branch so that we can do that too.

197. By Ted Gould

Adding a function description

198. By Ted Gould

Insert a libertine handler

199. By Ted Gould

Flesh out the libertine app info function

200. By Ted Gould

Adding new symbol into the symbols file

201. By Ted Gould

Make it so that we can use the libertine data in the tests

202. By Ted Gould

Updating to latest libertine-detection

203. By Ted Gould

Move the code into the app-info file

204. By Ted Gould

Merge the app-info refactoring

205. By Ted Gould

Grab triplet tests

206. By Ted Gould

App info tests

207. By Ted Gould

Make it so the libertine app info behaves like the others

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'CMakeLists.txt'
--- CMakeLists.txt 2015-03-05 02:59:41 +0000
+++ CMakeLists.txt 2015-08-07 02:13:47 +0000
@@ -36,7 +36,8 @@
36)36)
37set(ubuntu_app_launch_arch "${UBUNTU_APP_LAUNCH_ARCH}")37set(ubuntu_app_launch_arch "${UBUNTU_APP_LAUNCH_ARCH}")
3838
39set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wno-error=unused-function -std=c99")39# Deprecated needed for g_atexit() in libual
40set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wno-error=unused-function -Wno-error=deprecated-declarations -std=c99")
4041
41enable_testing()42enable_testing()
4243
@@ -46,7 +47,7 @@
46pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0)47pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0)
47include_directories(${GOBJECT2_INCLUDE_DIRS})48include_directories(${GOBJECT2_INCLUDE_DIRS})
4849
49pkg_check_modules(GIO2 REQUIRED gio-2.0)50pkg_check_modules(GIO2 REQUIRED gio-2.0 gio-unix-2.0)
50include_directories(${GIO2_INCLUDE_DIRS})51include_directories(${GIO2_INCLUDE_DIRS})
5152
52pkg_check_modules(JSONGLIB REQUIRED json-glib-1.0)53pkg_check_modules(JSONGLIB REQUIRED json-glib-1.0)
@@ -80,6 +81,8 @@
8081
81set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC")82set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC")
8283
84add_definitions( -DXMIR_HELPER="${pkglibexecdir}/xmir-helper" )
85
83####################86####################
84# Helpers87# Helpers
85####################88####################
@@ -135,6 +138,14 @@
135install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}")138install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}")
136139
137####################140####################
141# xmir-helper
142####################
143
144add_executable(xmir-helper xmir-helper.c)
145set_target_properties(xmir-helper PROPERTIES OUTPUT_NAME "xmir-helper")
146install(TARGETS xmir-helper RUNTIME DESTINATION "${pkglibexecdir}")
147
148####################
138# untrusted-helper-type-end149# untrusted-helper-type-end
139####################150####################
140151
@@ -161,6 +172,15 @@
161install(TARGETS oom-adjust-setuid-helper RUNTIME DESTINATION "${pkglibexecdir}")172install(TARGETS oom-adjust-setuid-helper RUNTIME DESTINATION "${pkglibexecdir}")
162173
163####################174####################
175# socket-demangler
176####################
177
178add_executable(socket-demangler-helper socket-demangler.c)
179set_target_properties(socket-demangler-helper PROPERTIES OUTPUT_NAME "socket-demangler")
180target_link_libraries(socket-demangler-helper ${GIO2_LIBRARIES})
181install(TARGETS socket-demangler-helper RUNTIME DESTINATION "${pkglibexecdir}")
182
183####################
164# ubuntu-app-launch-desktop.click-hook184# ubuntu-app-launch-desktop.click-hook
165####################185####################
166186
167187
=== modified file 'cmake/UseGdbusCodegen.cmake'
--- cmake/UseGdbusCodegen.cmake 2013-07-24 21:13:19 +0000
+++ cmake/UseGdbusCodegen.cmake 2015-08-07 02:13:47 +0000
@@ -8,28 +8,29 @@
8 message(FATAL_ERROR "Excutable gdbus-codegen not found")8 message(FATAL_ERROR "Excutable gdbus-codegen not found")
9endif()9endif()
1010
11function(add_gdbus_codegen)11macro(add_gdbus_codegen outfiles name prefix service_xml)
12 set(_one_value OUTFILES NAME PREFIX NAMESPACE SERVICE_XML)12 add_custom_command(
13 set(_multi_value DEPENDS)13 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
14 cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN})14 COMMAND "${GDBUS_CODEGEN}"
15 --interface-prefix "${prefix}"
16 --generate-c-code "${name}"
17 "${service_xml}"
18 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
19 DEPENDS ${ARGN} "${service_xml}"
20 )
21 list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
22endmacro(add_gdbus_codegen)
1523
16 if(arg_PREFIX)24macro(add_gdbus_codegen_with_namespace outfiles name prefix namespace service_xml)
17 set(PREFIX --interface-prefix ${arg_PREFIX})
18 endif()
19
20 if(arg_NAMESPACE)
21 set(NAMESPACE --c-namespace ${arg_NAMESPACE})
22 endif()
23
24 add_custom_command(25 add_custom_command(
25 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.h" "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c"26 OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c"
26 COMMAND "${GDBUS_CODEGEN}"27 COMMAND "${GDBUS_CODEGEN}"
27 --generate-c-code "${arg_NAME}"28 --interface-prefix "${prefix}"
28 ${PREFIX}29 --generate-c-code "${name}"
29 ${NAMESPACE}30 --c-namespace "${namespace}"
30 "${arg_SERVICE_XML}"31 "${service_xml}"
31 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}32 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
32 DEPENDS ${arg_DEPENDS} "${arg_SERVICE_XML}"33 DEPENDS ${ARGN} "${service_xml}"
33 )34 )
34 set(${arg_OUTFILES} ${${arg_OUTFILES}} "${CMAKE_CURRENT_BINARY_DIR}/${arg_NAME}.c" PARENT_SCOPE)35 list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c")
35endfunction(add_gdbus_codegen)36endmacro(add_gdbus_codegen_with_namespace)
3637
=== added file 'data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml'
--- data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml 1970-01-01 00:00:00 +0000
+++ data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml 2015-08-07 02:13:47 +0000
@@ -0,0 +1,8 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<node>
3 <interface name="com.canonical.UbuntuAppLaunch.SocketDemangler">
4 <method name="GetMirSocket">
5 <arg type="h" name="handle" direction="out" />
6 </method>
7 </interface>
8</node>
09
=== modified file 'debian/changelog'
--- debian/changelog 2015-06-03 21:20:42 +0000
+++ debian/changelog 2015-08-07 02:13:47 +0000
@@ -1,3 +1,4 @@
1<<<<<<< TREE
1ubuntu-app-launch (0.4+15.04.20150603-0ubuntu1) vivid; urgency=medium2ubuntu-app-launch (0.4+15.04.20150603-0ubuntu1) vivid; urgency=medium
23
3 [ Ted Gould ]4 [ Ted Gould ]
@@ -5,6 +6,27 @@
56
6 -- CI Train Bot <ci-train-bot@canonical.com> Wed, 03 Jun 2015 21:20:42 +00007 -- CI Train Bot <ci-train-bot@canonical.com> Wed, 03 Jun 2015 21:20:42 +0000
78
9=======
10ubuntu-app-launch (0.5+15.10.20150605-0ubuntu1) wily; urgency=medium
11
12 [ Ted Gould ]
13 * Don't error on ZG failure (LP: #1452178)
14 * Fallback to looking for the AppID tag if the source is missing (LP:
15 #1461138)
16
17 -- CI Train Bot <ci-train-bot@canonical.com> Fri, 05 Jun 2015 19:49:48 +0000
18
19ubuntu-app-launch (0.5+15.10.20150604-0ubuntu1) wily; urgency=medium
20
21 [ Ted Gould ]
22 * Add an untrusted helper that works with Mir trusted prompt sessions.
23
24 [ CI Train Bot ]
25 * debian/libubuntu-app-launch2.symbols: update to released version.
26
27 -- CI Train Bot <ci-train-bot@canonical.com> Thu, 04 Jun 2015 20:35:57 +0000
28
29>>>>>>> MERGE-SOURCE
8ubuntu-app-launch (0.4+15.04.20150410-0ubuntu1) vivid; urgency=medium30ubuntu-app-launch (0.4+15.04.20150410-0ubuntu1) vivid; urgency=medium
931
10 [ Ted Gould ]32 [ Ted Gould ]
1133
=== modified file 'debian/control'
--- debian/control 2015-03-05 03:04:41 +0000
+++ debian/control 2015-08-07 02:13:47 +0000
@@ -16,7 +16,7 @@
16 libgtest-dev,16 libgtest-dev,
17 libjson-glib-dev,17 libjson-glib-dev,
18 liblttng-ust-dev,18 liblttng-ust-dev,
19 libmirclient-dev (>= 0.5) [!powerpc !ppc64el],19 libmirclient-dev (>= 0.5),
20 libnih-dbus-dev,20 libnih-dbus-dev,
21 libnih-dev,21 libnih-dev,
22 libupstart-dev,22 libupstart-dev,
@@ -78,6 +78,7 @@
78Depends: ${misc:Depends},78Depends: ${misc:Depends},
79 ${shlibs:Depends},79 ${shlibs:Depends},
80 libglib2.0-dev,80 libglib2.0-dev,
81 libmirclient-dev (>= 0.5),
81 libubuntu-app-launch2 (= ${binary:Version}),82 libubuntu-app-launch2 (= ${binary:Version}),
82Pre-Depends: ${misc:Pre-Depends},83Pre-Depends: ${misc:Pre-Depends},
83Multi-Arch: same84Multi-Arch: same
8485
=== modified file 'debian/libubuntu-app-launch2.symbols'
--- debian/libubuntu-app-launch2.symbols 2015-03-05 14:36:33 +0000
+++ debian/libubuntu-app-launch2.symbols 2015-08-07 02:13:47 +0000
@@ -2,6 +2,7 @@
2 ubuntu_app_launch_app_id_parse@Base 0.42 ubuntu_app_launch_app_id_parse@Base 0.4
3 ubuntu_app_launch_application_log_path@Base 0.43 ubuntu_app_launch_application_log_path@Base 0.4
4 ubuntu_app_launch_get_primary_pid@Base 0.44 ubuntu_app_launch_get_primary_pid@Base 0.4
5 ubuntu_app_launch_helper_set_exec@Base 0.5+15.10.20150604
5 ubuntu_app_launch_list_helper_instances@Base 0.46 ubuntu_app_launch_list_helper_instances@Base 0.4
6 ubuntu_app_launch_list_helpers@Base 0.47 ubuntu_app_launch_list_helpers@Base 0.4
7 ubuntu_app_launch_list_running_apps@Base 0.48 ubuntu_app_launch_list_running_apps@Base 0.4
@@ -32,6 +33,7 @@
32 ubuntu_app_launch_start_application_test@Base 0.433 ubuntu_app_launch_start_application_test@Base 0.4
33 ubuntu_app_launch_start_helper@Base 0.434 ubuntu_app_launch_start_helper@Base 0.4
34 ubuntu_app_launch_start_multiple_helper@Base 0.435 ubuntu_app_launch_start_multiple_helper@Base 0.4
36 ubuntu_app_launch_start_session_helper@Base 0.5+15.10.20150604
35 ubuntu_app_launch_stop_application@Base 0.437 ubuntu_app_launch_stop_application@Base 0.4
36 ubuntu_app_launch_stop_helper@Base 0.438 ubuntu_app_launch_stop_helper@Base 0.4
37 ubuntu_app_launch_stop_multiple_helper@Base 0.439 ubuntu_app_launch_stop_multiple_helper@Base 0.4
3840
=== modified file 'exec-line-exec-trace.tp'
--- exec-line-exec-trace.tp 2014-08-11 17:19:57 +0000
+++ exec-line-exec-trace.tp 2015-08-07 02:13:47 +0000
@@ -5,6 +5,12 @@
5 ctf_string(appid, appid)5 ctf_string(appid, appid)
6 )6 )
7)7)
8TRACEPOINT_EVENT(ubuntu_app_launch, exec_parse_complete,
9 TP_ARGS(const char *, appid),
10 TP_FIELDS(
11 ctf_string(appid, appid)
12 )
13)
8TRACEPOINT_EVENT(ubuntu_app_launch, exec_pre_exec,14TRACEPOINT_EVENT(ubuntu_app_launch, exec_pre_exec,
9 TP_ARGS(const char *, appid),15 TP_ARGS(const char *, appid),
10 TP_FIELDS(16 TP_FIELDS(
1117
=== modified file 'exec-line-exec.c'
--- exec-line-exec.c 2014-08-11 17:19:57 +0000
+++ exec-line-exec.c 2015-08-07 02:13:47 +0000
@@ -139,6 +139,20 @@
139 return 1;139 return 1;
140 }140 }
141141
142 ual_tracepoint(exec_parse_complete, app_id);
143
144 if (g_getenv("MIR_SOCKET") != NULL && g_strcmp0(g_getenv("APP_XMIR_ENABLE"), "1") == 0) {
145 g_debug("XMir Helper being used");
146
147 /* xmir-helper $(APP_ID) $(COMMAND) */
148 const gchar * appid = g_getenv("APP_ID");
149 g_array_prepend_val(newargv, appid);
150
151 /* Pulling into the heap instead of the code page */
152 char * xmir_helper = g_strdup(XMIR_HELPER);
153 g_array_prepend_val(newargv, xmir_helper);
154 }
155
142 /* Now exec */156 /* Now exec */
143 gchar ** nargv = (gchar**)g_array_free(newargv, FALSE);157 gchar ** nargv = (gchar**)g_array_free(newargv, FALSE);
144158
145159
=== modified file 'helpers-shared.c'
--- helpers-shared.c 2014-11-21 21:17:18 +0000
+++ helpers-shared.c 2015-08-07 02:13:47 +0000
@@ -25,7 +25,7 @@
25#include "libubuntu-app-launch/recoverable-problem.h"25#include "libubuntu-app-launch/recoverable-problem.h"
2626
27/* Check to make sure we have the sections and keys we want */27/* Check to make sure we have the sections and keys we want */
28static gboolean28gboolean
29verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop)29verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop)
30{30{
31 if (inkeyfile == NULL) return FALSE;31 if (inkeyfile == NULL) return FALSE;
3232
=== modified file 'helpers.h'
--- helpers.h 2014-11-20 20:33:59 +0000
+++ helpers.h 2015-08-07 02:13:47 +0000
@@ -54,3 +54,5 @@
54 const gchar * jobname,54 const gchar * jobname,
55 const gchar * instancename);55 const gchar * instancename);
5656
57gboolean verify_keyfile (GKeyFile * inkeyfile,
58 const gchar * desktop);
5759
=== modified file 'libubuntu-app-launch/CMakeLists.txt'
--- libubuntu-app-launch/CMakeLists.txt 2014-11-21 21:17:09 +0000
+++ libubuntu-app-launch/CMakeLists.txt 2015-08-07 02:13:47 +0000
@@ -17,7 +17,8 @@
17add_lttng_gen_tp(NAME ubuntu-app-launch-trace)17add_lttng_gen_tp(NAME ubuntu-app-launch-trace)
1818
19set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")19set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden")
20add_definitions ( -DOOM_HELPER="${pkglibexecdir}/oom-adjust-setuid-helper" )20add_definitions ( -DOOM_HELPER="${pkglibexecdir}/oom-adjust-setuid-helper" -DDEMANGLER_PATH="${pkglibexecdir}/socket-demangler" )
21add_definitions ( -DLIBERTINE_LAUNCH="${CMAKE_INSTALL_FULL_BINDIR}/libertine-launch" )
2122
22set(LAUNCHER_HEADERS23set(LAUNCHER_HEADERS
23ubuntu-app-launch.h24ubuntu-app-launch.h
@@ -31,7 +32,13 @@
31ubuntu-app-launch-trace.c32ubuntu-app-launch-trace.c
32)33)
3334
34add_library(ubuntu-launcher SHARED ${LAUNCHER_SOURCES})35set(LAUNCHER_GEN_SOURCES
36)
37
38add_gdbus_codegen_with_namespace(LAUNCHER_GEN_SOURCES proxy-socket-demangler com.canonical.UbuntuAppLaunch. proxy ${CMAKE_SOURCE_DIR}/data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml)
39
40
41add_library(ubuntu-launcher SHARED ${LAUNCHER_SOURCES} ${LAUNCHER_GEN_SOURCES})
3542
36set_target_properties(ubuntu-launcher PROPERTIES43set_target_properties(ubuntu-launcher PROPERTIES
37 VERSION ${ABI_VERSION}.0.044 VERSION ${ABI_VERSION}.0.0
@@ -50,6 +57,7 @@
50 ${JSONGLIB_LIBRARIES}57 ${JSONGLIB_LIBRARIES}
51 ${CLICK_LIBRARIES}58 ${CLICK_LIBRARIES}
52 ${ZEITGEIST_LIBRARIES}59 ${ZEITGEIST_LIBRARIES}
60 ${MIR_LIBRARIES}
53 helpers61 helpers
54 -Wl,--no-undefined62 -Wl,--no-undefined
55)63)
@@ -91,7 +99,8 @@
91set(UbuntuAppLaunch_2_gir_INCLUDES GObject-2.0)99set(UbuntuAppLaunch_2_gir_INCLUDES GObject-2.0)
92100
93gir_get_cflags(_cflags)101gir_get_cflags(_cflags)
94set(UbuntuAppLaunch_2_gir_CFLAGS ${c_flags})102list_prefix(MIR_C_INCLUDES MIR_INCLUDE_DIRS "-I")
103set(UbuntuAppLaunch_2_gir_CFLAGS ${c_flags} ${MIR_C_INCLUDES})
95set(UbuntuAppLaunch_2_gir_LIBS ubuntu-app-launch)104set(UbuntuAppLaunch_2_gir_LIBS ubuntu-app-launch)
96105
97list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/")106list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/")
98107
=== modified file 'libubuntu-app-launch/click-exec.c'
--- libubuntu-app-launch/click-exec.c 2014-08-22 21:04:13 +0000
+++ libubuntu-app-launch/click-exec.c 2015-08-07 02:13:47 +0000
@@ -136,6 +136,14 @@
136 return FALSE;136 return FALSE;
137 }137 }
138138
139 if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
140 if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
141 env_handle_add(handle, "APP_XMIR_ENABLE", "1");
142 } else {
143 env_handle_add(handle, "APP_XMIR_ENABLE", "0");
144 }
145 }
146
139 /* This string is quoted using desktop file quoting:147 /* This string is quoted using desktop file quoting:
140 http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */148 http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */
141 gchar * exec = desktop_to_exec(keyfile, desktopfile);149 gchar * exec = desktop_to_exec(keyfile, desktopfile);
142150
=== modified file 'libubuntu-app-launch/desktop-exec.c'
--- libubuntu-app-launch/desktop-exec.c 2014-08-22 21:06:00 +0000
+++ libubuntu-app-launch/desktop-exec.c 2015-08-07 02:13:47 +0000
@@ -27,6 +27,7 @@
27#include "ubuntu-app-launch-trace.h"27#include "ubuntu-app-launch-trace.h"
28#include "recoverable-problem.h"28#include "recoverable-problem.h"
29#include "ual-tracepoint.h"29#include "ual-tracepoint.h"
30#include "ubuntu-app-launch.h"
3031
31/* Reports an error on the caller of UAL so that we can track32/* Reports an error on the caller of UAL so that we can track
32 who is trying to launch bad AppIDs, and then fix their bug33 who is trying to launch bad AppIDs, and then fix their bug
@@ -70,8 +71,65 @@
70 }71 }
71}72}
7273
74/* Get the keyfile object for a libertine container based application. Look into
75 the container's filesystem on disk and find it in /usr/share/applications in there.
76 Those are currently the only apps that we look at today. We're not ensuring anything
77 about the file other than it has basic sanity. */
78GKeyFile *
79keyfile_for_libertine (const gchar * appid, gchar ** outcontainer)
80{
81 /* Inital Tests, duplicating to be sure */
82 char * container = NULL;
83 char * app = NULL;
84
85 if (!ubuntu_app_launch_app_id_parse(appid, &container, &app, NULL)) {
86 return NULL;
87 }
88
89 gchar * containerdir = g_build_filename(g_get_user_cache_dir(), "libertine-container", container, NULL);
90 if (outcontainer != NULL) {
91 *outcontainer = container;
92 } else {
93 g_clear_pointer(&container, g_free);
94 }
95
96 if (!g_file_test(containerdir, G_FILE_TEST_IS_DIR)) {
97 g_free(app);
98 g_free(containerdir);
99
100 return NULL;
101 }
102
103 gchar * appdesktop = g_strdup_printf("%s.desktop", app);
104 gchar * desktopfile = g_build_filename(containerdir, "usr", "share", "applications", appdesktop, NULL);
105
106 g_free(containerdir);
107 g_free(appdesktop);
108 g_free(app);
109
110 /* We now think we have a valid 'desktopfile' path */
111 GKeyFile * keyfile = g_key_file_new();
112 gboolean loaded = g_key_file_load_from_file(keyfile, desktopfile, G_KEY_FILE_NONE, NULL);
113
114 if (!loaded) {
115 g_free(desktopfile);
116 g_key_file_free(keyfile);
117 return NULL;
118 }
119
120 if (!verify_keyfile(keyfile, desktopfile)) {
121 g_free(desktopfile);
122 g_key_file_free(keyfile);
123 return NULL;
124 }
125
126 g_free(desktopfile);
127
128 return keyfile;
129}
130
73gboolean131gboolean
74desktop_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * handle)132desktop_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * handle, gboolean is_libertine)
75{133{
76 if (app_id == NULL) {134 if (app_id == NULL) {
77 g_error("No APP_ID environment variable defined");135 g_error("No APP_ID environment variable defined");
@@ -88,10 +146,18 @@
88 ual_tracepoint(desktop_starting_sent, app_id);146 ual_tracepoint(desktop_starting_sent, app_id);
89147
90 gchar * desktopfilename = NULL;148 gchar * desktopfilename = NULL;
91 GKeyFile * keyfile = keyfile_for_appid(app_id, &desktopfilename);149 GKeyFile * keyfile = NULL;
150 gchar * libertinecontainer = NULL;
151 if (is_libertine) {
152 /* desktopfilename not set, not useful in this context */
153 keyfile = keyfile_for_libertine(app_id, &libertinecontainer);
154 } else {
155 keyfile = keyfile_for_appid(app_id, &desktopfilename);
156 }
92157
93 if (keyfile == NULL) {158 if (keyfile == NULL) {
94 report_error_on_caller(app_id);159 report_error_on_caller(app_id);
160 g_free(libertinecontainer);
95 return FALSE;161 return FALSE;
96 }162 }
97163
@@ -118,10 +184,37 @@
118 env_handle_add(handle, "APP_EXEC_POLICY", "unconfined");184 env_handle_add(handle, "APP_EXEC_POLICY", "unconfined");
119 }185 }
120186
187 if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
188 if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) {
189 env_handle_add(handle, "APP_XMIR_ENABLE", "1");
190 } else {
191 env_handle_add(handle, "APP_XMIR_ENABLE", "0");
192 }
193 } else if (is_libertine) {
194 /* Default to X for libertine stuff */
195 env_handle_add(handle, "APP_XMIR_ENABLE", "1");
196 }
197
121 /* This string is quoted using desktop file quoting:198 /* This string is quoted using desktop file quoting:
122 http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */199 http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */
123 gchar * execline = desktop_to_exec(keyfile, app_id);200 gchar * execline = desktop_to_exec(keyfile, app_id);
124 g_return_val_if_fail(execline != NULL, 1);201 g_return_val_if_fail(execline != NULL, 1);
202
203 if (is_libertine) {
204 static const gchar * libertine_launch = NULL;
205 if (G_UNLIKELY(libertine_launch == NULL)) {
206 libertine_launch = g_getenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH");
207 if (libertine_launch == NULL) {
208 libertine_launch = LIBERTINE_LAUNCH;
209 }
210 }
211
212 gchar * libexec = g_strdup_printf("%s \"%s\" %s", libertine_launch, libertinecontainer, execline);
213 g_free(execline);
214 execline = libexec;
215 }
216 g_free(libertinecontainer); /* Handles NULL, let's be sure it goes away */
217
125 env_handle_add(handle, "APP_EXEC", execline);218 env_handle_add(handle, "APP_EXEC", execline);
126 g_free(execline);219 g_free(execline);
127220
128221
=== modified file 'libubuntu-app-launch/desktop-exec.h'
--- libubuntu-app-launch/desktop-exec.h 2014-08-22 20:59:55 +0000
+++ libubuntu-app-launch/desktop-exec.h 2015-08-07 02:13:47 +0000
@@ -17,8 +17,10 @@
17 * Ted Gould <ted.gould@canonical.com>17 * Ted Gould <ted.gould@canonical.com>
18 */18 */
1919
20#pragma once
21
20#include <glib.h>22#include <glib.h>
21#include "helpers.h"23#include "helpers.h"
2224
23gboolean desktop_task_setup (GDBusConnection * bus, const gchar * appid, EnvHandle * envhandle);25gboolean desktop_task_setup (GDBusConnection * bus, const gchar * appid, EnvHandle * envhandle, gboolean is_libertine);
2426
2527
=== modified file 'libubuntu-app-launch/ubuntu-app-launch-trace.tp'
--- libubuntu-app-launch/ubuntu-app-launch-trace.tp 2014-08-21 21:00:53 +0000
+++ libubuntu-app-launch/ubuntu-app-launch-trace.tp 2015-08-07 02:13:47 +0000
@@ -18,6 +18,13 @@
18 ctf_string(type, type)18 ctf_string(type, type)
19 )19 )
20)20)
21TRACEPOINT_EVENT(ubuntu_app_launch, libual_determine_libertine,
22 TP_ARGS(const char *, appid, const char *, executionenv),
23 TP_FIELDS(
24 ctf_string(appid, appid)
25 ctf_string(executionenv, executionenv)
26 )
27)
21TRACEPOINT_EVENT(ubuntu_app_launch, libual_job_path_determined,28TRACEPOINT_EVENT(ubuntu_app_launch, libual_job_path_determined,
22 TP_ARGS(const char *, appid, const char *, job_path),29 TP_ARGS(const char *, appid, const char *, job_path),
23 TP_FIELDS(30 TP_FIELDS(
2431
=== modified file 'libubuntu-app-launch/ubuntu-app-launch.c'
--- libubuntu-app-launch/ubuntu-app-launch.c 2015-04-10 16:58:27 +0000
+++ libubuntu-app-launch/ubuntu-app-launch.c 2015-08-07 02:13:47 +0000
@@ -22,6 +22,7 @@
22#include <click.h>22#include <click.h>
23#include <upstart.h>23#include <upstart.h>
24#include <gio/gio.h>24#include <gio/gio.h>
25#include <gio/gunixfdlist.h>
25#include <string.h>26#include <string.h>
26#include <fcntl.h>27#include <fcntl.h>
27#include <errno.h>28#include <errno.h>
@@ -33,11 +34,18 @@
33#include "ual-tracepoint.h"34#include "ual-tracepoint.h"
34#include "click-exec.h"35#include "click-exec.h"
35#include "desktop-exec.h"36#include "desktop-exec.h"
37#include "recoverable-problem.h"
38#include "proxy-socket-demangler.h"
3639
37static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy);40static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy);
38static void free_helper (gpointer value);41static void free_helper (gpointer value);
39static GList * pids_for_appid (const gchar * appid);42static GList * pids_for_appid (const gchar * appid);
43static JsonObject * get_manifest (const gchar * pkg, gchar ** pkgpath);
40int kill (pid_t pid, int signal);44int kill (pid_t pid, int signal);
45static gchar * escape_dbus_string (const gchar * input);
46
47G_DEFINE_QUARK(UBUNTU_APP_LAUNCH_PROXY_PATH, proxy_path);
48G_DEFINE_QUARK(UBUNTU_APP_LAUNCH_MIR_FD, mir_fd);
4149
42/* Function to take the urls and escape them so that they can be50/* Function to take the urls and escape them so that they can be
43 parsed on the other side correctly. */51 parsed on the other side correctly. */
@@ -201,6 +209,45 @@
201 return click;209 return click;
202}210}
203211
212/* Determine whether an AppId is realated to a Libertine container by
213 checking the container and program name. */
214static gboolean
215is_libertine (const gchar * appid)
216{
217 char * container = NULL;
218 char * app = NULL;
219
220 if (!ubuntu_app_launch_app_id_parse(appid, &container, &app, NULL)) {
221 return FALSE;
222 }
223
224 gchar * containerdir = g_build_filename(g_get_user_cache_dir(), "libertine-container", container, NULL);
225 g_free(container);
226
227 if (!g_file_test(containerdir, G_FILE_TEST_IS_DIR)) {
228 g_free(app);
229 g_free(containerdir);
230
231 return FALSE;
232 }
233
234 gchar * appdesktop = g_strdup_printf("%s.desktop", app);
235 gchar * desktopfile = g_build_filename(containerdir, "usr", "share", "applications", appdesktop, NULL);
236
237 g_free(containerdir);
238 g_free(appdesktop);
239 g_free(app);
240
241 gboolean islib = g_file_test(desktopfile, G_FILE_TEST_EXISTS);
242 g_free(desktopfile);
243
244 if (islib) {
245 g_debug("Detected '%s' as a Libertine Application", appid);
246 }
247
248 return islib;
249}
250
204static gboolean251static gboolean
205start_application_core (const gchar * appid, const gchar * const * uris, gboolean test)252start_application_core (const gchar * appid, const gchar * const * uris, gboolean test)
206{253{
@@ -214,6 +261,14 @@
214 gboolean click = is_click(appid);261 gboolean click = is_click(appid);
215 ual_tracepoint(libual_determine_type, appid, click ? "click" : "legacy");262 ual_tracepoint(libual_determine_type, appid, click ? "click" : "legacy");
216263
264 /* Figure out if it is libertine */
265 gboolean libertine = FALSE;
266 if (!click) {
267 libertine = is_libertine(appid);
268 }
269
270 ual_tracepoint(libual_determine_libertine, appid, libertine ? "container" : "host");
271
217 /* Figure out the DBus path for the job */272 /* Figure out the DBus path for the job */
218 const gchar * jobpath = NULL;273 const gchar * jobpath = NULL;
219 if (click) {274 if (click) {
@@ -251,7 +306,7 @@
251 }306 }
252307
253 if (!click) {308 if (!click) {
254 if (legacy_single_instance(appid)) {309 if (libertine || legacy_single_instance(appid)) {
255 g_variant_builder_add_value(&builder, g_variant_new_string("INSTANCE_ID="));310 g_variant_builder_add_value(&builder, g_variant_new_string("INSTANCE_ID="));
256 } else {311 } else {
257 gchar * instanceid = g_strdup_printf("INSTANCE_ID=%" G_GUINT64_FORMAT, g_get_real_time());312 gchar * instanceid = g_strdup_printf("INSTANCE_ID=%" G_GUINT64_FORMAT, g_get_real_time());
@@ -267,7 +322,7 @@
267 if (click) {322 if (click) {
268 setup_complete = click_task_setup(con, appid, (EnvHandle*)&builder);323 setup_complete = click_task_setup(con, appid, (EnvHandle*)&builder);
269 } else {324 } else {
270 setup_complete = desktop_task_setup(con, appid, (EnvHandle*)&builder);325 setup_complete = desktop_task_setup(con, appid, (EnvHandle*)&builder, libertine);
271 }326 }
272327
273 if (setup_complete) {328 if (setup_complete) {
@@ -687,7 +742,7 @@
687 return path;742 return path;
688 }743 }
689744
690 if (legacy_single_instance(appid)) {745 if (!is_libertine(appid) && legacy_single_instance(appid)) {
691 gchar * appfile = g_strdup_printf("application-legacy-%s-.log", appid);746 gchar * appfile = g_strdup_printf("application-legacy-%s-.log", appid);
692 path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL);747 path = g_build_filename(g_get_user_cache_dir(), "upstart", appfile, NULL);
693 g_free(appfile);748 g_free(appfile);
@@ -721,6 +776,112 @@
721 return path;776 return path;
722}777}
723778
779/* Look to see if the app id results in a desktop file, if so, fill in the params */
780static gboolean
781evaluate_dir (const gchar * dir, const gchar * desktop, gchar ** appdir, gchar ** appdesktop)
782{
783 char * fulldir = g_build_filename(dir, "applications", desktop, NULL);
784
785 if (g_file_test(fulldir, G_FILE_TEST_EXISTS)) {
786 if (appdir != NULL) {
787 *appdir = g_strdup(dir);
788 }
789
790 if (appdesktop != NULL) {
791 *appdesktop = g_strdup_printf("applications/%s", desktop);
792 }
793 }
794
795 g_free(fulldir);
796 return FALSE;
797}
798
799/* Handle the legacy case where we look through the data directories */
800static gboolean
801app_info_legacy (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
802{
803 gchar * desktop = g_strdup_printf("%s.desktop", appid);
804
805 /* Special case the user's dir */
806 if (evaluate_dir(g_get_user_data_dir(), desktop, appdir, appdesktop)) {
807 g_free(desktop);
808 return TRUE;
809 }
810
811 const char * const * data_dirs = g_get_system_data_dirs();
812 int i;
813 for (i = 0; data_dirs[i] != NULL; i++) {
814 if (evaluate_dir(data_dirs[i], desktop, appdir, appdesktop)) {
815 g_free(desktop);
816 return TRUE;
817 }
818 }
819
820 return FALSE;
821}
822
823/* Get the information on where the desktop file is from libclick */
824static gboolean
825app_info_click (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
826{
827 gchar * package = NULL;
828 gchar * application = NULL;
829
830 if (!ubuntu_app_launch_app_id_parse(appid, &package, &application, NULL)) {
831 return FALSE;
832 }
833
834 JsonObject * manifest = get_manifest(package, appdir);
835 if (manifest == NULL) {
836 g_free(package);
837 g_free(application);
838 return FALSE;
839 }
840
841 g_free(package);
842
843 if (appdesktop != NULL) {
844 JsonObject * hooks = json_object_get_object_member(manifest, "hooks");
845 if (hooks == NULL) {
846 json_object_unref(manifest);
847 g_free(application);
848 return FALSE;
849 }
850
851 JsonObject * appobj = json_object_get_object_member(hooks, application);
852 g_free(application);
853
854 if (appobj == NULL) {
855 json_object_unref(manifest);
856 return FALSE;
857 }
858
859 const gchar * desktop = json_object_get_string_member(appobj, "desktop");
860 if (desktop == NULL) {
861 json_object_unref(manifest);
862 return FALSE;
863 }
864
865 *appdesktop = g_strdup(desktop);
866 } else {
867 g_free(application);
868 }
869
870 json_object_unref(manifest);
871
872 return TRUE;
873}
874
875gboolean
876ubuntu_app_launch_application_info (const gchar * appid, gchar ** appdir, gchar ** appdesktop)
877{
878 if (is_click(appid)) {
879 return app_info_click(appid, appdir, appdesktop);
880 } else {
881 return app_info_legacy(appid, appdir, appdesktop);
882 }
883}
884
724static GDBusConnection *885static GDBusConnection *
725gdbus_upstart_ref (void) {886gdbus_upstart_ref (void) {
726 static GDBusConnection * gdbus_upstart = NULL;887 static GDBusConnection * gdbus_upstart = NULL;
@@ -1483,7 +1644,7 @@
14831644
1484 ual_tracepoint(pids_list_finished, appid, g_list_length(pids));1645 ual_tracepoint(pids_list_finished, appid, g_list_length(pids));
1485 return pids;1646 return pids;
1486 } else if (legacy_single_instance(appid)) {1647 } else if (!is_libertine(appid) && legacy_single_instance(appid)) {
1487 gchar * jobname = g_strdup_printf("%s-", appid);1648 gchar * jobname = g_strdup_printf("%s-", appid);
1488 GList * pids = pids_from_cgroup(cgmanager, "application-legacy", jobname);1649 GList * pids = pids_from_cgroup(cgmanager, "application-legacy", jobname);
1489 g_free(jobname);1650 g_free(jobname);
@@ -1585,7 +1746,7 @@
15851746
1586/* Try and get a manifest and do a couple sanity checks on it */1747/* Try and get a manifest and do a couple sanity checks on it */
1587static JsonObject *1748static JsonObject *
1588get_manifest (const gchar * pkg)1749get_manifest (const gchar * pkg, gchar ** pkgpath)
1589{1750{
1590 /* Get the directory from click */1751 /* Get the directory from click */
1591 GError * error = NULL;1752 GError * error = NULL;
@@ -1615,6 +1776,16 @@
1615 g_object_unref(user);1776 g_object_unref(user);
1616 return NULL;1777 return NULL;
1617 }1778 }
1779
1780 if (pkgpath != NULL) {
1781 *pkgpath = click_user_get_path(user, pkg, &error);
1782 if (error != NULL) {
1783 g_warning("Unable to get the Click package directory for %s: %s", pkg, error->message);
1784 g_error_free(error);
1785 g_object_unref(user);
1786 return NULL;
1787 }
1788 }
1618 g_object_unref(user);1789 g_object_unref(user);
16191790
1620 if (!json_object_has_member(manifest, "version")) {1791 if (!json_object_has_member(manifest, "version")) {
@@ -1653,7 +1824,7 @@
1653 }1824 }
16541825
1655 if (*manifest == NULL) {1826 if (*manifest == NULL) {
1656 *manifest = get_manifest(pkg);1827 *manifest = get_manifest(pkg, NULL);
1657 }1828 }
16581829
1659 JsonObject * hooks = json_object_get_object_member(*manifest, "hooks");1830 JsonObject * hooks = json_object_get_object_member(*manifest, "hooks");
@@ -1698,7 +1869,7 @@
1698 return original_ver;1869 return original_ver;
1699 } else {1870 } else {
1700 if (*manifest == NULL) {1871 if (*manifest == NULL) {
1701 *manifest = get_manifest(pkg);1872 *manifest = get_manifest(pkg, NULL);
1702 }1873 }
1703 g_return_val_if_fail(*manifest != NULL, NULL);1874 g_return_val_if_fail(*manifest != NULL, NULL);
17041875
@@ -1754,7 +1925,7 @@
1754 to define the instance. In the end there's only one job with1925 to define the instance. In the end there's only one job with
1755 an array of instances. */1926 an array of instances. */
1756static gboolean1927static gboolean
1757start_helper_core (const gchar * type, const gchar * appid, const gchar * const * uris, const gchar * instance)1928start_helper_core (const gchar * type, const gchar * appid, const gchar * const * uris, const gchar * instance, const gchar * mirsocketpath)
1758{1929{
1759 GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);1930 GDBusConnection * con = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
1760 g_return_val_if_fail(con != NULL, FALSE);1931 g_return_val_if_fail(con != NULL, FALSE);
@@ -1778,6 +1949,11 @@
1778 g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instance)));1949 g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("INSTANCE_ID=%s", instance)));
1779 }1950 }
17801951
1952 if (mirsocketpath != NULL) {
1953 g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("UBUNTU_APP_LAUNCH_DEMANGLE_PATH=%s", mirsocketpath)));
1954 g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("UBUNTU_APP_LAUNCH_DEMANGLE_NAME=%s", g_dbus_connection_get_unique_name(con))));
1955 }
1956
1781 g_variant_builder_close(&builder);1957 g_variant_builder_close(&builder);
1782 g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE));1958 g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE));
1783 1959
@@ -1807,7 +1983,7 @@
1807 g_return_val_if_fail(appid != NULL, FALSE);1983 g_return_val_if_fail(appid != NULL, FALSE);
1808 g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE);1984 g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, FALSE);
18091985
1810 return start_helper_core(type, appid, uris, NULL);1986 return start_helper_core(type, appid, uris, NULL, NULL);
1811}1987}
18121988
1813gchar *1989gchar *
@@ -1819,10 +1995,254 @@
18191995
1820 gchar * instanceid = g_strdup_printf("%" G_GUINT64_FORMAT, g_get_real_time());1996 gchar * instanceid = g_strdup_printf("%" G_GUINT64_FORMAT, g_get_real_time());
18211997
1822 if (start_helper_core(type, appid, uris, instanceid)) {1998 if (start_helper_core(type, appid, uris, instanceid, NULL)) {
1823 return instanceid;1999 return instanceid;
1824 }2000 }
18252001
2002 g_free(instanceid);
2003 return NULL;
2004}
2005
2006/* Transfer from Mir's data structure to ours */
2007static void
2008get_mir_session_fd_helper (MirPromptSession * session, size_t count, int const * fdin, void * user_data)
2009{
2010 if (count != 1) {
2011 g_warning("Mir trusted session returned %d FDs instead of one", (int)count);
2012 return;
2013 }
2014
2015 int * retfd = (int *)user_data;
2016 *retfd = fdin[0];
2017}
2018
2019/* Setup to get the FD from Mir, blocking */
2020static int
2021get_mir_session_fd (MirPromptSession * session)
2022{
2023 int retfd = 0;
2024 MirWaitHandle * wait = mir_prompt_session_new_fds_for_prompt_providers(session,
2025 1,
2026 get_mir_session_fd_helper,
2027 &retfd);
2028
2029 mir_wait_for(wait);
2030
2031 return retfd;
2032}
2033
2034static GList * open_proxies = NULL;
2035
2036static gint
2037remove_socket_path_find (gconstpointer a, gconstpointer b)
2038{
2039 GObject * obj = (GObject *)a;
2040 const gchar * path = (const gchar *)b;
2041
2042 gchar * objpath = g_object_get_qdata(obj, proxy_path_quark());
2043
2044 return g_strcmp0(objpath, path);
2045}
2046
2047/* Cleans up if we need to early */
2048static gboolean
2049remove_socket_path (const gchar * path)
2050{
2051 GList * thisproxy = g_list_find_custom(open_proxies, path, remove_socket_path_find);
2052 if (thisproxy == NULL)
2053 return FALSE;
2054
2055 g_debug("Removing Mir Socket Proxy: %s", path);
2056
2057 GObject * obj = G_OBJECT(thisproxy->data);
2058 open_proxies = g_list_delete_link(open_proxies, thisproxy);
2059
2060 /* Remove ourselves from DBus if we weren't already */
2061 g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(obj));
2062
2063 /* If we still have FD, close it */
2064 int mirfd = GPOINTER_TO_INT(g_object_get_qdata(obj, mir_fd_quark()));
2065 if (mirfd != 0) {
2066 close(mirfd);
2067
2068 /* This is actually an error, we should expect not to find
2069 this here to do anything with it. */
2070 const gchar * props[3] = {
2071 "UbuntuAppLaunchProxyDbusPath",
2072 NULL,
2073 NULL
2074 };
2075 props[1] = path;
2076 report_recoverable_problem("ubuntu-app-launch-mir-fd-proxy", 0, TRUE, props);
2077 }
2078
2079 g_object_unref(obj);
2080
2081 return TRUE;
2082}
2083
2084/* Small timeout function that shouldn't, in most cases, ever do anything.
2085 But we need it here to ensure we don't leave things on the bus */
2086static gboolean
2087proxy_timeout (gpointer user_data)
2088{
2089 const gchar * path = (const gchar *)user_data;
2090 remove_socket_path(path);
2091 return G_SOURCE_REMOVE;
2092}
2093
2094/* Removes the whole list of proxies if they are there */
2095static void
2096proxy_cleanup_list (void)
2097{
2098 while (open_proxies) {
2099 GObject * obj = G_OBJECT(open_proxies->data);
2100 gchar * path = g_object_get_qdata(obj, proxy_path_quark());
2101 remove_socket_path(path);
2102 }
2103}
2104
2105static gboolean
2106proxy_mir_socket (GObject * obj, GDBusMethodInvocation * invocation, gpointer user_data)
2107{
2108 g_debug("Called to give Mir socket");
2109 int fd = GPOINTER_TO_INT(user_data);
2110
2111 if (fd == 0) {
2112 g_critical("No FDs to give!");
2113 return FALSE;
2114 }
2115
2116 /* Index into fds */
2117 GVariant* handle = g_variant_new_handle(0);
2118 GVariant* tuple = g_variant_new_tuple(&handle, 1);
2119
2120 GError* error = NULL;
2121 GUnixFDList* list = g_unix_fd_list_new();
2122 g_unix_fd_list_append(list, fd, &error);
2123
2124 if (error == NULL) {
2125 g_dbus_method_invocation_return_value_with_unix_fd_list(invocation, tuple, list);
2126 } else {
2127 g_variant_ref_sink(tuple);
2128 g_variant_unref(tuple);
2129 }
2130
2131 g_object_unref(list);
2132
2133 if (error != NULL) {
2134 g_critical("Unable to pass FD %d: %s", fd, error->message);
2135 g_error_free(error);
2136 return FALSE;
2137 }
2138
2139 g_object_set_qdata(obj, mir_fd_quark(), GINT_TO_POINTER(0));
2140
2141 return TRUE;
2142}
2143
2144/* Sets up the DBus proxy to send to the demangler */
2145static gchar *
2146build_proxy_socket_path (const gchar * appid, int mirfd)
2147{
2148 static gboolean final_cleanup = FALSE;
2149 if (!final_cleanup) {
2150 g_atexit(proxy_cleanup_list);
2151 final_cleanup = TRUE;
2152 }
2153
2154 GError * error = NULL;
2155 GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
2156 if (error != NULL) {
2157 g_warning("Unable to get session bus: %s", error->message);
2158 g_error_free(error);
2159 return NULL;
2160 }
2161
2162 /* Export an Object on DBus */
2163 proxySocketDemangler * skel = proxy_socket_demangler_skeleton_new();
2164 g_signal_connect(G_OBJECT(skel), "handle-get-mir-socket", G_CALLBACK(proxy_mir_socket), GINT_TO_POINTER(mirfd));
2165
2166 gchar * encoded_appid = escape_dbus_string(appid);
2167 gchar * socket_name = NULL;
2168 /* Loop until we fine an object path that isn't taken (probably only once) */
2169 while (socket_name == NULL) {
2170 gchar* tryname = g_strdup_printf("/com/canonical/UbuntuAppLaunch/%s/%X", encoded_appid, g_random_int());
2171 g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skel),
2172 session,
2173 tryname,
2174 &error);
2175
2176 if (error == NULL) {
2177 socket_name = tryname;
2178 g_debug("Exporting Mir socket on path: %s", socket_name);
2179 } else {
2180 /* Always print the error, but if the object path is in use let's
2181 not exit the loop. Let's just try again. */
2182 bool exitnow = (error->domain != G_DBUS_ERROR || error->code != G_DBUS_ERROR_OBJECT_PATH_IN_USE);
2183 g_critical("Unable to export trusted session object: %s", error->message);
2184
2185 g_clear_error(&error);
2186 g_free(tryname);
2187
2188 if (exitnow) {
2189 break;
2190 }
2191 }
2192 }
2193 g_free(encoded_appid);
2194
2195 /* If we didn't get a socket name, we should just exit. And
2196 make sure to clean up the socket. */
2197 if (socket_name == NULL) {
2198 g_object_unref(skel);
2199 g_object_unref(session);
2200 g_critical("Unable to export object to any name");
2201 return NULL;
2202 }
2203
2204 g_object_set_qdata_full(G_OBJECT(skel), proxy_path_quark(), g_strdup(socket_name), g_free);
2205 g_object_set_qdata(G_OBJECT(skel), mir_fd_quark(), GINT_TO_POINTER(mirfd));
2206 open_proxies = g_list_prepend(open_proxies, skel);
2207
2208 g_timeout_add_seconds_full(G_PRIORITY_DEFAULT,
2209 2,
2210 proxy_timeout,
2211 g_strdup(socket_name),
2212 g_free);
2213
2214 g_object_unref(session);
2215
2216 return socket_name;
2217}
2218
2219gchar *
2220ubuntu_app_launch_start_session_helper (const gchar * type, MirPromptSession * session, const gchar * appid, const gchar * const * uris)
2221{
2222 g_return_val_if_fail(type != NULL, NULL);
2223 g_return_val_if_fail(session != NULL, NULL);
2224 g_return_val_if_fail(appid != NULL, NULL);
2225 g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, NULL);
2226
2227 int mirfd = get_mir_session_fd(session);
2228 if (mirfd == 0)
2229 return NULL;
2230
2231 gchar * socket_path = build_proxy_socket_path(appid, mirfd);
2232 if (socket_path == NULL) {
2233 close(mirfd);
2234 return NULL;
2235 }
2236
2237 gchar * instanceid = g_strdup_printf("%" G_GUINT64_FORMAT, g_get_real_time());
2238
2239 if (start_helper_core(type, appid, uris, instanceid, socket_path)) {
2240 return instanceid;
2241 }
2242
2243 remove_socket_path(socket_path);
2244 g_free(socket_path);
2245 close(mirfd);
1826 g_free(instanceid);2246 g_free(instanceid);
1827 return NULL;2247 return NULL;
1828}2248}
@@ -2203,3 +2623,104 @@
2203 return delete_helper_generic(observer, helper_type, user_data, &helper_stopped_obs);2623 return delete_helper_generic(observer, helper_type, user_data, &helper_stopped_obs);
2204}2624}
22052625
2626/* Sets an environment variable in Upstart */
2627static void
2628set_var (GDBusConnection * bus, const gchar * job_name, const gchar * instance_name, const gchar * envvar)
2629{
2630 GVariantBuilder builder; /* Target: (assb) */
2631 g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
2632
2633 /* Setup the job properties */
2634 g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY);
2635 g_variant_builder_add_value(&builder, g_variant_new_string(job_name));
2636 if (instance_name != NULL)
2637 g_variant_builder_add_value(&builder, g_variant_new_string(instance_name));
2638 g_variant_builder_close(&builder);
2639
2640 g_variant_builder_add_value(&builder, g_variant_new_string(envvar));
2641
2642 /* Do we want to replace? Yes, we do! */
2643 g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE));
2644
2645 g_dbus_connection_call(bus,
2646 "com.ubuntu.Upstart",
2647 "/com/ubuntu/Upstart",
2648 "com.ubuntu.Upstart0_6",
2649 "SetEnv",
2650 g_variant_builder_end(&builder),
2651 NULL, /* reply */
2652 G_DBUS_CALL_FLAGS_NONE,
2653 -1, /* timeout */
2654 NULL, /* cancelable */
2655 NULL, NULL); /* callback */
2656}
2657
2658gboolean
2659ubuntu_app_launch_helper_set_exec (const gchar * execline, const gchar * directory)
2660{
2661 g_return_val_if_fail(execline != NULL, FALSE);
2662 g_return_val_if_fail(execline[0] != '\0', FALSE);
2663
2664 /* Check to see if we can get the job environment */
2665 const gchar * job_name = g_getenv("UPSTART_JOB");
2666 const gchar * instance_name = g_getenv("UPSTART_INSTANCE");
2667 const gchar * demangler = g_getenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME");
2668 g_return_if_fail(job_name != NULL);
2669
2670 GError * error = NULL;
2671 GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
2672
2673 if (error != NULL) {
2674 g_warning("Unable to get session bus: %s", error->message);
2675 g_error_free(error);
2676 return FALSE;
2677 }
2678
2679 /* The exec value */
2680 gchar * envstr = NULL;
2681 if (demangler) {
2682 envstr = g_strdup_printf("APP_EXEC=" DEMANGLER_PATH " %s", execline);
2683 } else {
2684 envstr = g_strdup_printf("APP_EXEC=%s", execline);
2685 }
2686
2687 set_var(bus, job_name, instance_name, envstr);
2688 g_free(envstr);
2689
2690 /* The directory value */
2691 if (directory != NULL) {
2692 gchar * direnv = g_strdup_printf("APP_DIR=%s", directory);
2693 set_var(bus, job_name, instance_name, direnv);
2694 g_free(direnv);
2695 }
2696
2697 g_object_unref(bus);
2698
2699 return TRUE;
2700}
2701
2702
2703/* ensure that all characters are valid in the dbus output string */
2704static gchar *
2705escape_dbus_string (const gchar * input)
2706{
2707 static const gchar *xdigits = "0123456789abcdef";
2708 GString *escaped;
2709 gchar c;
2710
2711 g_return_val_if_fail (input != NULL, NULL);
2712
2713 escaped = g_string_new (NULL);
2714 while ((c = *input++)) {
2715 if (g_ascii_isalnum (c)) {
2716 g_string_append_c (escaped, c);
2717 } else {
2718 g_string_append_c (escaped, '_');
2719 g_string_append_c (escaped, xdigits[c >> 4]);
2720 g_string_append_c (escaped, xdigits[c & 0xf]);
2721 }
2722 }
2723
2724 return g_string_free (escaped, FALSE);
2725}
2726
22062727
=== modified file 'libubuntu-app-launch/ubuntu-app-launch.h'
--- libubuntu-app-launch/ubuntu-app-launch.h 2015-02-25 22:20:14 +0000
+++ libubuntu-app-launch/ubuntu-app-launch.h 2015-08-07 02:13:47 +0000
@@ -18,6 +18,7 @@
18 */18 */
1919
20#include <glib.h>20#include <glib.h>
21#include <mir_toolkit/mir_prompt_session.h>
2122
22#ifndef __UBUNTU_APP_LAUNCH_H__23#ifndef __UBUNTU_APP_LAUNCH_H__
23#define __UBUNTU_APP_LAUNCH_H__ 124#define __UBUNTU_APP_LAUNCH_H__ 1
@@ -141,6 +142,19 @@
141gchar * ubuntu_app_launch_application_log_path (const gchar * appid);142gchar * ubuntu_app_launch_application_log_path (const gchar * appid);
142143
143/**144/**
145 * ubuntu_app_launch_application_info:
146 * @appid: ID of the application
147 * @appdir: (allow-none) (transfer full): Directory for the application
148 * @appdesktop: (allow-none) (transfer full): Relative path to desktop file
149 *
150 *
151 * Return value: Path to a log file or NULL if unavailable
152 */
153gboolean ubuntu_app_launch_application_info (const gchar * appid,
154 gchar ** appdir,
155 gchar ** appdesktop);
156
157/**
144 * ubuntu_app_launch_observer_add_app_starting:158 * ubuntu_app_launch_observer_add_app_starting:
145 * @observer: (scope notified): Callback when an application is about to start159 * @observer: (scope notified): Callback when an application is about to start
146 * @user_data: (closure) (allow-none): Data to pass to the observer160 * @user_data: (closure) (allow-none): Data to pass to the observer
@@ -450,7 +464,7 @@
450 * @appid: App ID of the helper464 * @appid: App ID of the helper
451 * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper465 * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper
452 *466 *
453 * Start an untrusted helper for a specific @type on a given467 * Start an untrusted helper for a specific @type of a given
454 * @appid. We don't know how that is done specifically, as Upstart468 * @appid. We don't know how that is done specifically, as Upstart
455 * will call a helper for that type. And then execute it under the469 * will call a helper for that type. And then execute it under the
456 * Apparmor profile for that helper type. This function is different470 * Apparmor profile for that helper type. This function is different
@@ -465,6 +479,29 @@
465 const gchar * const * uris);479 const gchar * const * uris);
466480
467/**481/**
482 * ubuntu_app_launch_start_session_helper:
483 * @type: Type of helper
484 * @session: Mir Trusted Prompt Session to run the helper under
485 * @appid: App ID of the helper
486 * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper
487 *
488 * Start an untrusted helper for a specific @type of a given
489 * @appid running under a Mir Trusted Prompt Session @session. The
490 * helper's MIR_SOCKET environment variable will be set appropriately
491 * so that the helper will draw on the correct surfaces. Otherwise this
492 * is the same as #ubuntu_app_launch_start_multiple_helper.
493 *
494 * It is important that all exec tools for @type call the function
495 * #ubuntu_app_launch_helper_set_exec to set the exec line.
496 *
497 * Return value: The generated instance ID or NULL on failure
498 */
499gchar * ubuntu_app_launch_start_session_helper (const gchar * type,
500 MirPromptSession * session,
501 const gchar * appid,
502 const gchar * const * uris);
503
504/**
468 * ubuntu_app_launch_stop_helper:505 * ubuntu_app_launch_stop_helper:
469 * @type: Type of helper506 * @type: Type of helper
470 * @appid: App ID of the helper507 * @appid: App ID of the helper
@@ -574,6 +611,24 @@
574 const gchar * helper_type,611 const gchar * helper_type,
575 gpointer user_data);612 gpointer user_data);
576613
614/**
615 * ubuntu_app_launch_helper_set_exec:
616 * @execline: Exec line to be executed, in Desktop file format
617 * @directory: (allow-none): The directory that the exec line should
618 * be executed in.
619 *
620 * A function to be called by an untrusted helper exec
621 * tool to set the exec line. The exec tool should determine
622 * what should be executed from some sort of configuration
623 * based on its type (usually a configuration file from a click
624 * package). Once it determines the exec line it can set it
625 * with this function and exit.
626 *
627 * Return Value: Whether we were able to set the exec line
628 */
629gboolean ubuntu_app_launch_helper_set_exec (const gchar * execline,
630 const gchar * directory);
631
577#ifdef __cplusplus632#ifdef __cplusplus
578}633}
579#endif634#endif
580635
=== modified file 'libubuntu-app-launch/ubuntu-app-launch.pc.in'
--- libubuntu-app-launch/ubuntu-app-launch.pc.in 2014-04-30 15:45:23 +0000
+++ libubuntu-app-launch/ubuntu-app-launch.pc.in 2015-08-07 02:13:47 +0000
@@ -2,7 +2,7 @@
2includedir=@includedir@2includedir=@includedir@
33
4Cflags: -I${includedir}/libubuntu-app-launch-@apiversion@4Cflags: -I${includedir}/libubuntu-app-launch-@apiversion@
5Requires: glib-2.05Requires: glib-2.0 mirclient
6Libs: -L${libdir} -lubuntu-app-launch6Libs: -L${libdir} -lubuntu-app-launch
77
8Name: libubuntu-app-launch8Name: libubuntu-app-launch
99
=== added file 'socket-demangler.c'
--- socket-demangler.c 1970-01-01 00:00:00 +0000
+++ socket-demangler.c 2015-08-07 02:13:47 +0000
@@ -0,0 +1,124 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Ted Gould <ted.gould@canonical.com>
18 */
19
20#define _POSIX_C_SOURCE 200112L
21
22#include <gio/gio.h>
23#include <gio/gunixfdlist.h>
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <errno.h>
28#include <fcntl.h>
29
30int
31main (int argc, char * argv[])
32{
33 const gchar * mir_name = g_getenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME");
34 const gchar * mir_socket = g_getenv("UBUNTU_APP_LAUNCH_DEMANGLE_PATH");
35 if (mir_socket == NULL || mir_socket[0] == '\0') {
36 g_error("Unable to find Mir path for service");
37 return -1;
38 }
39 if (mir_name == NULL || mir_name[0] == '\0') {
40 g_error("Unable to find Mir name for service");
41 return -1;
42 }
43
44 g_debug("Mir socket connection to %s:%s", mir_name, mir_socket);
45
46 GError * error = NULL;
47 GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error);
48
49 if (error != NULL) {
50 g_error("Unable to get session bus: %s", error->message);
51 g_error_free(error);
52 return -1;
53 }
54
55 GVariant * retval;
56 GUnixFDList * fdlist;
57
58 retval = g_dbus_connection_call_with_unix_fd_list_sync(
59 bus,
60 mir_name,
61 mir_socket,
62 "com.canonical.UbuntuAppLaunch.SocketDemangler",
63 "GetMirSocket",
64 NULL,
65 G_VARIANT_TYPE("(h)"),
66 G_DBUS_CALL_FLAGS_NO_AUTO_START,
67 -1, /* timeout */
68 NULL, /* fd list in */
69 &fdlist,
70 NULL, /* cancelable */
71 &error);
72
73 g_clear_object(&bus);
74
75 if (error != NULL) {
76 g_error("Unable to get Mir socket over dbus: %s", error->message);
77 g_error_free(error);
78 return -1;
79 }
80
81 GVariant * outhandle = g_variant_get_child_value(retval, 0);
82
83 if (outhandle == NULL) {
84 g_error("Unable to get data from function");
85 return -1;
86 }
87
88 gint32 handle = g_variant_get_handle(outhandle);
89 g_variant_unref(outhandle);
90 g_variant_unref(retval);
91
92 if (handle >= g_unix_fd_list_get_length(fdlist)) {
93 g_error("Handle is %d but the FD list only has %d entries", handle, g_unix_fd_list_get_length(fdlist));
94 g_clear_object(&fdlist);
95 return -1;
96 }
97
98 gint32 fd = g_unix_fd_list_get(fdlist, handle, &error);
99 g_clear_object(&fdlist);
100
101 if (error != NULL) {
102 g_error("Unable to Unix FD: %s", error->message);
103 g_error_free(error);
104 return -1;
105 }
106
107 errno = 0;
108 fcntl(fd, F_GETFD);
109 if (errno != 0) {
110 perror("File descriptor is invalid");
111 return -1;
112 }
113
114 /* Make sure the FD doesn't close on exec */
115 fcntl(fd, F_SETFD, 0);
116
117 gchar * mirsocketbuf = g_strdup_printf("fd://%d", fd);
118 setenv("MIR_SOCKET", mirsocketbuf, 1);
119 g_debug("MIR_SOCKET=%s", mirsocketbuf);
120
121 g_free(mirsocketbuf);
122
123 return execvp(argv[1], argv + 1);
124}
0125
=== modified file 'tests/CMakeLists.txt'
--- tests/CMakeLists.txt 2015-04-06 21:28:13 +0000
+++ tests/CMakeLists.txt 2015-08-07 02:13:47 +0000
@@ -32,15 +32,23 @@
3232
33include_directories("${CMAKE_SOURCE_DIR}/libubuntu-app-launch")33include_directories("${CMAKE_SOURCE_DIR}/libubuntu-app-launch")
34add_definitions ( -DSPEW_UTILITY="${CMAKE_CURRENT_BINARY_DIR}/data-spew" )34add_definitions ( -DSPEW_UTILITY="${CMAKE_CURRENT_BINARY_DIR}/data-spew" )
35add_definitions ( -DSESSION_TEMP_FILE="${CMAKE_CURRENT_BINARY_DIR}/libual-test-session-start-temp" )
36add_definitions ( -DSOCKET_DEMANGLER="${CMAKE_BINARY_DIR}/socket-demangler" )
37add_definitions ( -DSOCKET_DEMANGLER_INSTALL="${pkglibexecdir}/socket-demangler" )
38add_definitions ( -DSOCKET_TOOL="${CMAKE_CURRENT_BINARY_DIR}/socket-tool" )
3539
36add_executable (libual-test40add_executable (libual-test
37 libual-test.cc)41 libual-test.cc
42 mir-mock.cpp)
38target_link_libraries (libual-test gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} ubuntu-launcher)43target_link_libraries (libual-test gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} ubuntu-launcher)
3944
40add_executable (data-spew45add_executable (data-spew
41 data-spew.c)46 data-spew.c)
42target_link_libraries (data-spew ${GLIB2_LIBRARIES})47target_link_libraries (data-spew ${GLIB2_LIBRARIES})
4348
49add_executable (socket-tool
50 socket-tool.c)
51
44add_test (NAME libual-test COMMAND libual-test)52add_test (NAME libual-test COMMAND libual-test)
4553
46# Failure Test54# Failure Test
@@ -87,3 +95,9 @@
87configure_file ("click-desktop-hook-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-desktop-hook-db/test.conf" @ONLY)95configure_file ("click-desktop-hook-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-desktop-hook-db/test.conf" @ONLY)
88configure_file ("desktop-hook-test.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/desktop-hook-test.sh" @ONLY)96configure_file ("desktop-hook-test.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/desktop-hook-test.sh" @ONLY)
89add_test (desktop-hook-test desktop-hook-test.sh)97add_test (desktop-hook-test desktop-hook-test.sh)
98
99# XMir helper Test
100
101configure_file ("xmir-helper-test.in" "${CMAKE_CURRENT_BINARY_DIR}/xmir-helper-test" @ONLY)
102add_test (xmir-helper-test xmir-helper-test)
103
90104
=== added file 'tests/applications/noxmir.desktop'
--- tests/applications/noxmir.desktop 1970-01-01 00:00:00 +0000
+++ tests/applications/noxmir.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,8 @@
1[Desktop Entry]
2Name=No XMir Needed
3Type=Application
4Exec=noxmir
5NoDisplay=false
6Hidden=false
7Terminal=false
8X-Ubuntu-XMir-Enable=false
09
=== added file 'tests/applications/xmir.desktop'
--- tests/applications/xmir.desktop 1970-01-01 00:00:00 +0000
+++ tests/applications/xmir.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,8 @@
1[Desktop Entry]
2Name=X Application
3Type=Application
4Exec=xfoo
5NoDisplay=false
6Hidden=false
7Terminal=false
8X-Ubuntu-XMir-Enable=true
09
=== added file 'tests/click-app-dir/.click/info/com.test.mir.manifest'
--- tests/click-app-dir/.click/info/com.test.mir.manifest 1970-01-01 00:00:00 +0000
+++ tests/click-app-dir/.click/info/com.test.mir.manifest 2015-08-07 02:13:47 +0000
@@ -0,0 +1,11 @@
1{
2 "version": "1",
3 "hooks": {
4 "mir": {
5 "desktop": "xmir.desktop"
6 },
7 "nomir": {
8 "desktop": "noxmir.desktop"
9 }
10 }
11}
012
=== added file 'tests/click-app-dir/noxmir.desktop'
--- tests/click-app-dir/noxmir.desktop 1970-01-01 00:00:00 +0000
+++ tests/click-app-dir/noxmir.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,8 @@
1[Desktop Entry]
2Name=No XMir Needed
3Type=Application
4Exec=noxmir
5NoDisplay=false
6Hidden=false
7Terminal=false
8X-Ubuntu-XMir-Enable=false
09
=== added file 'tests/click-app-dir/xmir.desktop'
--- tests/click-app-dir/xmir.desktop 1970-01-01 00:00:00 +0000
+++ tests/click-app-dir/xmir.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,8 @@
1[Desktop Entry]
2Name=X Application
3Type=Application
4Exec=xfoo
5NoDisplay=false
6Hidden=false
7Terminal=false
8X-Ubuntu-XMir-Enable=true
09
=== added symlink 'tests/click-root-dir/.click/users/test-user/com.test.mir'
=== target is u'../../../com.test.mir/1/'
=== added directory 'tests/click-root-dir/com.test.mir'
=== added symlink 'tests/click-root-dir/com.test.mir/1'
=== target is u'../../click-app-dir/'
=== modified file 'tests/exec-util-test.cc'
--- tests/exec-util-test.cc 2014-08-26 02:21:57 +0000
+++ tests/exec-util-test.cc 2015-08-07 02:13:47 +0000
@@ -37,6 +37,8 @@
37 virtual void SetUp() {37 virtual void SetUp() {
38 g_setenv("UPSTART_JOB", "made-up-job", TRUE);38 g_setenv("UPSTART_JOB", "made-up-job", TRUE);
39 g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE);39 g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE);
40 g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR "/libertine-data", TRUE);
41 g_setenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH", "libertine-launch", TRUE);
4042
41 service = dbus_test_service_new(NULL);43 service = dbus_test_service_new(NULL);
4244
@@ -271,3 +273,258 @@
271 EXPECT_TRUE(got_app_pid);273 EXPECT_TRUE(got_app_pid);
272 EXPECT_TRUE(got_instance_id);274 EXPECT_TRUE(got_instance_id);
273}275}
276
277TEST_F(ExecUtil, DesktopMir)
278{
279 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL);
280
281 ASSERT_TRUE(ubuntu_app_launch_start_application("xmir", NULL));
282
283 guint len = 0;
284 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL);
285
286 ASSERT_EQ(1, len);
287 ASSERT_NE(nullptr, calls);
288 ASSERT_STREQ("Start", calls[0].name);
289
290 unsigned int i;
291
292 bool got_mir = false;
293
294 GVariant * envarray = g_variant_get_child_value(calls[0].params, 0);
295 GVariantIter iter;
296 g_variant_iter_init(&iter, envarray);
297 gchar * envvar = NULL;
298
299 while (g_variant_iter_loop(&iter, "s", &envvar)) {
300 gchar * var = g_strdup(envvar);
301
302 gchar * equal = g_strstr_len(var, -1, "=");
303 ASSERT_NE(equal, nullptr);
304
305 equal[0] = '\0';
306 gchar * value = &(equal[1]);
307
308 if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) {
309 EXPECT_STREQ("1", value);
310 got_mir = true;
311 }
312
313 g_free(var);
314 }
315
316 g_variant_unref(envarray);
317
318 EXPECT_TRUE(got_mir);
319}
320
321TEST_F(ExecUtil, DesktopNoMir)
322{
323 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL);
324
325 ASSERT_TRUE(ubuntu_app_launch_start_application("noxmir", NULL));
326
327 guint len = 0;
328 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL);
329
330 ASSERT_EQ(1, len);
331 ASSERT_NE(nullptr, calls);
332 ASSERT_STREQ("Start", calls[0].name);
333
334 unsigned int i;
335
336 bool got_mir = false;
337
338 GVariant * envarray = g_variant_get_child_value(calls[0].params, 0);
339 GVariantIter iter;
340 g_variant_iter_init(&iter, envarray);
341 gchar * envvar = NULL;
342
343 while (g_variant_iter_loop(&iter, "s", &envvar)) {
344 gchar * var = g_strdup(envvar);
345
346 gchar * equal = g_strstr_len(var, -1, "=");
347 ASSERT_NE(equal, nullptr);
348
349 equal[0] = '\0';
350 gchar * value = &(equal[1]);
351
352 if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) {
353 EXPECT_STREQ("0", value);
354 got_mir = true;
355 }
356
357 g_free(var);
358 }
359
360 g_variant_unref(envarray);
361
362 EXPECT_TRUE(got_mir);
363}
364
365TEST_F(ExecUtil, ClickMir)
366{
367 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL);
368
369 g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE);
370 g_setenv("TEST_CLICK_USER", "test-user", TRUE);
371 g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE);
372
373 ASSERT_TRUE(ubuntu_app_launch_start_application("com.test.mir_mir_1", NULL));
374
375 guint len = 0;
376 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL);
377
378 ASSERT_EQ(1, len);
379 ASSERT_NE(nullptr, calls);
380 ASSERT_STREQ("Start", calls[0].name);
381
382 unsigned int i;
383
384 bool got_mir = false;
385
386 GVariant * envarray = g_variant_get_child_value(calls[0].params, 0);
387 GVariantIter iter;
388 g_variant_iter_init(&iter, envarray);
389 gchar * envvar = NULL;
390
391 while (g_variant_iter_loop(&iter, "s", &envvar)) {
392 gchar * var = g_strdup(envvar);
393
394 gchar * equal = g_strstr_len(var, -1, "=");
395 ASSERT_NE(equal, nullptr);
396
397 equal[0] = '\0';
398 gchar * value = &(equal[1]);
399
400 if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) {
401 EXPECT_STREQ("1", value);
402 got_mir = true;
403 }
404
405 g_free(var);
406 }
407
408 g_variant_unref(envarray);
409
410 EXPECT_TRUE(got_mir);
411}
412
413TEST_F(ExecUtil, ClickNoMir)
414{
415 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL);
416
417 g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE);
418 g_setenv("TEST_CLICK_USER", "test-user", TRUE);
419 g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE);
420
421 ASSERT_TRUE(ubuntu_app_launch_start_application("com.test.mir_nomir_1", NULL));
422
423 guint len = 0;
424 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL);
425
426 ASSERT_EQ(1, len);
427 ASSERT_NE(nullptr, calls);
428 ASSERT_STREQ("Start", calls[0].name);
429
430 unsigned int i;
431
432 bool got_mir = false;
433
434 GVariant * envarray = g_variant_get_child_value(calls[0].params, 0);
435 GVariantIter iter;
436 g_variant_iter_init(&iter, envarray);
437 gchar * envvar = NULL;
438
439 while (g_variant_iter_loop(&iter, "s", &envvar)) {
440 gchar * var = g_strdup(envvar);
441
442 gchar * equal = g_strstr_len(var, -1, "=");
443 ASSERT_NE(equal, nullptr);
444
445 equal[0] = '\0';
446 gchar * value = &(equal[1]);
447
448 if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) {
449 EXPECT_STREQ("0", value);
450 got_mir = true;
451 }
452
453 g_free(var);
454 }
455
456 g_variant_unref(envarray);
457
458 EXPECT_TRUE(got_mir);
459}
460
461TEST_F(ExecUtil, LibertineExec)
462{
463 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL);
464
465 ASSERT_TRUE(ubuntu_app_launch_start_application("container-name_test_0.0", NULL));
466
467 guint len = 0;
468 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL);
469
470 ASSERT_EQ(1, len);
471 ASSERT_NE(nullptr, calls);
472 ASSERT_STREQ("Start", calls[0].name);
473
474 unsigned int i;
475
476 bool got_app_exec = false;
477 bool got_app_exec_policy = false;
478 bool got_app_id = false;
479 bool got_app_pid = false;
480 bool got_instance_id = false;
481 bool got_mir = false;
482
483 GVariant * envarray = g_variant_get_child_value(calls[0].params, 0);
484 GVariantIter iter;
485 g_variant_iter_init(&iter, envarray);
486 gchar * envvar = NULL;
487
488 while (g_variant_iter_loop(&iter, "s", &envvar)) {
489 gchar * var = g_strdup(envvar);
490
491 gchar * equal = g_strstr_len(var, -1, "=");
492 ASSERT_NE(equal, nullptr);
493
494 equal[0] = '\0';
495 gchar * value = &(equal[1]);
496
497 if (g_strcmp0(var, "APP_EXEC") == 0) {
498 EXPECT_STREQ("libertine-launch \"container-name\" test", value);
499 got_app_exec = true;
500 } else if (g_strcmp0(var, "APP_EXEC_POLICY") == 0) {
501 EXPECT_STREQ("unconfined", value);
502 got_app_exec_policy = true;
503 } else if (g_strcmp0(var, "APP_ID") == 0) {
504 EXPECT_STREQ("container-name_test_0.0", value);
505 got_app_id = true;
506 } else if (g_strcmp0(var, "APP_LAUNCHER_PID") == 0) {
507 EXPECT_EQ(getpid(), atoi(value));
508 got_app_pid = true;
509 } else if (g_strcmp0(var, "INSTANCE_ID") == 0) {
510 got_instance_id = true;
511 } else if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) {
512 EXPECT_STREQ("1", value);
513 got_mir = true;
514 } else {
515 g_warning("Unknown variable! %s", var);
516 EXPECT_TRUE(false);
517 }
518
519 g_free(var);
520 }
521
522 g_variant_unref(envarray);
523
524 EXPECT_TRUE(got_app_exec);
525 EXPECT_TRUE(got_app_exec_policy);
526 EXPECT_TRUE(got_app_id);
527 EXPECT_TRUE(got_app_pid);
528 EXPECT_TRUE(got_instance_id);
529 EXPECT_TRUE(got_mir);
530}
274531
=== added directory 'tests/libertine-data'
=== added directory 'tests/libertine-data/libertine-container'
=== added directory 'tests/libertine-data/libertine-container/container-name'
=== added directory 'tests/libertine-data/libertine-container/container-name/usr'
=== added directory 'tests/libertine-data/libertine-container/container-name/usr/share'
=== added directory 'tests/libertine-data/libertine-container/container-name/usr/share/applications'
=== added file 'tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop'
--- tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop 1970-01-01 00:00:00 +0000
+++ tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,4 @@
1[Desktop Entry]
2Name=Test
3Type=Application
4Exec=test
05
=== modified file 'tests/libual-test.cc'
--- tests/libual-test.cc 2015-03-02 19:59:44 +0000
+++ tests/libual-test.cc 2015-08-07 02:13:47 +0000
@@ -17,13 +17,18 @@
17 * Ted Gould <ted.gould@canonical.com>17 * Ted Gould <ted.gould@canonical.com>
18 */18 */
1919
20#include <future>
21#include <thread>
22
20#include <gtest/gtest.h>23#include <gtest/gtest.h>
21#include <gio/gio.h>24#include <gio/gio.h>
22#include <zeitgeist.h>25#include <zeitgeist.h>
26#include "mir-mock.h"
2327
24extern "C" {28extern "C" {
25#include "ubuntu-app-launch.h"29#include "ubuntu-app-launch.h"
26#include "libdbustest/dbus-test.h"30#include "libdbustest/dbus-test.h"
31#include <fcntl.h>
27}32}
2833
29class LibUAL : public ::testing::Test34class LibUAL : public ::testing::Test
@@ -108,6 +113,13 @@
108 " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n",113 " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n",
109 NULL);114 NULL);
110115
116 dbus_test_dbus_mock_object_add_method(mock, obj,
117 "SetEnv",
118 G_VARIANT_TYPE("(assb)"),
119 NULL,
120 "",
121 NULL);
122
111 /* Click App */123 /* Click App */
112 DbusTestDbusMockObject * jobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL);124 DbusTestDbusMockObject * jobobj = dbus_test_dbus_mock_get_object(mock, "/com/test/application_click", "com.ubuntu.Upstart0_6.Job", NULL);
113125
@@ -266,50 +278,64 @@
266 }278 }
267 ASSERT_EQ(nullptr, bus);279 ASSERT_EQ(nullptr, bus);
268 }280 }
269281
270 bool check_env (GVariant * env_array, const gchar * var, const gchar * value) {282 GVariant * find_env (GVariant * env_array, const gchar * var) {
271 GVariantIter iter;283 int i;
272 g_variant_iter_init(&iter, env_array);
273 gchar * envvar = NULL;284 gchar * envvar = NULL;
274 bool found = false;285 GVariant * retval = nullptr;
275286
276 while (g_variant_iter_loop(&iter, "s", &envvar)) {287 for (i = 0; i < g_variant_n_children(env_array); i++) {
288 GVariant * child = g_variant_get_child_value(env_array, i);
289 const gchar * envvar = g_variant_get_string(child, nullptr);
290
277 if (g_str_has_prefix(envvar, var)) {291 if (g_str_has_prefix(envvar, var)) {
278 if (found) {292 if (retval != nullptr) {
279 g_warning("Found the env var more than once!");293 g_warning("Found the env var more than once!");
280 return false;294 g_variant_unref(retval);
295 return nullptr;
281 }296 }
282297
283 if (value != NULL) {298 retval = child;
284 gchar * combined = g_strdup_printf("%s=%s", var, value);299 } else {
285 if (g_strcmp0(envvar, combined) == 0) {300 g_variant_unref(child);
286 found = true;
287 }
288 g_free(combined);
289 } else {
290 found = true;
291 }
292 }301 }
293 }302 }
294303
295 if (!found) {304 if (!retval) {
296 gchar * envstr = g_variant_print(env_array, FALSE);305 gchar * envstr = g_variant_print(env_array, FALSE);
297 g_warning("Unable to find '%s' with value '%s' in '%s'", var, value, envstr);306 g_warning("Unable to find '%s' in '%s'", var, envstr);
298 g_free(envstr);307 g_free(envstr);
299 }308 }
300309
310 return retval;
311 }
312
313 bool check_env (GVariant * env_array, const gchar * var, const gchar * value) {
314 bool found = false;
315 GVariant * val = find_env(env_array, var);
316 if (val == nullptr)
317 return false;
318
319 const gchar * envvar = g_variant_get_string(val, nullptr);
320
321 gchar * combined = g_strdup_printf("%s=%s", var, value);
322 if (g_strcmp0(envvar, combined) == 0) {
323 found = true;
324 }
325
326 g_variant_unref(val);
327
301 return found;328 return found;
302 }329 }
303330
304 static gboolean pause_helper (gpointer pmainloop) {331 void pause (guint time = 0) {
305 g_main_loop_quit(static_cast<GMainLoop *>(pmainloop));
306 return G_SOURCE_REMOVE;
307 }
308
309 void pause (guint time) {
310 if (time > 0) {332 if (time > 0) {
311 GMainLoop * mainloop = g_main_loop_new(NULL, FALSE);333 GMainLoop * mainloop = g_main_loop_new(NULL, FALSE);
312 g_timeout_add(time, pause_helper, mainloop);334
335 g_timeout_add(time, [](gpointer pmainloop) -> gboolean {
336 g_main_loop_quit(static_cast<GMainLoop *>(pmainloop));
337 return G_SOURCE_REMOVE;
338 }, mainloop);
313339
314 g_main_loop_run(mainloop);340 g_main_loop_run(mainloop);
315341
@@ -1446,3 +1472,147 @@
1446 1472
1447 g_free(oomadjfile);1473 g_free(oomadjfile);
1448}1474}
1475
1476TEST_F(LibUAL, StartSessionHelper)
1477{
1478 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL);
1479 MirConnection * conn = mir_connect_sync("libual-test", "start-session-helper"); // Mocked, doesn't need cleaning up
1480 MirPromptSession * msession = mir_connection_create_prompt_session_sync(conn, 5, nullptr, nullptr);
1481
1482 /* Building a temporary file and making an FD for it */
1483 const char * filedata = "This is some data that we should get on the other side\n";
1484 ASSERT_TRUE(g_file_set_contents(SESSION_TEMP_FILE, filedata, strlen(filedata), nullptr) == TRUE);
1485 int mirfd = open(SESSION_TEMP_FILE, 0);
1486 mir_mock_set_trusted_fd(mirfd);
1487
1488 /* Basic make sure we can send the event */
1489 gchar * instance_id = ubuntu_app_launch_start_session_helper("untrusted-type", msession, "com.test.multiple_first_1.2.3", NULL);
1490 ASSERT_NE(nullptr, instance_id);
1491
1492 guint len = 0;
1493 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL);
1494 EXPECT_NE(nullptr, calls);
1495 EXPECT_EQ(1, len);
1496
1497 EXPECT_STREQ("Start", calls->name);
1498 EXPECT_EQ(2, g_variant_n_children(calls->params));
1499
1500 GVariant * block = g_variant_get_child_value(calls->params, 1);
1501 EXPECT_TRUE(g_variant_get_boolean(block));
1502 g_variant_unref(block);
1503
1504 /* Check the environment */
1505 GVariant * env = g_variant_get_child_value(calls->params, 0);
1506 EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3"));
1507 EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type"));
1508 EXPECT_TRUE(check_env(env, "INSTANCE_ID", instance_id));
1509
1510 GVariant * mnamev = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_NAME");
1511 ASSERT_NE(nullptr, mnamev); /* Have to assert because, eh, GVariant */
1512 EXPECT_STREQ(g_dbus_connection_get_unique_name(bus), g_variant_get_string(mnamev, nullptr) + strlen("UBUNTU_APP_LAUNCH_DEMANGLE_NAME="));
1513 GVariant * mpathv = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_PATH");
1514 ASSERT_NE(nullptr, mpathv); /* Have to assert because, eh, GVariant */
1515
1516 g_variant_unref(env);
1517
1518 /* Setup environment for call */
1519 const gchar * mname = g_variant_get_string(mnamev, nullptr);
1520 mname += strlen("UBUNTU_APP_LAUNCH_DEMANGLE_NAME=");
1521 g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", mname, TRUE);
1522 g_variant_unref(mnamev);
1523
1524 const gchar * mpath = g_variant_get_string(mpathv, nullptr);
1525 mpath += strlen("UBUNTU_APP_LAUNCH_DEMANGLE_PATH=");
1526 g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_PATH", mpath, TRUE);
1527 g_variant_unref(mpathv);
1528
1529 /* Exec our tool */
1530 std::promise<std::string> outputpromise;
1531 std::thread t([&outputpromise]() {
1532 gchar * socketstdout = nullptr;
1533 GError * error = nullptr;
1534 g_unsetenv("G_MESSAGES_DEBUG");
1535
1536 g_spawn_command_line_sync(
1537 SOCKET_DEMANGLER " " SOCKET_TOOL,
1538 &socketstdout,
1539 nullptr,
1540 nullptr,
1541 &error);
1542
1543 if (error != nullptr) {
1544 fprintf(stderr, "Unable to spawn '" SOCKET_DEMANGLER " " SOCKET_TOOL "': %s\n", error->message);
1545 g_error_free(error);
1546 outputpromise.set_value(std::string(""));
1547 } else {
1548 outputpromise.set_value(std::string(socketstdout));
1549 g_free(socketstdout);
1550 }
1551 });
1552 t.detach();
1553
1554 auto outputfuture = outputpromise.get_future();
1555 while (outputfuture.wait_for(std::chrono::milliseconds{1}) != std::future_status::ready) {
1556 pause();
1557 }
1558
1559 ASSERT_STREQ(filedata, outputfuture.get().c_str());
1560
1561 ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL));
1562
1563 return;
1564}
1565
1566TEST_F(LibUAL, SetExec)
1567{
1568 DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL);
1569
1570 const char * exec = "lets exec this";
1571
1572 g_setenv("UPSTART_JOB", "fubar", TRUE);
1573 g_unsetenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME");
1574 EXPECT_TRUE(ubuntu_app_launch_helper_set_exec(exec, NULL));
1575
1576 guint len = 0;
1577 const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL);
1578 ASSERT_NE(nullptr, calls);
1579 EXPECT_EQ(1, len);
1580
1581 gchar * appexecstr = g_strdup_printf("APP_EXEC=%s", exec);
1582 GVariant * appexecenv = g_variant_get_child_value(calls[0].params, 1);
1583 EXPECT_STREQ(appexecstr, g_variant_get_string(appexecenv, nullptr));
1584 g_variant_unref(appexecenv);
1585 g_free(appexecstr);
1586
1587 ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL));
1588
1589 /* Now check for the demangler */
1590 g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", g_dbus_connection_get_unique_name(bus), TRUE);
1591 EXPECT_TRUE(ubuntu_app_launch_helper_set_exec(exec, NULL));
1592
1593 calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL);
1594 ASSERT_NE(nullptr, calls);
1595 EXPECT_EQ(1, len);
1596
1597 gchar * demangleexecstr = g_strdup_printf("APP_EXEC=%s %s", SOCKET_DEMANGLER_INSTALL, exec);
1598 appexecenv = g_variant_get_child_value(calls[0].params, 1);
1599 EXPECT_STREQ(demangleexecstr, g_variant_get_string(appexecenv, nullptr));
1600 g_variant_unref(appexecenv);
1601 g_free(demangleexecstr);
1602
1603 ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL));
1604
1605 /* Now check for the directory */
1606 g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", g_dbus_connection_get_unique_name(bus), TRUE);
1607 EXPECT_TRUE(ubuntu_app_launch_helper_set_exec(exec, "/not/a/real/directory"));
1608
1609 calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL);
1610 ASSERT_NE(nullptr, calls);
1611 EXPECT_EQ(2, len);
1612
1613 appexecenv = g_variant_get_child_value(calls[1].params, 1);
1614 EXPECT_STREQ("APP_DIR=/not/a/real/directory", g_variant_get_string(appexecenv, nullptr));
1615 g_variant_unref(appexecenv);
1616
1617 ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL));
1618}
14491619
=== added file 'tests/link-farm/com.test.mir_mir_1.desktop'
--- tests/link-farm/com.test.mir_mir_1.desktop 1970-01-01 00:00:00 +0000
+++ tests/link-farm/com.test.mir_mir_1.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,1 @@
1Needs to exist
02
=== added file 'tests/link-farm/com.test.mir_nomir_1.desktop'
--- tests/link-farm/com.test.mir_nomir_1.desktop 1970-01-01 00:00:00 +0000
+++ tests/link-farm/com.test.mir_nomir_1.desktop 2015-08-07 02:13:47 +0000
@@ -0,0 +1,1 @@
1Needs to exist
02
=== added file 'tests/mir-mock.cpp'
--- tests/mir-mock.cpp 1970-01-01 00:00:00 +0000
+++ tests/mir-mock.cpp 2015-08-07 02:13:47 +0000
@@ -0,0 +1,106 @@
1
2#include "mir-mock.h"
3
4#include <iostream>
5#include <thread>
6
7#include <mir_toolkit/mir_connection.h>
8#include <mir_toolkit/mir_prompt_session.h>
9
10static const char * valid_trust_session = "In the circle of trust";
11static bool valid_trust_connection = true;
12static pid_t last_trust_pid = 0;
13static int trusted_fd = 1234;
14
15MirPromptSession *
16mir_connection_create_prompt_session_sync(MirConnection * connection, pid_t pid, void (*)(MirPromptSession *, MirPromptSessionState, void*data), void * context) {
17 last_trust_pid = pid;
18
19 if (valid_trust_connection) {
20 return (MirPromptSession *)valid_trust_session;
21 } else {
22 return nullptr;
23 }
24}
25
26void
27mir_prompt_session_release_sync (MirPromptSession * session)
28{
29 if (reinterpret_cast<char *>(session) != valid_trust_session) {
30 std::cerr << "Releasing a Mir Trusted Prompt that isn't valid" << std::endl;
31 exit(1);
32 }
33}
34
35MirWaitHandle *
36mir_prompt_session_new_fds_for_prompt_providers (MirPromptSession * session, unsigned int numfds, mir_client_fd_callback cb, void * data) {
37 if (reinterpret_cast<char *>(session) != valid_trust_session) {
38 std::cerr << "Releasing a Mir Trusted Prompt that isn't valid" << std::endl;
39 exit(1);
40 }
41
42 /* TODO: Put in another thread to be more mir like */
43 std::thread * thread = new std::thread([session, numfds, cb, data]() {
44 int fdlist[numfds];
45
46 for (int i = 0; i < numfds; i++)
47 fdlist[i] = trusted_fd;
48
49 cb(session, numfds, fdlist, data);
50 });
51
52 return reinterpret_cast<MirWaitHandle *>(thread);
53}
54
55void
56mir_wait_for (MirWaitHandle * wait)
57{
58 auto thread = reinterpret_cast<std::thread *>(wait);
59
60 if (thread->joinable())
61 thread->join();
62
63 delete thread;
64}
65
66static const char * valid_connection_str = "Valid Mir Connection";
67static std::pair<std::string, std::string> last_connection;
68static bool valid_connection = true;
69
70void
71mir_mock_connect_return_valid (bool valid)
72{
73 valid_connection = valid;
74}
75
76std::pair<std::string, std::string>
77mir_mock_connect_last_connect (void)
78{
79 return last_connection;
80}
81
82MirConnection *
83mir_connect_sync (char const * server, char const * appname)
84{
85 last_connection = std::pair<std::string, std::string>(server, appname);
86
87 if (valid_connection) {
88 return (MirConnection *)(valid_connection_str);
89 } else {
90 return nullptr;
91 }
92}
93
94void
95mir_connection_release (MirConnection * con)
96{
97 if (reinterpret_cast<char *>(con) != valid_connection_str) {
98 std::cerr << "Releasing a Mir Connection that isn't valid" << std::endl;
99 exit(1);
100 }
101}
102
103void mir_mock_set_trusted_fd (int fd)
104{
105 trusted_fd = fd;
106}
0107
=== added file 'tests/mir-mock.h'
--- tests/mir-mock.h 1970-01-01 00:00:00 +0000
+++ tests/mir-mock.h 2015-08-07 02:13:47 +0000
@@ -0,0 +1,12 @@
1
2#ifndef MIR_MOCK_H
3#define MIR_MOCK_H 1
4
5#include <string>
6#include <utility>
7
8void mir_mock_connect_return_valid (bool valid);
9std::pair<std::string, std::string> mir_mock_connect_last_connect (void);
10void mir_mock_set_trusted_fd (int fd);
11
12#endif // MIR_MOCK_H
013
=== added file 'tests/socket-tool.c'
--- tests/socket-tool.c 1970-01-01 00:00:00 +0000
+++ tests/socket-tool.c 2015-08-07 02:13:47 +0000
@@ -0,0 +1,28 @@
1
2#include <stdlib.h>
3#include <stdio.h>
4#include <unistd.h>
5
6int
7main (int argc, char * argv[])
8{
9 const char * fdstr = getenv("MIR_SOCKET");
10 if (!fdstr) {
11 fprintf(stderr, "No MIR_SOCKET defined\n");
12 return 1;
13 }
14
15 int fdnum = 0;
16 sscanf(fdstr, "fd://%d", &fdnum);
17 if (fdnum == 0) {
18 fprintf(stderr, "Unable to get FD number\n");
19 return 1;
20 }
21
22 char inchar;
23 while (read(fdnum, &inchar, 1) == 1)
24 fwrite(&inchar, 1, 1, stdout);
25
26 close(fdnum);
27 return 0;
28}
029
=== added file 'tests/xmir-helper-exec.sh'
--- tests/xmir-helper-exec.sh 1970-01-01 00:00:00 +0000
+++ tests/xmir-helper-exec.sh 2015-08-07 02:13:47 +0000
@@ -0,0 +1,3 @@
1#!/bin/bash
2
3echo $DISPLAY
04
=== added file 'tests/xmir-helper-test.in'
--- tests/xmir-helper-test.in 1970-01-01 00:00:00 +0000
+++ tests/xmir-helper-test.in 2015-08-07 02:13:47 +0000
@@ -0,0 +1,25 @@
1#!/bin/bash
2
3echo -n "Testing XMir Helper… "
4
5export UBUNTU_APP_LAUNCH_XMIR_PATH="@CMAKE_CURRENT_SOURCE_DIR@/xmir-mock.sh"
6
7TESTVALUE=`@CMAKE_BINARY_DIR@/xmir-helper com.mir.test_mirtest_1.2.3 @CMAKE_CURRENT_SOURCE_DIR@/xmir-helper-exec.sh`
8
9if [ $TESTVALUE == ":42" ]; then
10 echo "PASSED"
11else
12 echo "FAILED"
13 exit 1
14fi
15
16echo -n "Testing an evil XMir helper… "
17
18export UBUNTU_APP_LAUNCH_XMIR_PATH="@CMAKE_CURRENT_SOURCE_DIR@/xmir-mock-evil.sh"
19
20if @CMAKE_BINARY_DIR@/xmir-helper com.mir.test_mirtest_1.2.3 @CMAKE_CURRENT_SOURCE_DIR@/xmir-helper-exec.sh ; then
21 echo "FAILED"
22 exit 1
23else
24 echo "PASSED"
25fi
026
=== added file 'tests/xmir-mock.sh'
--- tests/xmir-mock.sh 1970-01-01 00:00:00 +0000
+++ tests/xmir-mock.sh 2015-08-07 02:13:47 +0000
@@ -0,0 +1,22 @@
1#!/bin/bash
2
3if [ $1 != "-displayfd" ]; then
4 echo "-displayfd missing"
5 exit 1
6fi
7
8if [ $3 != "-mir" ]; then
9 echo "-mir missing"
10 exit 1
11fi
12
13if [ $4 != "com.mir.test_mirtest_1.2.3" ]; then
14 echo "AppID wrong"
15 exit 1
16fi
17
18echo "42" >&$2
19
20# Ensure that our "XMir" runs longer than
21# the test, if it exits first that's a failure
22sleep 1
023
=== modified file 'ubuntu-app-test/CMakeLists.txt'
--- ubuntu-app-test/CMakeLists.txt 2015-03-05 14:35:26 +0000
+++ ubuntu-app-test/CMakeLists.txt 2015-08-07 02:13:47 +0000
@@ -1,6 +1,4 @@
1add_subdirectory(data)1add_subdirectory(data)
2
3if (${MIR_FOUND})
4add_subdirectory(src)2add_subdirectory(src)
53
6# testing & coverage4# testing & coverage
@@ -8,9 +6,3 @@
8 add_subdirectory(tests)6 add_subdirectory(tests)
9endif ()7endif ()
108
11else ()
12
13install(PROGRAMS ubuntu-app-test DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}/app-test")
14
15endif ()
16
179
=== removed file 'ubuntu-app-test/ubuntu-app-test'
--- ubuntu-app-test/ubuntu-app-test 2015-03-05 14:35:26 +0000
+++ ubuntu-app-test/ubuntu-app-test 1970-01-01 00:00:00 +0000
@@ -1,6 +0,0 @@
1#!/bin/sh
2
3# Used for Architectures that don't have Mir, otherwise we build the executable
4
5echo "ubuntu-app-test doesn't work on this architecture, sorry"
6exit 1
70
=== modified file 'upstart-jobs/application-click.conf.in'
--- upstart-jobs/application-click.conf.in 2015-01-23 18:12:29 +0000
+++ upstart-jobs/application-click.conf.in 2015-08-07 02:13:47 +0000
@@ -12,6 +12,9 @@
12env APP_DIR12env APP_DIR
13env APP_DESKTOP_FILE_PATH13env APP_DESKTOP_FILE_PATH
1414
15env APP_XMIR_ENABLE=0
16export APP_XMIR_ENABLE
17
15env UBUNTU_APP_LAUNCH_ARCH="@ubuntu_app_launch_arch@"18env UBUNTU_APP_LAUNCH_ARCH="@ubuntu_app_launch_arch@"
16export UBUNTU_APP_LAUNCH_ARCH19export UBUNTU_APP_LAUNCH_ARCH
1720
1821
=== modified file 'upstart-jobs/application-legacy.conf.in'
--- upstart-jobs/application-legacy.conf.in 2015-01-23 18:12:29 +0000
+++ upstart-jobs/application-legacy.conf.in 2015-08-07 02:13:47 +0000
@@ -12,6 +12,9 @@
12env APP_URIS12env APP_URIS
13env APP_DESKTOP_FILE_PATH13env APP_DESKTOP_FILE_PATH
1414
15env APP_XMIR_ENABLE=1
16export APP_XMIR_ENABLE
17
15# This will be set to "unconfined" by desktop-exec if there is no confinement defined18# This will be set to "unconfined" by desktop-exec if there is no confinement defined
16apparmor switch $APP_EXEC_POLICY19apparmor switch $APP_EXEC_POLICY
17cgroup freezer20cgroup freezer
1821
=== added file 'xmir-helper.c'
--- xmir-helper.c 1970-01-01 00:00:00 +0000
+++ xmir-helper.c 2015-08-07 02:13:47 +0000
@@ -0,0 +1,117 @@
1/*
2 * Copyright © 2014 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Ted Gould <ted.gould@canonical.com>
18 */
19
20#define _POSIX_C_SOURCE 200212L
21
22#include <unistd.h>
23#include <stdio.h>
24#include <stdlib.h>
25#include <sys/types.h>
26#include <sys/socket.h>
27#include <signal.h>
28
29void
30sigchild_handler (int signal)
31{
32 fprintf(stderr, "XMir has closed unexpectedly\n");
33 exit(1);
34}
35
36struct sigaction sigchild_action = {
37 .sa_handler = sigchild_handler,
38 .sa_flags = SA_NOCLDWAIT
39};
40
41int
42main (int argc, char * argv[])
43{
44 if (argc < 3) {
45 fprintf(stderr, "xmir-helper needs more arguments: xmir-helper $(appid) $(thing to exec)\n");
46 return 1;
47 }
48
49 /* Make nice variables for the things we need */
50 char * appid = argv[1];
51 char * xmir = getenv("UBUNTU_APP_LAUNCH_XMIR_PATH");
52 if (xmir == NULL) {
53 xmir = "/usr/bin/Xmir";
54 }
55
56 /* Build a socket pair to get the connection back from XMir */
57 int sockets[2];
58 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) != 0) {
59 fprintf(stderr, "Unable to create socketpair for communicating with XMir\n");
60 return 1;
61 }
62
63 /* Give them nice names, the compiler will optimize out */
64 int xmirsocket = sockets[0];
65 int helpersocket = sockets[1];
66
67 /* Watch for the child dying */
68 if (sigaction(SIGCHLD, &sigchild_action, NULL) != 0) {
69 fprintf(stderr, "Unable to setup child signal handler\n");
70 return 1;
71 }
72
73 /* Start XMir */
74 if (fork() == 0) {
75 /* XMir start here */
76 /* GOAL: XMir -displayfd ${xmirsocket} -mir ${appid} */
77 char socketbuf[16] = {0};
78 snprintf(socketbuf, 16, "%d", xmirsocket);
79
80 char * xmirexec[6] = {
81 xmir,
82 "-displayfd",
83 socketbuf,
84 "-mir",
85 appid,
86 NULL
87 };
88
89 return execv(xmir, xmirexec);
90 }
91
92 /* Wait to get the display number from XMir */
93 char readbuf[16] = {0};
94 if (read(helpersocket, readbuf, 16) == 0) {
95 fprintf(stderr, "Not reading anything from XMir\n");
96 return 1;
97 }
98
99 int i;
100 for (i = 0; i < sizeof(readbuf); i++) {
101 if (readbuf[i] == '\n') {
102 readbuf[i] = '\0';
103 break;
104 }
105 }
106
107 char displaynumber[16] = {0};
108 snprintf(displaynumber, 16, ":%s", readbuf);
109
110 /* Set up the display variable */
111 setenv("DISPLAY", displaynumber, 1);
112
113 /* Now that we have everything setup, we can execute */
114 char ** nargv = &argv[2];
115 int execret = execvp(nargv[0], nargv);
116 return execret;
117}
0118
=== modified file 'zg-report-app.c'
--- zg-report-app.c 2014-09-10 14:54:01 +0000
+++ zg-report-app.c 2015-08-07 02:13:47 +0000
@@ -39,7 +39,7 @@
39 result = zeitgeist_log_insert_event_finish(ZEITGEIST_LOG(obj), res, &error);39 result = zeitgeist_log_insert_event_finish(ZEITGEIST_LOG(obj), res, &error);
4040
41 if (error != NULL) {41 if (error != NULL) {
42 g_error("Unable to submit Zeitgeist Event: %s", error->message);42 g_warning("Unable to submit Zeitgeist Event: %s", error->message);
43 g_error_free(error);43 g_error_free(error);
44 }44 }
4545

Subscribers

People subscribed via source and target branches