Merge lp:~ted/ubuntu-app-launch/libual-desktop-file into lp:ubuntu-app-launch/15.04
- libual-desktop-file
- Merge into trunk.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 |
Related bugs: |
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.
Commit message
Description of the change
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
1 | === modified file 'CMakeLists.txt' | |||
2 | --- CMakeLists.txt 2015-03-05 02:59:41 +0000 | |||
3 | +++ CMakeLists.txt 2015-08-07 02:13:47 +0000 | |||
4 | @@ -36,7 +36,8 @@ | |||
5 | 36 | ) | 36 | ) |
6 | 37 | set(ubuntu_app_launch_arch "${UBUNTU_APP_LAUNCH_ARCH}") | 37 | set(ubuntu_app_launch_arch "${UBUNTU_APP_LAUNCH_ARCH}") |
7 | 38 | 38 | ||
9 | 39 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wno-error=unused-function -std=c99") | 39 | # Deprecated needed for g_atexit() in libual |
10 | 40 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Werror -Wno-error=unused-function -Wno-error=deprecated-declarations -std=c99") | ||
11 | 40 | 41 | ||
12 | 41 | enable_testing() | 42 | enable_testing() |
13 | 42 | 43 | ||
14 | @@ -46,7 +47,7 @@ | |||
15 | 46 | pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0) | 47 | pkg_check_modules(GOBJECT2 REQUIRED gobject-2.0) |
16 | 47 | include_directories(${GOBJECT2_INCLUDE_DIRS}) | 48 | include_directories(${GOBJECT2_INCLUDE_DIRS}) |
17 | 48 | 49 | ||
19 | 49 | pkg_check_modules(GIO2 REQUIRED gio-2.0) | 50 | pkg_check_modules(GIO2 REQUIRED gio-2.0 gio-unix-2.0) |
20 | 50 | include_directories(${GIO2_INCLUDE_DIRS}) | 51 | include_directories(${GIO2_INCLUDE_DIRS}) |
21 | 51 | 52 | ||
22 | 52 | pkg_check_modules(JSONGLIB REQUIRED json-glib-1.0) | 53 | pkg_check_modules(JSONGLIB REQUIRED json-glib-1.0) |
23 | @@ -80,6 +81,8 @@ | |||
24 | 80 | 81 | ||
25 | 81 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC") | 82 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC") |
26 | 82 | 83 | ||
27 | 84 | add_definitions( -DXMIR_HELPER="${pkglibexecdir}/xmir-helper" ) | ||
28 | 85 | |||
29 | 83 | #################### | 86 | #################### |
30 | 84 | # Helpers | 87 | # Helpers |
31 | 85 | #################### | 88 | #################### |
32 | @@ -135,6 +138,14 @@ | |||
33 | 135 | install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}") | 138 | install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}") |
34 | 136 | 139 | ||
35 | 137 | #################### | 140 | #################### |
36 | 141 | # xmir-helper | ||
37 | 142 | #################### | ||
38 | 143 | |||
39 | 144 | add_executable(xmir-helper xmir-helper.c) | ||
40 | 145 | set_target_properties(xmir-helper PROPERTIES OUTPUT_NAME "xmir-helper") | ||
41 | 146 | install(TARGETS xmir-helper RUNTIME DESTINATION "${pkglibexecdir}") | ||
42 | 147 | |||
43 | 148 | #################### | ||
44 | 138 | # untrusted-helper-type-end | 149 | # untrusted-helper-type-end |
45 | 139 | #################### | 150 | #################### |
46 | 140 | 151 | ||
47 | @@ -161,6 +172,15 @@ | |||
48 | 161 | install(TARGETS oom-adjust-setuid-helper RUNTIME DESTINATION "${pkglibexecdir}") | 172 | install(TARGETS oom-adjust-setuid-helper RUNTIME DESTINATION "${pkglibexecdir}") |
49 | 162 | 173 | ||
50 | 163 | #################### | 174 | #################### |
51 | 175 | # socket-demangler | ||
52 | 176 | #################### | ||
53 | 177 | |||
54 | 178 | add_executable(socket-demangler-helper socket-demangler.c) | ||
55 | 179 | set_target_properties(socket-demangler-helper PROPERTIES OUTPUT_NAME "socket-demangler") | ||
56 | 180 | target_link_libraries(socket-demangler-helper ${GIO2_LIBRARIES}) | ||
57 | 181 | install(TARGETS socket-demangler-helper RUNTIME DESTINATION "${pkglibexecdir}") | ||
58 | 182 | |||
59 | 183 | #################### | ||
60 | 164 | # ubuntu-app-launch-desktop.click-hook | 184 | # ubuntu-app-launch-desktop.click-hook |
61 | 165 | #################### | 185 | #################### |
62 | 166 | 186 | ||
63 | 167 | 187 | ||
64 | === modified file 'cmake/UseGdbusCodegen.cmake' | |||
65 | --- cmake/UseGdbusCodegen.cmake 2013-07-24 21:13:19 +0000 | |||
66 | +++ cmake/UseGdbusCodegen.cmake 2015-08-07 02:13:47 +0000 | |||
67 | @@ -8,28 +8,29 @@ | |||
68 | 8 | message(FATAL_ERROR "Excutable gdbus-codegen not found") | 8 | message(FATAL_ERROR "Excutable gdbus-codegen not found") |
69 | 9 | endif() | 9 | endif() |
70 | 10 | 10 | ||
75 | 11 | function(add_gdbus_codegen) | 11 | macro(add_gdbus_codegen outfiles name prefix service_xml) |
76 | 12 | set(_one_value OUTFILES NAME PREFIX NAMESPACE SERVICE_XML) | 12 | add_custom_command( |
77 | 13 | set(_multi_value DEPENDS) | 13 | OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${name}.h" "${CMAKE_CURRENT_BINARY_DIR}/${name}.c" |
78 | 14 | cmake_parse_arguments (arg "" "${_one_value}" "${_multi_value}" ${ARGN}) | 14 | COMMAND "${GDBUS_CODEGEN}" |
79 | 15 | --interface-prefix "${prefix}" | ||
80 | 16 | --generate-c-code "${name}" | ||
81 | 17 | "${service_xml}" | ||
82 | 18 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | ||
83 | 19 | DEPENDS ${ARGN} "${service_xml}" | ||
84 | 20 | ) | ||
85 | 21 | list(APPEND ${outfiles} "${CMAKE_CURRENT_BINARY_DIR}/${name}.c") | ||
86 | 22 | endmacro(add_gdbus_codegen) | ||
87 | 15 | 23 | ||
96 | 16 | if(arg_PREFIX) | 24 | macro(add_gdbus_codegen_with_namespace outfiles name prefix namespace service_xml) |
89 | 17 | set(PREFIX --interface-prefix ${arg_PREFIX}) | ||
90 | 18 | endif() | ||
91 | 19 | |||
92 | 20 | if(arg_NAMESPACE) | ||
93 | 21 | set(NAMESPACE --c-namespace ${arg_NAMESPACE}) | ||
94 | 22 | endif() | ||
95 | 23 | |||
97 | 24 | add_custom_command( | 25 | add_custom_command( |
99 | 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" |
100 | 26 | COMMAND "${GDBUS_CODEGEN}" | 27 | COMMAND "${GDBUS_CODEGEN}" |
105 | 27 | --generate-c-code "${arg_NAME}" | 28 | --interface-prefix "${prefix}" |
106 | 28 | ${PREFIX} | 29 | --generate-c-code "${name}" |
107 | 29 | ${NAMESPACE} | 30 | --c-namespace "${namespace}" |
108 | 30 | "${arg_SERVICE_XML}" | 31 | "${service_xml}" |
109 | 31 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} | 32 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
111 | 32 | DEPENDS ${arg_DEPENDS} "${arg_SERVICE_XML}" | 33 | DEPENDS ${ARGN} "${service_xml}" |
112 | 33 | ) | 34 | ) |
115 | 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") |
116 | 35 | endfunction(add_gdbus_codegen) | 36 | endmacro(add_gdbus_codegen_with_namespace) |
117 | 36 | 37 | ||
118 | === added file 'data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml' | |||
119 | --- data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml 1970-01-01 00:00:00 +0000 | |||
120 | +++ data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml 2015-08-07 02:13:47 +0000 | |||
121 | @@ -0,0 +1,8 @@ | |||
122 | 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
123 | 2 | <node> | ||
124 | 3 | <interface name="com.canonical.UbuntuAppLaunch.SocketDemangler"> | ||
125 | 4 | <method name="GetMirSocket"> | ||
126 | 5 | <arg type="h" name="handle" direction="out" /> | ||
127 | 6 | </method> | ||
128 | 7 | </interface> | ||
129 | 8 | </node> | ||
130 | 0 | 9 | ||
131 | === modified file 'debian/changelog' | |||
132 | --- debian/changelog 2015-06-03 21:20:42 +0000 | |||
133 | +++ debian/changelog 2015-08-07 02:13:47 +0000 | |||
134 | @@ -1,3 +1,4 @@ | |||
135 | 1 | <<<<<<< TREE | ||
136 | 1 | ubuntu-app-launch (0.4+15.04.20150603-0ubuntu1) vivid; urgency=medium | 2 | ubuntu-app-launch (0.4+15.04.20150603-0ubuntu1) vivid; urgency=medium |
137 | 2 | 3 | ||
138 | 3 | [ Ted Gould ] | 4 | [ Ted Gould ] |
139 | @@ -5,6 +6,27 @@ | |||
140 | 5 | 6 | ||
141 | 6 | -- CI Train Bot <ci-train-bot@canonical.com> Wed, 03 Jun 2015 21:20:42 +0000 | 7 | -- CI Train Bot <ci-train-bot@canonical.com> Wed, 03 Jun 2015 21:20:42 +0000 |
142 | 7 | 8 | ||
143 | 9 | ======= | ||
144 | 10 | ubuntu-app-launch (0.5+15.10.20150605-0ubuntu1) wily; urgency=medium | ||
145 | 11 | |||
146 | 12 | [ Ted Gould ] | ||
147 | 13 | * Don't error on ZG failure (LP: #1452178) | ||
148 | 14 | * Fallback to looking for the AppID tag if the source is missing (LP: | ||
149 | 15 | #1461138) | ||
150 | 16 | |||
151 | 17 | -- CI Train Bot <ci-train-bot@canonical.com> Fri, 05 Jun 2015 19:49:48 +0000 | ||
152 | 18 | |||
153 | 19 | ubuntu-app-launch (0.5+15.10.20150604-0ubuntu1) wily; urgency=medium | ||
154 | 20 | |||
155 | 21 | [ Ted Gould ] | ||
156 | 22 | * Add an untrusted helper that works with Mir trusted prompt sessions. | ||
157 | 23 | |||
158 | 24 | [ CI Train Bot ] | ||
159 | 25 | * debian/libubuntu-app-launch2.symbols: update to released version. | ||
160 | 26 | |||
161 | 27 | -- CI Train Bot <ci-train-bot@canonical.com> Thu, 04 Jun 2015 20:35:57 +0000 | ||
162 | 28 | |||
163 | 29 | >>>>>>> MERGE-SOURCE | ||
164 | 8 | ubuntu-app-launch (0.4+15.04.20150410-0ubuntu1) vivid; urgency=medium | 30 | ubuntu-app-launch (0.4+15.04.20150410-0ubuntu1) vivid; urgency=medium |
165 | 9 | 31 | ||
166 | 10 | [ Ted Gould ] | 32 | [ Ted Gould ] |
167 | 11 | 33 | ||
168 | === modified file 'debian/control' | |||
169 | --- debian/control 2015-03-05 03:04:41 +0000 | |||
170 | +++ debian/control 2015-08-07 02:13:47 +0000 | |||
171 | @@ -16,7 +16,7 @@ | |||
172 | 16 | libgtest-dev, | 16 | libgtest-dev, |
173 | 17 | libjson-glib-dev, | 17 | libjson-glib-dev, |
174 | 18 | liblttng-ust-dev, | 18 | liblttng-ust-dev, |
176 | 19 | libmirclient-dev (>= 0.5) [!powerpc !ppc64el], | 19 | libmirclient-dev (>= 0.5), |
177 | 20 | libnih-dbus-dev, | 20 | libnih-dbus-dev, |
178 | 21 | libnih-dev, | 21 | libnih-dev, |
179 | 22 | libupstart-dev, | 22 | libupstart-dev, |
180 | @@ -78,6 +78,7 @@ | |||
181 | 78 | Depends: ${misc:Depends}, | 78 | Depends: ${misc:Depends}, |
182 | 79 | ${shlibs:Depends}, | 79 | ${shlibs:Depends}, |
183 | 80 | libglib2.0-dev, | 80 | libglib2.0-dev, |
184 | 81 | libmirclient-dev (>= 0.5), | ||
185 | 81 | libubuntu-app-launch2 (= ${binary:Version}), | 82 | libubuntu-app-launch2 (= ${binary:Version}), |
186 | 82 | Pre-Depends: ${misc:Pre-Depends}, | 83 | Pre-Depends: ${misc:Pre-Depends}, |
187 | 83 | Multi-Arch: same | 84 | Multi-Arch: same |
188 | 84 | 85 | ||
189 | === modified file 'debian/libubuntu-app-launch2.symbols' | |||
190 | --- debian/libubuntu-app-launch2.symbols 2015-03-05 14:36:33 +0000 | |||
191 | +++ debian/libubuntu-app-launch2.symbols 2015-08-07 02:13:47 +0000 | |||
192 | @@ -2,6 +2,7 @@ | |||
193 | 2 | ubuntu_app_launch_app_id_parse@Base 0.4 | 2 | ubuntu_app_launch_app_id_parse@Base 0.4 |
194 | 3 | ubuntu_app_launch_application_log_path@Base 0.4 | 3 | ubuntu_app_launch_application_log_path@Base 0.4 |
195 | 4 | ubuntu_app_launch_get_primary_pid@Base 0.4 | 4 | ubuntu_app_launch_get_primary_pid@Base 0.4 |
196 | 5 | ubuntu_app_launch_helper_set_exec@Base 0.5+15.10.20150604 | ||
197 | 5 | ubuntu_app_launch_list_helper_instances@Base 0.4 | 6 | ubuntu_app_launch_list_helper_instances@Base 0.4 |
198 | 6 | ubuntu_app_launch_list_helpers@Base 0.4 | 7 | ubuntu_app_launch_list_helpers@Base 0.4 |
199 | 7 | ubuntu_app_launch_list_running_apps@Base 0.4 | 8 | ubuntu_app_launch_list_running_apps@Base 0.4 |
200 | @@ -32,6 +33,7 @@ | |||
201 | 32 | ubuntu_app_launch_start_application_test@Base 0.4 | 33 | ubuntu_app_launch_start_application_test@Base 0.4 |
202 | 33 | ubuntu_app_launch_start_helper@Base 0.4 | 34 | ubuntu_app_launch_start_helper@Base 0.4 |
203 | 34 | ubuntu_app_launch_start_multiple_helper@Base 0.4 | 35 | ubuntu_app_launch_start_multiple_helper@Base 0.4 |
204 | 36 | ubuntu_app_launch_start_session_helper@Base 0.5+15.10.20150604 | ||
205 | 35 | ubuntu_app_launch_stop_application@Base 0.4 | 37 | ubuntu_app_launch_stop_application@Base 0.4 |
206 | 36 | ubuntu_app_launch_stop_helper@Base 0.4 | 38 | ubuntu_app_launch_stop_helper@Base 0.4 |
207 | 37 | ubuntu_app_launch_stop_multiple_helper@Base 0.4 | 39 | ubuntu_app_launch_stop_multiple_helper@Base 0.4 |
208 | 38 | 40 | ||
209 | === modified file 'exec-line-exec-trace.tp' | |||
210 | --- exec-line-exec-trace.tp 2014-08-11 17:19:57 +0000 | |||
211 | +++ exec-line-exec-trace.tp 2015-08-07 02:13:47 +0000 | |||
212 | @@ -5,6 +5,12 @@ | |||
213 | 5 | ctf_string(appid, appid) | 5 | ctf_string(appid, appid) |
214 | 6 | ) | 6 | ) |
215 | 7 | ) | 7 | ) |
216 | 8 | TRACEPOINT_EVENT(ubuntu_app_launch, exec_parse_complete, | ||
217 | 9 | TP_ARGS(const char *, appid), | ||
218 | 10 | TP_FIELDS( | ||
219 | 11 | ctf_string(appid, appid) | ||
220 | 12 | ) | ||
221 | 13 | ) | ||
222 | 8 | TRACEPOINT_EVENT(ubuntu_app_launch, exec_pre_exec, | 14 | TRACEPOINT_EVENT(ubuntu_app_launch, exec_pre_exec, |
223 | 9 | TP_ARGS(const char *, appid), | 15 | TP_ARGS(const char *, appid), |
224 | 10 | TP_FIELDS( | 16 | TP_FIELDS( |
225 | 11 | 17 | ||
226 | === modified file 'exec-line-exec.c' | |||
227 | --- exec-line-exec.c 2014-08-11 17:19:57 +0000 | |||
228 | +++ exec-line-exec.c 2015-08-07 02:13:47 +0000 | |||
229 | @@ -139,6 +139,20 @@ | |||
230 | 139 | return 1; | 139 | return 1; |
231 | 140 | } | 140 | } |
232 | 141 | 141 | ||
233 | 142 | ual_tracepoint(exec_parse_complete, app_id); | ||
234 | 143 | |||
235 | 144 | if (g_getenv("MIR_SOCKET") != NULL && g_strcmp0(g_getenv("APP_XMIR_ENABLE"), "1") == 0) { | ||
236 | 145 | g_debug("XMir Helper being used"); | ||
237 | 146 | |||
238 | 147 | /* xmir-helper $(APP_ID) $(COMMAND) */ | ||
239 | 148 | const gchar * appid = g_getenv("APP_ID"); | ||
240 | 149 | g_array_prepend_val(newargv, appid); | ||
241 | 150 | |||
242 | 151 | /* Pulling into the heap instead of the code page */ | ||
243 | 152 | char * xmir_helper = g_strdup(XMIR_HELPER); | ||
244 | 153 | g_array_prepend_val(newargv, xmir_helper); | ||
245 | 154 | } | ||
246 | 155 | |||
247 | 142 | /* Now exec */ | 156 | /* Now exec */ |
248 | 143 | gchar ** nargv = (gchar**)g_array_free(newargv, FALSE); | 157 | gchar ** nargv = (gchar**)g_array_free(newargv, FALSE); |
249 | 144 | 158 | ||
250 | 145 | 159 | ||
251 | === modified file 'helpers-shared.c' | |||
252 | --- helpers-shared.c 2014-11-21 21:17:18 +0000 | |||
253 | +++ helpers-shared.c 2015-08-07 02:13:47 +0000 | |||
254 | @@ -25,7 +25,7 @@ | |||
255 | 25 | #include "libubuntu-app-launch/recoverable-problem.h" | 25 | #include "libubuntu-app-launch/recoverable-problem.h" |
256 | 26 | 26 | ||
257 | 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 */ |
259 | 28 | static gboolean | 28 | gboolean |
260 | 29 | verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop) | 29 | verify_keyfile (GKeyFile * inkeyfile, const gchar * desktop) |
261 | 30 | { | 30 | { |
262 | 31 | if (inkeyfile == NULL) return FALSE; | 31 | if (inkeyfile == NULL) return FALSE; |
263 | 32 | 32 | ||
264 | === modified file 'helpers.h' | |||
265 | --- helpers.h 2014-11-20 20:33:59 +0000 | |||
266 | +++ helpers.h 2015-08-07 02:13:47 +0000 | |||
267 | @@ -54,3 +54,5 @@ | |||
268 | 54 | const gchar * jobname, | 54 | const gchar * jobname, |
269 | 55 | const gchar * instancename); | 55 | const gchar * instancename); |
270 | 56 | 56 | ||
271 | 57 | gboolean verify_keyfile (GKeyFile * inkeyfile, | ||
272 | 58 | const gchar * desktop); | ||
273 | 57 | 59 | ||
274 | === modified file 'libubuntu-app-launch/CMakeLists.txt' | |||
275 | --- libubuntu-app-launch/CMakeLists.txt 2014-11-21 21:17:09 +0000 | |||
276 | +++ libubuntu-app-launch/CMakeLists.txt 2015-08-07 02:13:47 +0000 | |||
277 | @@ -17,7 +17,8 @@ | |||
278 | 17 | add_lttng_gen_tp(NAME ubuntu-app-launch-trace) | 17 | add_lttng_gen_tp(NAME ubuntu-app-launch-trace) |
279 | 18 | 18 | ||
280 | 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") | 19 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fvisibility=hidden") |
282 | 20 | add_definitions ( -DOOM_HELPER="${pkglibexecdir}/oom-adjust-setuid-helper" ) | 20 | add_definitions ( -DOOM_HELPER="${pkglibexecdir}/oom-adjust-setuid-helper" -DDEMANGLER_PATH="${pkglibexecdir}/socket-demangler" ) |
283 | 21 | add_definitions ( -DLIBERTINE_LAUNCH="${CMAKE_INSTALL_FULL_BINDIR}/libertine-launch" ) | ||
284 | 21 | 22 | ||
285 | 22 | set(LAUNCHER_HEADERS | 23 | set(LAUNCHER_HEADERS |
286 | 23 | ubuntu-app-launch.h | 24 | ubuntu-app-launch.h |
287 | @@ -31,7 +32,13 @@ | |||
288 | 31 | ubuntu-app-launch-trace.c | 32 | ubuntu-app-launch-trace.c |
289 | 32 | ) | 33 | ) |
290 | 33 | 34 | ||
292 | 34 | add_library(ubuntu-launcher SHARED ${LAUNCHER_SOURCES}) | 35 | set(LAUNCHER_GEN_SOURCES |
293 | 36 | ) | ||
294 | 37 | |||
295 | 38 | add_gdbus_codegen_with_namespace(LAUNCHER_GEN_SOURCES proxy-socket-demangler com.canonical.UbuntuAppLaunch. proxy ${CMAKE_SOURCE_DIR}/data/com.canonical.UbuntuAppLaunch.SocketDemangler.xml) | ||
296 | 39 | |||
297 | 40 | |||
298 | 41 | add_library(ubuntu-launcher SHARED ${LAUNCHER_SOURCES} ${LAUNCHER_GEN_SOURCES}) | ||
299 | 35 | 42 | ||
300 | 36 | set_target_properties(ubuntu-launcher PROPERTIES | 43 | set_target_properties(ubuntu-launcher PROPERTIES |
301 | 37 | VERSION ${ABI_VERSION}.0.0 | 44 | VERSION ${ABI_VERSION}.0.0 |
302 | @@ -50,6 +57,7 @@ | |||
303 | 50 | ${JSONGLIB_LIBRARIES} | 57 | ${JSONGLIB_LIBRARIES} |
304 | 51 | ${CLICK_LIBRARIES} | 58 | ${CLICK_LIBRARIES} |
305 | 52 | ${ZEITGEIST_LIBRARIES} | 59 | ${ZEITGEIST_LIBRARIES} |
306 | 60 | ${MIR_LIBRARIES} | ||
307 | 53 | helpers | 61 | helpers |
308 | 54 | -Wl,--no-undefined | 62 | -Wl,--no-undefined |
309 | 55 | ) | 63 | ) |
310 | @@ -91,7 +99,8 @@ | |||
311 | 91 | set(UbuntuAppLaunch_2_gir_INCLUDES GObject-2.0) | 99 | set(UbuntuAppLaunch_2_gir_INCLUDES GObject-2.0) |
312 | 92 | 100 | ||
313 | 93 | gir_get_cflags(_cflags) | 101 | gir_get_cflags(_cflags) |
315 | 94 | set(UbuntuAppLaunch_2_gir_CFLAGS ${c_flags}) | 102 | list_prefix(MIR_C_INCLUDES MIR_INCLUDE_DIRS "-I") |
316 | 103 | set(UbuntuAppLaunch_2_gir_CFLAGS ${c_flags} ${MIR_C_INCLUDES}) | ||
317 | 95 | set(UbuntuAppLaunch_2_gir_LIBS ubuntu-app-launch) | 104 | set(UbuntuAppLaunch_2_gir_LIBS ubuntu-app-launch) |
318 | 96 | 105 | ||
319 | 97 | list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/") | 106 | list_make_absolute(_abs_introspection_files _introspection_files "${CMAKE_CURRENT_SOURCE_DIR}/") |
320 | 98 | 107 | ||
321 | === modified file 'libubuntu-app-launch/click-exec.c' | |||
322 | --- libubuntu-app-launch/click-exec.c 2014-08-22 21:04:13 +0000 | |||
323 | +++ libubuntu-app-launch/click-exec.c 2015-08-07 02:13:47 +0000 | |||
324 | @@ -136,6 +136,14 @@ | |||
325 | 136 | return FALSE; | 136 | return FALSE; |
326 | 137 | } | 137 | } |
327 | 138 | 138 | ||
328 | 139 | if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { | ||
329 | 140 | if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { | ||
330 | 141 | env_handle_add(handle, "APP_XMIR_ENABLE", "1"); | ||
331 | 142 | } else { | ||
332 | 143 | env_handle_add(handle, "APP_XMIR_ENABLE", "0"); | ||
333 | 144 | } | ||
334 | 145 | } | ||
335 | 146 | |||
336 | 139 | /* This string is quoted using desktop file quoting: | 147 | /* This string is quoted using desktop file quoting: |
337 | 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 */ |
338 | 141 | gchar * exec = desktop_to_exec(keyfile, desktopfile); | 149 | gchar * exec = desktop_to_exec(keyfile, desktopfile); |
339 | 142 | 150 | ||
340 | === modified file 'libubuntu-app-launch/desktop-exec.c' | |||
341 | --- libubuntu-app-launch/desktop-exec.c 2014-08-22 21:06:00 +0000 | |||
342 | +++ libubuntu-app-launch/desktop-exec.c 2015-08-07 02:13:47 +0000 | |||
343 | @@ -27,6 +27,7 @@ | |||
344 | 27 | #include "ubuntu-app-launch-trace.h" | 27 | #include "ubuntu-app-launch-trace.h" |
345 | 28 | #include "recoverable-problem.h" | 28 | #include "recoverable-problem.h" |
346 | 29 | #include "ual-tracepoint.h" | 29 | #include "ual-tracepoint.h" |
347 | 30 | #include "ubuntu-app-launch.h" | ||
348 | 30 | 31 | ||
349 | 31 | /* Reports an error on the caller of UAL so that we can track | 32 | /* Reports an error on the caller of UAL so that we can track |
350 | 32 | who is trying to launch bad AppIDs, and then fix their bug | 33 | who is trying to launch bad AppIDs, and then fix their bug |
351 | @@ -70,8 +71,65 @@ | |||
352 | 70 | } | 71 | } |
353 | 71 | } | 72 | } |
354 | 72 | 73 | ||
355 | 74 | /* Get the keyfile object for a libertine container based application. Look into | ||
356 | 75 | the container's filesystem on disk and find it in /usr/share/applications in there. | ||
357 | 76 | Those are currently the only apps that we look at today. We're not ensuring anything | ||
358 | 77 | about the file other than it has basic sanity. */ | ||
359 | 78 | GKeyFile * | ||
360 | 79 | keyfile_for_libertine (const gchar * appid, gchar ** outcontainer) | ||
361 | 80 | { | ||
362 | 81 | /* Inital Tests, duplicating to be sure */ | ||
363 | 82 | char * container = NULL; | ||
364 | 83 | char * app = NULL; | ||
365 | 84 | |||
366 | 85 | if (!ubuntu_app_launch_app_id_parse(appid, &container, &app, NULL)) { | ||
367 | 86 | return NULL; | ||
368 | 87 | } | ||
369 | 88 | |||
370 | 89 | gchar * containerdir = g_build_filename(g_get_user_cache_dir(), "libertine-container", container, NULL); | ||
371 | 90 | if (outcontainer != NULL) { | ||
372 | 91 | *outcontainer = container; | ||
373 | 92 | } else { | ||
374 | 93 | g_clear_pointer(&container, g_free); | ||
375 | 94 | } | ||
376 | 95 | |||
377 | 96 | if (!g_file_test(containerdir, G_FILE_TEST_IS_DIR)) { | ||
378 | 97 | g_free(app); | ||
379 | 98 | g_free(containerdir); | ||
380 | 99 | |||
381 | 100 | return NULL; | ||
382 | 101 | } | ||
383 | 102 | |||
384 | 103 | gchar * appdesktop = g_strdup_printf("%s.desktop", app); | ||
385 | 104 | gchar * desktopfile = g_build_filename(containerdir, "usr", "share", "applications", appdesktop, NULL); | ||
386 | 105 | |||
387 | 106 | g_free(containerdir); | ||
388 | 107 | g_free(appdesktop); | ||
389 | 108 | g_free(app); | ||
390 | 109 | |||
391 | 110 | /* We now think we have a valid 'desktopfile' path */ | ||
392 | 111 | GKeyFile * keyfile = g_key_file_new(); | ||
393 | 112 | gboolean loaded = g_key_file_load_from_file(keyfile, desktopfile, G_KEY_FILE_NONE, NULL); | ||
394 | 113 | |||
395 | 114 | if (!loaded) { | ||
396 | 115 | g_free(desktopfile); | ||
397 | 116 | g_key_file_free(keyfile); | ||
398 | 117 | return NULL; | ||
399 | 118 | } | ||
400 | 119 | |||
401 | 120 | if (!verify_keyfile(keyfile, desktopfile)) { | ||
402 | 121 | g_free(desktopfile); | ||
403 | 122 | g_key_file_free(keyfile); | ||
404 | 123 | return NULL; | ||
405 | 124 | } | ||
406 | 125 | |||
407 | 126 | g_free(desktopfile); | ||
408 | 127 | |||
409 | 128 | return keyfile; | ||
410 | 129 | } | ||
411 | 130 | |||
412 | 73 | gboolean | 131 | gboolean |
414 | 74 | desktop_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * handle) | 132 | desktop_task_setup (GDBusConnection * bus, const gchar * app_id, EnvHandle * handle, gboolean is_libertine) |
415 | 75 | { | 133 | { |
416 | 76 | if (app_id == NULL) { | 134 | if (app_id == NULL) { |
417 | 77 | g_error("No APP_ID environment variable defined"); | 135 | g_error("No APP_ID environment variable defined"); |
418 | @@ -88,10 +146,18 @@ | |||
419 | 88 | ual_tracepoint(desktop_starting_sent, app_id); | 146 | ual_tracepoint(desktop_starting_sent, app_id); |
420 | 89 | 147 | ||
421 | 90 | gchar * desktopfilename = NULL; | 148 | gchar * desktopfilename = NULL; |
423 | 91 | GKeyFile * keyfile = keyfile_for_appid(app_id, &desktopfilename); | 149 | GKeyFile * keyfile = NULL; |
424 | 150 | gchar * libertinecontainer = NULL; | ||
425 | 151 | if (is_libertine) { | ||
426 | 152 | /* desktopfilename not set, not useful in this context */ | ||
427 | 153 | keyfile = keyfile_for_libertine(app_id, &libertinecontainer); | ||
428 | 154 | } else { | ||
429 | 155 | keyfile = keyfile_for_appid(app_id, &desktopfilename); | ||
430 | 156 | } | ||
431 | 92 | 157 | ||
432 | 93 | if (keyfile == NULL) { | 158 | if (keyfile == NULL) { |
433 | 94 | report_error_on_caller(app_id); | 159 | report_error_on_caller(app_id); |
434 | 160 | g_free(libertinecontainer); | ||
435 | 95 | return FALSE; | 161 | return FALSE; |
436 | 96 | } | 162 | } |
437 | 97 | 163 | ||
438 | @@ -118,10 +184,37 @@ | |||
439 | 118 | env_handle_add(handle, "APP_EXEC_POLICY", "unconfined"); | 184 | env_handle_add(handle, "APP_EXEC_POLICY", "unconfined"); |
440 | 119 | } | 185 | } |
441 | 120 | 186 | ||
442 | 187 | if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { | ||
443 | 188 | if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { | ||
444 | 189 | env_handle_add(handle, "APP_XMIR_ENABLE", "1"); | ||
445 | 190 | } else { | ||
446 | 191 | env_handle_add(handle, "APP_XMIR_ENABLE", "0"); | ||
447 | 192 | } | ||
448 | 193 | } else if (is_libertine) { | ||
449 | 194 | /* Default to X for libertine stuff */ | ||
450 | 195 | env_handle_add(handle, "APP_XMIR_ENABLE", "1"); | ||
451 | 196 | } | ||
452 | 197 | |||
453 | 121 | /* This string is quoted using desktop file quoting: | 198 | /* This string is quoted using desktop file quoting: |
454 | 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 */ |
455 | 123 | gchar * execline = desktop_to_exec(keyfile, app_id); | 200 | gchar * execline = desktop_to_exec(keyfile, app_id); |
456 | 124 | g_return_val_if_fail(execline != NULL, 1); | 201 | g_return_val_if_fail(execline != NULL, 1); |
457 | 202 | |||
458 | 203 | if (is_libertine) { | ||
459 | 204 | static const gchar * libertine_launch = NULL; | ||
460 | 205 | if (G_UNLIKELY(libertine_launch == NULL)) { | ||
461 | 206 | libertine_launch = g_getenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH"); | ||
462 | 207 | if (libertine_launch == NULL) { | ||
463 | 208 | libertine_launch = LIBERTINE_LAUNCH; | ||
464 | 209 | } | ||
465 | 210 | } | ||
466 | 211 | |||
467 | 212 | gchar * libexec = g_strdup_printf("%s \"%s\" %s", libertine_launch, libertinecontainer, execline); | ||
468 | 213 | g_free(execline); | ||
469 | 214 | execline = libexec; | ||
470 | 215 | } | ||
471 | 216 | g_free(libertinecontainer); /* Handles NULL, let's be sure it goes away */ | ||
472 | 217 | |||
473 | 125 | env_handle_add(handle, "APP_EXEC", execline); | 218 | env_handle_add(handle, "APP_EXEC", execline); |
474 | 126 | g_free(execline); | 219 | g_free(execline); |
475 | 127 | 220 | ||
476 | 128 | 221 | ||
477 | === modified file 'libubuntu-app-launch/desktop-exec.h' | |||
478 | --- libubuntu-app-launch/desktop-exec.h 2014-08-22 20:59:55 +0000 | |||
479 | +++ libubuntu-app-launch/desktop-exec.h 2015-08-07 02:13:47 +0000 | |||
480 | @@ -17,8 +17,10 @@ | |||
481 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
482 | 18 | */ | 18 | */ |
483 | 19 | 19 | ||
484 | 20 | #pragma once | ||
485 | 21 | |||
486 | 20 | #include <glib.h> | 22 | #include <glib.h> |
487 | 21 | #include "helpers.h" | 23 | #include "helpers.h" |
488 | 22 | 24 | ||
490 | 23 | gboolean desktop_task_setup (GDBusConnection * bus, const gchar * appid, EnvHandle * envhandle); | 25 | gboolean desktop_task_setup (GDBusConnection * bus, const gchar * appid, EnvHandle * envhandle, gboolean is_libertine); |
491 | 24 | 26 | ||
492 | 25 | 27 | ||
493 | === modified file 'libubuntu-app-launch/ubuntu-app-launch-trace.tp' | |||
494 | --- libubuntu-app-launch/ubuntu-app-launch-trace.tp 2014-08-21 21:00:53 +0000 | |||
495 | +++ libubuntu-app-launch/ubuntu-app-launch-trace.tp 2015-08-07 02:13:47 +0000 | |||
496 | @@ -18,6 +18,13 @@ | |||
497 | 18 | ctf_string(type, type) | 18 | ctf_string(type, type) |
498 | 19 | ) | 19 | ) |
499 | 20 | ) | 20 | ) |
500 | 21 | TRACEPOINT_EVENT(ubuntu_app_launch, libual_determine_libertine, | ||
501 | 22 | TP_ARGS(const char *, appid, const char *, executionenv), | ||
502 | 23 | TP_FIELDS( | ||
503 | 24 | ctf_string(appid, appid) | ||
504 | 25 | ctf_string(executionenv, executionenv) | ||
505 | 26 | ) | ||
506 | 27 | ) | ||
507 | 21 | TRACEPOINT_EVENT(ubuntu_app_launch, libual_job_path_determined, | 28 | TRACEPOINT_EVENT(ubuntu_app_launch, libual_job_path_determined, |
508 | 22 | TP_ARGS(const char *, appid, const char *, job_path), | 29 | TP_ARGS(const char *, appid, const char *, job_path), |
509 | 23 | TP_FIELDS( | 30 | TP_FIELDS( |
510 | 24 | 31 | ||
511 | === modified file 'libubuntu-app-launch/ubuntu-app-launch.c' | |||
512 | --- libubuntu-app-launch/ubuntu-app-launch.c 2015-04-10 16:58:27 +0000 | |||
513 | +++ libubuntu-app-launch/ubuntu-app-launch.c 2015-08-07 02:13:47 +0000 | |||
514 | @@ -22,6 +22,7 @@ | |||
515 | 22 | #include <click.h> | 22 | #include <click.h> |
516 | 23 | #include <upstart.h> | 23 | #include <upstart.h> |
517 | 24 | #include <gio/gio.h> | 24 | #include <gio/gio.h> |
518 | 25 | #include <gio/gunixfdlist.h> | ||
519 | 25 | #include <string.h> | 26 | #include <string.h> |
520 | 26 | #include <fcntl.h> | 27 | #include <fcntl.h> |
521 | 27 | #include <errno.h> | 28 | #include <errno.h> |
522 | @@ -33,11 +34,18 @@ | |||
523 | 33 | #include "ual-tracepoint.h" | 34 | #include "ual-tracepoint.h" |
524 | 34 | #include "click-exec.h" | 35 | #include "click-exec.h" |
525 | 35 | #include "desktop-exec.h" | 36 | #include "desktop-exec.h" |
526 | 37 | #include "recoverable-problem.h" | ||
527 | 38 | #include "proxy-socket-demangler.h" | ||
528 | 36 | 39 | ||
529 | 37 | static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy); | 40 | static void apps_for_job (GDBusConnection * con, const gchar * name, GArray * apps, gboolean truncate_legacy); |
530 | 38 | static void free_helper (gpointer value); | 41 | static void free_helper (gpointer value); |
531 | 39 | static GList * pids_for_appid (const gchar * appid); | 42 | static GList * pids_for_appid (const gchar * appid); |
532 | 43 | static JsonObject * get_manifest (const gchar * pkg, gchar ** pkgpath); | ||
533 | 40 | int kill (pid_t pid, int signal); | 44 | int kill (pid_t pid, int signal); |
534 | 45 | static gchar * escape_dbus_string (const gchar * input); | ||
535 | 46 | |||
536 | 47 | G_DEFINE_QUARK(UBUNTU_APP_LAUNCH_PROXY_PATH, proxy_path); | ||
537 | 48 | G_DEFINE_QUARK(UBUNTU_APP_LAUNCH_MIR_FD, mir_fd); | ||
538 | 41 | 49 | ||
539 | 42 | /* Function to take the urls and escape them so that they can be | 50 | /* Function to take the urls and escape them so that they can be |
540 | 43 | parsed on the other side correctly. */ | 51 | parsed on the other side correctly. */ |
541 | @@ -201,6 +209,45 @@ | |||
542 | 201 | return click; | 209 | return click; |
543 | 202 | } | 210 | } |
544 | 203 | 211 | ||
545 | 212 | /* Determine whether an AppId is realated to a Libertine container by | ||
546 | 213 | checking the container and program name. */ | ||
547 | 214 | static gboolean | ||
548 | 215 | is_libertine (const gchar * appid) | ||
549 | 216 | { | ||
550 | 217 | char * container = NULL; | ||
551 | 218 | char * app = NULL; | ||
552 | 219 | |||
553 | 220 | if (!ubuntu_app_launch_app_id_parse(appid, &container, &app, NULL)) { | ||
554 | 221 | return FALSE; | ||
555 | 222 | } | ||
556 | 223 | |||
557 | 224 | gchar * containerdir = g_build_filename(g_get_user_cache_dir(), "libertine-container", container, NULL); | ||
558 | 225 | g_free(container); | ||
559 | 226 | |||
560 | 227 | if (!g_file_test(containerdir, G_FILE_TEST_IS_DIR)) { | ||
561 | 228 | g_free(app); | ||
562 | 229 | g_free(containerdir); | ||
563 | 230 | |||
564 | 231 | return FALSE; | ||
565 | 232 | } | ||
566 | 233 | |||
567 | 234 | gchar * appdesktop = g_strdup_printf("%s.desktop", app); | ||
568 | 235 | gchar * desktopfile = g_build_filename(containerdir, "usr", "share", "applications", appdesktop, NULL); | ||
569 | 236 | |||
570 | 237 | g_free(containerdir); | ||
571 | 238 | g_free(appdesktop); | ||
572 | 239 | g_free(app); | ||
573 | 240 | |||
574 | 241 | gboolean islib = g_file_test(desktopfile, G_FILE_TEST_EXISTS); | ||
575 | 242 | g_free(desktopfile); | ||
576 | 243 | |||
577 | 244 | if (islib) { | ||
578 | 245 | g_debug("Detected '%s' as a Libertine Application", appid); | ||
579 | 246 | } | ||
580 | 247 | |||
581 | 248 | return islib; | ||
582 | 249 | } | ||
583 | 250 | |||
584 | 204 | static gboolean | 251 | static gboolean |
585 | 205 | start_application_core (const gchar * appid, const gchar * const * uris, gboolean test) | 252 | start_application_core (const gchar * appid, const gchar * const * uris, gboolean test) |
586 | 206 | { | 253 | { |
587 | @@ -214,6 +261,14 @@ | |||
588 | 214 | gboolean click = is_click(appid); | 261 | gboolean click = is_click(appid); |
589 | 215 | ual_tracepoint(libual_determine_type, appid, click ? "click" : "legacy"); | 262 | ual_tracepoint(libual_determine_type, appid, click ? "click" : "legacy"); |
590 | 216 | 263 | ||
591 | 264 | /* Figure out if it is libertine */ | ||
592 | 265 | gboolean libertine = FALSE; | ||
593 | 266 | if (!click) { | ||
594 | 267 | libertine = is_libertine(appid); | ||
595 | 268 | } | ||
596 | 269 | |||
597 | 270 | ual_tracepoint(libual_determine_libertine, appid, libertine ? "container" : "host"); | ||
598 | 271 | |||
599 | 217 | /* Figure out the DBus path for the job */ | 272 | /* Figure out the DBus path for the job */ |
600 | 218 | const gchar * jobpath = NULL; | 273 | const gchar * jobpath = NULL; |
601 | 219 | if (click) { | 274 | if (click) { |
602 | @@ -251,7 +306,7 @@ | |||
603 | 251 | } | 306 | } |
604 | 252 | 307 | ||
605 | 253 | if (!click) { | 308 | if (!click) { |
607 | 254 | if (legacy_single_instance(appid)) { | 309 | if (libertine || legacy_single_instance(appid)) { |
608 | 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=")); |
609 | 256 | } else { | 311 | } else { |
610 | 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()); |
611 | @@ -267,7 +322,7 @@ | |||
612 | 267 | if (click) { | 322 | if (click) { |
613 | 268 | setup_complete = click_task_setup(con, appid, (EnvHandle*)&builder); | 323 | setup_complete = click_task_setup(con, appid, (EnvHandle*)&builder); |
614 | 269 | } else { | 324 | } else { |
616 | 270 | setup_complete = desktop_task_setup(con, appid, (EnvHandle*)&builder); | 325 | setup_complete = desktop_task_setup(con, appid, (EnvHandle*)&builder, libertine); |
617 | 271 | } | 326 | } |
618 | 272 | 327 | ||
619 | 273 | if (setup_complete) { | 328 | if (setup_complete) { |
620 | @@ -687,7 +742,7 @@ | |||
621 | 687 | return path; | 742 | return path; |
622 | 688 | } | 743 | } |
623 | 689 | 744 | ||
625 | 690 | if (legacy_single_instance(appid)) { | 745 | if (!is_libertine(appid) && legacy_single_instance(appid)) { |
626 | 691 | gchar * appfile = g_strdup_printf("application-legacy-%s-.log", appid); | 746 | gchar * appfile = g_strdup_printf("application-legacy-%s-.log", appid); |
627 | 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); |
628 | 693 | g_free(appfile); | 748 | g_free(appfile); |
629 | @@ -721,6 +776,112 @@ | |||
630 | 721 | return path; | 776 | return path; |
631 | 722 | } | 777 | } |
632 | 723 | 778 | ||
633 | 779 | /* Look to see if the app id results in a desktop file, if so, fill in the params */ | ||
634 | 780 | static gboolean | ||
635 | 781 | evaluate_dir (const gchar * dir, const gchar * desktop, gchar ** appdir, gchar ** appdesktop) | ||
636 | 782 | { | ||
637 | 783 | char * fulldir = g_build_filename(dir, "applications", desktop, NULL); | ||
638 | 784 | |||
639 | 785 | if (g_file_test(fulldir, G_FILE_TEST_EXISTS)) { | ||
640 | 786 | if (appdir != NULL) { | ||
641 | 787 | *appdir = g_strdup(dir); | ||
642 | 788 | } | ||
643 | 789 | |||
644 | 790 | if (appdesktop != NULL) { | ||
645 | 791 | *appdesktop = g_strdup_printf("applications/%s", desktop); | ||
646 | 792 | } | ||
647 | 793 | } | ||
648 | 794 | |||
649 | 795 | g_free(fulldir); | ||
650 | 796 | return FALSE; | ||
651 | 797 | } | ||
652 | 798 | |||
653 | 799 | /* Handle the legacy case where we look through the data directories */ | ||
654 | 800 | static gboolean | ||
655 | 801 | app_info_legacy (const gchar * appid, gchar ** appdir, gchar ** appdesktop) | ||
656 | 802 | { | ||
657 | 803 | gchar * desktop = g_strdup_printf("%s.desktop", appid); | ||
658 | 804 | |||
659 | 805 | /* Special case the user's dir */ | ||
660 | 806 | if (evaluate_dir(g_get_user_data_dir(), desktop, appdir, appdesktop)) { | ||
661 | 807 | g_free(desktop); | ||
662 | 808 | return TRUE; | ||
663 | 809 | } | ||
664 | 810 | |||
665 | 811 | const char * const * data_dirs = g_get_system_data_dirs(); | ||
666 | 812 | int i; | ||
667 | 813 | for (i = 0; data_dirs[i] != NULL; i++) { | ||
668 | 814 | if (evaluate_dir(data_dirs[i], desktop, appdir, appdesktop)) { | ||
669 | 815 | g_free(desktop); | ||
670 | 816 | return TRUE; | ||
671 | 817 | } | ||
672 | 818 | } | ||
673 | 819 | |||
674 | 820 | return FALSE; | ||
675 | 821 | } | ||
676 | 822 | |||
677 | 823 | /* Get the information on where the desktop file is from libclick */ | ||
678 | 824 | static gboolean | ||
679 | 825 | app_info_click (const gchar * appid, gchar ** appdir, gchar ** appdesktop) | ||
680 | 826 | { | ||
681 | 827 | gchar * package = NULL; | ||
682 | 828 | gchar * application = NULL; | ||
683 | 829 | |||
684 | 830 | if (!ubuntu_app_launch_app_id_parse(appid, &package, &application, NULL)) { | ||
685 | 831 | return FALSE; | ||
686 | 832 | } | ||
687 | 833 | |||
688 | 834 | JsonObject * manifest = get_manifest(package, appdir); | ||
689 | 835 | if (manifest == NULL) { | ||
690 | 836 | g_free(package); | ||
691 | 837 | g_free(application); | ||
692 | 838 | return FALSE; | ||
693 | 839 | } | ||
694 | 840 | |||
695 | 841 | g_free(package); | ||
696 | 842 | |||
697 | 843 | if (appdesktop != NULL) { | ||
698 | 844 | JsonObject * hooks = json_object_get_object_member(manifest, "hooks"); | ||
699 | 845 | if (hooks == NULL) { | ||
700 | 846 | json_object_unref(manifest); | ||
701 | 847 | g_free(application); | ||
702 | 848 | return FALSE; | ||
703 | 849 | } | ||
704 | 850 | |||
705 | 851 | JsonObject * appobj = json_object_get_object_member(hooks, application); | ||
706 | 852 | g_free(application); | ||
707 | 853 | |||
708 | 854 | if (appobj == NULL) { | ||
709 | 855 | json_object_unref(manifest); | ||
710 | 856 | return FALSE; | ||
711 | 857 | } | ||
712 | 858 | |||
713 | 859 | const gchar * desktop = json_object_get_string_member(appobj, "desktop"); | ||
714 | 860 | if (desktop == NULL) { | ||
715 | 861 | json_object_unref(manifest); | ||
716 | 862 | return FALSE; | ||
717 | 863 | } | ||
718 | 864 | |||
719 | 865 | *appdesktop = g_strdup(desktop); | ||
720 | 866 | } else { | ||
721 | 867 | g_free(application); | ||
722 | 868 | } | ||
723 | 869 | |||
724 | 870 | json_object_unref(manifest); | ||
725 | 871 | |||
726 | 872 | return TRUE; | ||
727 | 873 | } | ||
728 | 874 | |||
729 | 875 | gboolean | ||
730 | 876 | ubuntu_app_launch_application_info (const gchar * appid, gchar ** appdir, gchar ** appdesktop) | ||
731 | 877 | { | ||
732 | 878 | if (is_click(appid)) { | ||
733 | 879 | return app_info_click(appid, appdir, appdesktop); | ||
734 | 880 | } else { | ||
735 | 881 | return app_info_legacy(appid, appdir, appdesktop); | ||
736 | 882 | } | ||
737 | 883 | } | ||
738 | 884 | |||
739 | 724 | static GDBusConnection * | 885 | static GDBusConnection * |
740 | 725 | gdbus_upstart_ref (void) { | 886 | gdbus_upstart_ref (void) { |
741 | 726 | static GDBusConnection * gdbus_upstart = NULL; | 887 | static GDBusConnection * gdbus_upstart = NULL; |
742 | @@ -1483,7 +1644,7 @@ | |||
743 | 1483 | 1644 | ||
744 | 1484 | ual_tracepoint(pids_list_finished, appid, g_list_length(pids)); | 1645 | ual_tracepoint(pids_list_finished, appid, g_list_length(pids)); |
745 | 1485 | return pids; | 1646 | return pids; |
747 | 1486 | } else if (legacy_single_instance(appid)) { | 1647 | } else if (!is_libertine(appid) && legacy_single_instance(appid)) { |
748 | 1487 | gchar * jobname = g_strdup_printf("%s-", appid); | 1648 | gchar * jobname = g_strdup_printf("%s-", appid); |
749 | 1488 | GList * pids = pids_from_cgroup(cgmanager, "application-legacy", jobname); | 1649 | GList * pids = pids_from_cgroup(cgmanager, "application-legacy", jobname); |
750 | 1489 | g_free(jobname); | 1650 | g_free(jobname); |
751 | @@ -1585,7 +1746,7 @@ | |||
752 | 1585 | 1746 | ||
753 | 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 */ |
754 | 1587 | static JsonObject * | 1748 | static JsonObject * |
756 | 1588 | get_manifest (const gchar * pkg) | 1749 | get_manifest (const gchar * pkg, gchar ** pkgpath) |
757 | 1589 | { | 1750 | { |
758 | 1590 | /* Get the directory from click */ | 1751 | /* Get the directory from click */ |
759 | 1591 | GError * error = NULL; | 1752 | GError * error = NULL; |
760 | @@ -1615,6 +1776,16 @@ | |||
761 | 1615 | g_object_unref(user); | 1776 | g_object_unref(user); |
762 | 1616 | return NULL; | 1777 | return NULL; |
763 | 1617 | } | 1778 | } |
764 | 1779 | |||
765 | 1780 | if (pkgpath != NULL) { | ||
766 | 1781 | *pkgpath = click_user_get_path(user, pkg, &error); | ||
767 | 1782 | if (error != NULL) { | ||
768 | 1783 | g_warning("Unable to get the Click package directory for %s: %s", pkg, error->message); | ||
769 | 1784 | g_error_free(error); | ||
770 | 1785 | g_object_unref(user); | ||
771 | 1786 | return NULL; | ||
772 | 1787 | } | ||
773 | 1788 | } | ||
774 | 1618 | g_object_unref(user); | 1789 | g_object_unref(user); |
775 | 1619 | 1790 | ||
776 | 1620 | if (!json_object_has_member(manifest, "version")) { | 1791 | if (!json_object_has_member(manifest, "version")) { |
777 | @@ -1653,7 +1824,7 @@ | |||
778 | 1653 | } | 1824 | } |
779 | 1654 | 1825 | ||
780 | 1655 | if (*manifest == NULL) { | 1826 | if (*manifest == NULL) { |
782 | 1656 | *manifest = get_manifest(pkg); | 1827 | *manifest = get_manifest(pkg, NULL); |
783 | 1657 | } | 1828 | } |
784 | 1658 | 1829 | ||
785 | 1659 | JsonObject * hooks = json_object_get_object_member(*manifest, "hooks"); | 1830 | JsonObject * hooks = json_object_get_object_member(*manifest, "hooks"); |
786 | @@ -1698,7 +1869,7 @@ | |||
787 | 1698 | return original_ver; | 1869 | return original_ver; |
788 | 1699 | } else { | 1870 | } else { |
789 | 1700 | if (*manifest == NULL) { | 1871 | if (*manifest == NULL) { |
791 | 1701 | *manifest = get_manifest(pkg); | 1872 | *manifest = get_manifest(pkg, NULL); |
792 | 1702 | } | 1873 | } |
793 | 1703 | g_return_val_if_fail(*manifest != NULL, NULL); | 1874 | g_return_val_if_fail(*manifest != NULL, NULL); |
794 | 1704 | 1875 | ||
795 | @@ -1754,7 +1925,7 @@ | |||
796 | 1754 | to define the instance. In the end there's only one job with | 1925 | to define the instance. In the end there's only one job with |
797 | 1755 | an array of instances. */ | 1926 | an array of instances. */ |
798 | 1756 | static gboolean | 1927 | static gboolean |
800 | 1757 | start_helper_core (const gchar * type, const gchar * appid, const gchar * const * uris, const gchar * instance) | 1928 | start_helper_core (const gchar * type, const gchar * appid, const gchar * const * uris, const gchar * instance, const gchar * mirsocketpath) |
801 | 1758 | { | 1929 | { |
802 | 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); |
803 | 1760 | g_return_val_if_fail(con != NULL, FALSE); | 1931 | g_return_val_if_fail(con != NULL, FALSE); |
804 | @@ -1778,6 +1949,11 @@ | |||
805 | 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))); |
806 | 1779 | } | 1950 | } |
807 | 1780 | 1951 | ||
808 | 1952 | if (mirsocketpath != NULL) { | ||
809 | 1953 | g_variant_builder_add_value(&builder, g_variant_new_take_string(g_strdup_printf("UBUNTU_APP_LAUNCH_DEMANGLE_PATH=%s", mirsocketpath))); | ||
810 | 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)))); | ||
811 | 1955 | } | ||
812 | 1956 | |||
813 | 1781 | g_variant_builder_close(&builder); | 1957 | g_variant_builder_close(&builder); |
814 | 1782 | g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); | 1958 | g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); |
815 | 1783 | 1959 | ||
816 | @@ -1807,7 +1983,7 @@ | |||
817 | 1807 | g_return_val_if_fail(appid != NULL, FALSE); | 1983 | g_return_val_if_fail(appid != NULL, FALSE); |
818 | 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); |
819 | 1809 | 1985 | ||
821 | 1810 | return start_helper_core(type, appid, uris, NULL); | 1986 | return start_helper_core(type, appid, uris, NULL, NULL); |
822 | 1811 | } | 1987 | } |
823 | 1812 | 1988 | ||
824 | 1813 | gchar * | 1989 | gchar * |
825 | @@ -1819,10 +1995,254 @@ | |||
826 | 1819 | 1995 | ||
827 | 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()); |
828 | 1821 | 1997 | ||
833 | 1822 | if (start_helper_core(type, appid, uris, instanceid)) { | 1998 | if (start_helper_core(type, appid, uris, instanceid, NULL)) { |
834 | 1823 | return instanceid; | 1999 | return instanceid; |
835 | 1824 | } | 2000 | } |
836 | 1825 | 2001 | ||
837 | 2002 | g_free(instanceid); | ||
838 | 2003 | return NULL; | ||
839 | 2004 | } | ||
840 | 2005 | |||
841 | 2006 | /* Transfer from Mir's data structure to ours */ | ||
842 | 2007 | static void | ||
843 | 2008 | get_mir_session_fd_helper (MirPromptSession * session, size_t count, int const * fdin, void * user_data) | ||
844 | 2009 | { | ||
845 | 2010 | if (count != 1) { | ||
846 | 2011 | g_warning("Mir trusted session returned %d FDs instead of one", (int)count); | ||
847 | 2012 | return; | ||
848 | 2013 | } | ||
849 | 2014 | |||
850 | 2015 | int * retfd = (int *)user_data; | ||
851 | 2016 | *retfd = fdin[0]; | ||
852 | 2017 | } | ||
853 | 2018 | |||
854 | 2019 | /* Setup to get the FD from Mir, blocking */ | ||
855 | 2020 | static int | ||
856 | 2021 | get_mir_session_fd (MirPromptSession * session) | ||
857 | 2022 | { | ||
858 | 2023 | int retfd = 0; | ||
859 | 2024 | MirWaitHandle * wait = mir_prompt_session_new_fds_for_prompt_providers(session, | ||
860 | 2025 | 1, | ||
861 | 2026 | get_mir_session_fd_helper, | ||
862 | 2027 | &retfd); | ||
863 | 2028 | |||
864 | 2029 | mir_wait_for(wait); | ||
865 | 2030 | |||
866 | 2031 | return retfd; | ||
867 | 2032 | } | ||
868 | 2033 | |||
869 | 2034 | static GList * open_proxies = NULL; | ||
870 | 2035 | |||
871 | 2036 | static gint | ||
872 | 2037 | remove_socket_path_find (gconstpointer a, gconstpointer b) | ||
873 | 2038 | { | ||
874 | 2039 | GObject * obj = (GObject *)a; | ||
875 | 2040 | const gchar * path = (const gchar *)b; | ||
876 | 2041 | |||
877 | 2042 | gchar * objpath = g_object_get_qdata(obj, proxy_path_quark()); | ||
878 | 2043 | |||
879 | 2044 | return g_strcmp0(objpath, path); | ||
880 | 2045 | } | ||
881 | 2046 | |||
882 | 2047 | /* Cleans up if we need to early */ | ||
883 | 2048 | static gboolean | ||
884 | 2049 | remove_socket_path (const gchar * path) | ||
885 | 2050 | { | ||
886 | 2051 | GList * thisproxy = g_list_find_custom(open_proxies, path, remove_socket_path_find); | ||
887 | 2052 | if (thisproxy == NULL) | ||
888 | 2053 | return FALSE; | ||
889 | 2054 | |||
890 | 2055 | g_debug("Removing Mir Socket Proxy: %s", path); | ||
891 | 2056 | |||
892 | 2057 | GObject * obj = G_OBJECT(thisproxy->data); | ||
893 | 2058 | open_proxies = g_list_delete_link(open_proxies, thisproxy); | ||
894 | 2059 | |||
895 | 2060 | /* Remove ourselves from DBus if we weren't already */ | ||
896 | 2061 | g_dbus_interface_skeleton_unexport(G_DBUS_INTERFACE_SKELETON(obj)); | ||
897 | 2062 | |||
898 | 2063 | /* If we still have FD, close it */ | ||
899 | 2064 | int mirfd = GPOINTER_TO_INT(g_object_get_qdata(obj, mir_fd_quark())); | ||
900 | 2065 | if (mirfd != 0) { | ||
901 | 2066 | close(mirfd); | ||
902 | 2067 | |||
903 | 2068 | /* This is actually an error, we should expect not to find | ||
904 | 2069 | this here to do anything with it. */ | ||
905 | 2070 | const gchar * props[3] = { | ||
906 | 2071 | "UbuntuAppLaunchProxyDbusPath", | ||
907 | 2072 | NULL, | ||
908 | 2073 | NULL | ||
909 | 2074 | }; | ||
910 | 2075 | props[1] = path; | ||
911 | 2076 | report_recoverable_problem("ubuntu-app-launch-mir-fd-proxy", 0, TRUE, props); | ||
912 | 2077 | } | ||
913 | 2078 | |||
914 | 2079 | g_object_unref(obj); | ||
915 | 2080 | |||
916 | 2081 | return TRUE; | ||
917 | 2082 | } | ||
918 | 2083 | |||
919 | 2084 | /* Small timeout function that shouldn't, in most cases, ever do anything. | ||
920 | 2085 | But we need it here to ensure we don't leave things on the bus */ | ||
921 | 2086 | static gboolean | ||
922 | 2087 | proxy_timeout (gpointer user_data) | ||
923 | 2088 | { | ||
924 | 2089 | const gchar * path = (const gchar *)user_data; | ||
925 | 2090 | remove_socket_path(path); | ||
926 | 2091 | return G_SOURCE_REMOVE; | ||
927 | 2092 | } | ||
928 | 2093 | |||
929 | 2094 | /* Removes the whole list of proxies if they are there */ | ||
930 | 2095 | static void | ||
931 | 2096 | proxy_cleanup_list (void) | ||
932 | 2097 | { | ||
933 | 2098 | while (open_proxies) { | ||
934 | 2099 | GObject * obj = G_OBJECT(open_proxies->data); | ||
935 | 2100 | gchar * path = g_object_get_qdata(obj, proxy_path_quark()); | ||
936 | 2101 | remove_socket_path(path); | ||
937 | 2102 | } | ||
938 | 2103 | } | ||
939 | 2104 | |||
940 | 2105 | static gboolean | ||
941 | 2106 | proxy_mir_socket (GObject * obj, GDBusMethodInvocation * invocation, gpointer user_data) | ||
942 | 2107 | { | ||
943 | 2108 | g_debug("Called to give Mir socket"); | ||
944 | 2109 | int fd = GPOINTER_TO_INT(user_data); | ||
945 | 2110 | |||
946 | 2111 | if (fd == 0) { | ||
947 | 2112 | g_critical("No FDs to give!"); | ||
948 | 2113 | return FALSE; | ||
949 | 2114 | } | ||
950 | 2115 | |||
951 | 2116 | /* Index into fds */ | ||
952 | 2117 | GVariant* handle = g_variant_new_handle(0); | ||
953 | 2118 | GVariant* tuple = g_variant_new_tuple(&handle, 1); | ||
954 | 2119 | |||
955 | 2120 | GError* error = NULL; | ||
956 | 2121 | GUnixFDList* list = g_unix_fd_list_new(); | ||
957 | 2122 | g_unix_fd_list_append(list, fd, &error); | ||
958 | 2123 | |||
959 | 2124 | if (error == NULL) { | ||
960 | 2125 | g_dbus_method_invocation_return_value_with_unix_fd_list(invocation, tuple, list); | ||
961 | 2126 | } else { | ||
962 | 2127 | g_variant_ref_sink(tuple); | ||
963 | 2128 | g_variant_unref(tuple); | ||
964 | 2129 | } | ||
965 | 2130 | |||
966 | 2131 | g_object_unref(list); | ||
967 | 2132 | |||
968 | 2133 | if (error != NULL) { | ||
969 | 2134 | g_critical("Unable to pass FD %d: %s", fd, error->message); | ||
970 | 2135 | g_error_free(error); | ||
971 | 2136 | return FALSE; | ||
972 | 2137 | } | ||
973 | 2138 | |||
974 | 2139 | g_object_set_qdata(obj, mir_fd_quark(), GINT_TO_POINTER(0)); | ||
975 | 2140 | |||
976 | 2141 | return TRUE; | ||
977 | 2142 | } | ||
978 | 2143 | |||
979 | 2144 | /* Sets up the DBus proxy to send to the demangler */ | ||
980 | 2145 | static gchar * | ||
981 | 2146 | build_proxy_socket_path (const gchar * appid, int mirfd) | ||
982 | 2147 | { | ||
983 | 2148 | static gboolean final_cleanup = FALSE; | ||
984 | 2149 | if (!final_cleanup) { | ||
985 | 2150 | g_atexit(proxy_cleanup_list); | ||
986 | 2151 | final_cleanup = TRUE; | ||
987 | 2152 | } | ||
988 | 2153 | |||
989 | 2154 | GError * error = NULL; | ||
990 | 2155 | GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); | ||
991 | 2156 | if (error != NULL) { | ||
992 | 2157 | g_warning("Unable to get session bus: %s", error->message); | ||
993 | 2158 | g_error_free(error); | ||
994 | 2159 | return NULL; | ||
995 | 2160 | } | ||
996 | 2161 | |||
997 | 2162 | /* Export an Object on DBus */ | ||
998 | 2163 | proxySocketDemangler * skel = proxy_socket_demangler_skeleton_new(); | ||
999 | 2164 | g_signal_connect(G_OBJECT(skel), "handle-get-mir-socket", G_CALLBACK(proxy_mir_socket), GINT_TO_POINTER(mirfd)); | ||
1000 | 2165 | |||
1001 | 2166 | gchar * encoded_appid = escape_dbus_string(appid); | ||
1002 | 2167 | gchar * socket_name = NULL; | ||
1003 | 2168 | /* Loop until we fine an object path that isn't taken (probably only once) */ | ||
1004 | 2169 | while (socket_name == NULL) { | ||
1005 | 2170 | gchar* tryname = g_strdup_printf("/com/canonical/UbuntuAppLaunch/%s/%X", encoded_appid, g_random_int()); | ||
1006 | 2171 | g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skel), | ||
1007 | 2172 | session, | ||
1008 | 2173 | tryname, | ||
1009 | 2174 | &error); | ||
1010 | 2175 | |||
1011 | 2176 | if (error == NULL) { | ||
1012 | 2177 | socket_name = tryname; | ||
1013 | 2178 | g_debug("Exporting Mir socket on path: %s", socket_name); | ||
1014 | 2179 | } else { | ||
1015 | 2180 | /* Always print the error, but if the object path is in use let's | ||
1016 | 2181 | not exit the loop. Let's just try again. */ | ||
1017 | 2182 | bool exitnow = (error->domain != G_DBUS_ERROR || error->code != G_DBUS_ERROR_OBJECT_PATH_IN_USE); | ||
1018 | 2183 | g_critical("Unable to export trusted session object: %s", error->message); | ||
1019 | 2184 | |||
1020 | 2185 | g_clear_error(&error); | ||
1021 | 2186 | g_free(tryname); | ||
1022 | 2187 | |||
1023 | 2188 | if (exitnow) { | ||
1024 | 2189 | break; | ||
1025 | 2190 | } | ||
1026 | 2191 | } | ||
1027 | 2192 | } | ||
1028 | 2193 | g_free(encoded_appid); | ||
1029 | 2194 | |||
1030 | 2195 | /* If we didn't get a socket name, we should just exit. And | ||
1031 | 2196 | make sure to clean up the socket. */ | ||
1032 | 2197 | if (socket_name == NULL) { | ||
1033 | 2198 | g_object_unref(skel); | ||
1034 | 2199 | g_object_unref(session); | ||
1035 | 2200 | g_critical("Unable to export object to any name"); | ||
1036 | 2201 | return NULL; | ||
1037 | 2202 | } | ||
1038 | 2203 | |||
1039 | 2204 | g_object_set_qdata_full(G_OBJECT(skel), proxy_path_quark(), g_strdup(socket_name), g_free); | ||
1040 | 2205 | g_object_set_qdata(G_OBJECT(skel), mir_fd_quark(), GINT_TO_POINTER(mirfd)); | ||
1041 | 2206 | open_proxies = g_list_prepend(open_proxies, skel); | ||
1042 | 2207 | |||
1043 | 2208 | g_timeout_add_seconds_full(G_PRIORITY_DEFAULT, | ||
1044 | 2209 | 2, | ||
1045 | 2210 | proxy_timeout, | ||
1046 | 2211 | g_strdup(socket_name), | ||
1047 | 2212 | g_free); | ||
1048 | 2213 | |||
1049 | 2214 | g_object_unref(session); | ||
1050 | 2215 | |||
1051 | 2216 | return socket_name; | ||
1052 | 2217 | } | ||
1053 | 2218 | |||
1054 | 2219 | gchar * | ||
1055 | 2220 | ubuntu_app_launch_start_session_helper (const gchar * type, MirPromptSession * session, const gchar * appid, const gchar * const * uris) | ||
1056 | 2221 | { | ||
1057 | 2222 | g_return_val_if_fail(type != NULL, NULL); | ||
1058 | 2223 | g_return_val_if_fail(session != NULL, NULL); | ||
1059 | 2224 | g_return_val_if_fail(appid != NULL, NULL); | ||
1060 | 2225 | g_return_val_if_fail(g_strstr_len(type, -1, ":") == NULL, NULL); | ||
1061 | 2226 | |||
1062 | 2227 | int mirfd = get_mir_session_fd(session); | ||
1063 | 2228 | if (mirfd == 0) | ||
1064 | 2229 | return NULL; | ||
1065 | 2230 | |||
1066 | 2231 | gchar * socket_path = build_proxy_socket_path(appid, mirfd); | ||
1067 | 2232 | if (socket_path == NULL) { | ||
1068 | 2233 | close(mirfd); | ||
1069 | 2234 | return NULL; | ||
1070 | 2235 | } | ||
1071 | 2236 | |||
1072 | 2237 | gchar * instanceid = g_strdup_printf("%" G_GUINT64_FORMAT, g_get_real_time()); | ||
1073 | 2238 | |||
1074 | 2239 | if (start_helper_core(type, appid, uris, instanceid, socket_path)) { | ||
1075 | 2240 | return instanceid; | ||
1076 | 2241 | } | ||
1077 | 2242 | |||
1078 | 2243 | remove_socket_path(socket_path); | ||
1079 | 2244 | g_free(socket_path); | ||
1080 | 2245 | close(mirfd); | ||
1081 | 1826 | g_free(instanceid); | 2246 | g_free(instanceid); |
1082 | 1827 | return NULL; | 2247 | return NULL; |
1083 | 1828 | } | 2248 | } |
1084 | @@ -2203,3 +2623,104 @@ | |||
1085 | 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); |
1086 | 2204 | } | 2624 | } |
1087 | 2205 | 2625 | ||
1088 | 2626 | /* Sets an environment variable in Upstart */ | ||
1089 | 2627 | static void | ||
1090 | 2628 | set_var (GDBusConnection * bus, const gchar * job_name, const gchar * instance_name, const gchar * envvar) | ||
1091 | 2629 | { | ||
1092 | 2630 | GVariantBuilder builder; /* Target: (assb) */ | ||
1093 | 2631 | g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE); | ||
1094 | 2632 | |||
1095 | 2633 | /* Setup the job properties */ | ||
1096 | 2634 | g_variant_builder_open(&builder, G_VARIANT_TYPE_ARRAY); | ||
1097 | 2635 | g_variant_builder_add_value(&builder, g_variant_new_string(job_name)); | ||
1098 | 2636 | if (instance_name != NULL) | ||
1099 | 2637 | g_variant_builder_add_value(&builder, g_variant_new_string(instance_name)); | ||
1100 | 2638 | g_variant_builder_close(&builder); | ||
1101 | 2639 | |||
1102 | 2640 | g_variant_builder_add_value(&builder, g_variant_new_string(envvar)); | ||
1103 | 2641 | |||
1104 | 2642 | /* Do we want to replace? Yes, we do! */ | ||
1105 | 2643 | g_variant_builder_add_value(&builder, g_variant_new_boolean(TRUE)); | ||
1106 | 2644 | |||
1107 | 2645 | g_dbus_connection_call(bus, | ||
1108 | 2646 | "com.ubuntu.Upstart", | ||
1109 | 2647 | "/com/ubuntu/Upstart", | ||
1110 | 2648 | "com.ubuntu.Upstart0_6", | ||
1111 | 2649 | "SetEnv", | ||
1112 | 2650 | g_variant_builder_end(&builder), | ||
1113 | 2651 | NULL, /* reply */ | ||
1114 | 2652 | G_DBUS_CALL_FLAGS_NONE, | ||
1115 | 2653 | -1, /* timeout */ | ||
1116 | 2654 | NULL, /* cancelable */ | ||
1117 | 2655 | NULL, NULL); /* callback */ | ||
1118 | 2656 | } | ||
1119 | 2657 | |||
1120 | 2658 | gboolean | ||
1121 | 2659 | ubuntu_app_launch_helper_set_exec (const gchar * execline, const gchar * directory) | ||
1122 | 2660 | { | ||
1123 | 2661 | g_return_val_if_fail(execline != NULL, FALSE); | ||
1124 | 2662 | g_return_val_if_fail(execline[0] != '\0', FALSE); | ||
1125 | 2663 | |||
1126 | 2664 | /* Check to see if we can get the job environment */ | ||
1127 | 2665 | const gchar * job_name = g_getenv("UPSTART_JOB"); | ||
1128 | 2666 | const gchar * instance_name = g_getenv("UPSTART_INSTANCE"); | ||
1129 | 2667 | const gchar * demangler = g_getenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME"); | ||
1130 | 2668 | g_return_if_fail(job_name != NULL); | ||
1131 | 2669 | |||
1132 | 2670 | GError * error = NULL; | ||
1133 | 2671 | GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); | ||
1134 | 2672 | |||
1135 | 2673 | if (error != NULL) { | ||
1136 | 2674 | g_warning("Unable to get session bus: %s", error->message); | ||
1137 | 2675 | g_error_free(error); | ||
1138 | 2676 | return FALSE; | ||
1139 | 2677 | } | ||
1140 | 2678 | |||
1141 | 2679 | /* The exec value */ | ||
1142 | 2680 | gchar * envstr = NULL; | ||
1143 | 2681 | if (demangler) { | ||
1144 | 2682 | envstr = g_strdup_printf("APP_EXEC=" DEMANGLER_PATH " %s", execline); | ||
1145 | 2683 | } else { | ||
1146 | 2684 | envstr = g_strdup_printf("APP_EXEC=%s", execline); | ||
1147 | 2685 | } | ||
1148 | 2686 | |||
1149 | 2687 | set_var(bus, job_name, instance_name, envstr); | ||
1150 | 2688 | g_free(envstr); | ||
1151 | 2689 | |||
1152 | 2690 | /* The directory value */ | ||
1153 | 2691 | if (directory != NULL) { | ||
1154 | 2692 | gchar * direnv = g_strdup_printf("APP_DIR=%s", directory); | ||
1155 | 2693 | set_var(bus, job_name, instance_name, direnv); | ||
1156 | 2694 | g_free(direnv); | ||
1157 | 2695 | } | ||
1158 | 2696 | |||
1159 | 2697 | g_object_unref(bus); | ||
1160 | 2698 | |||
1161 | 2699 | return TRUE; | ||
1162 | 2700 | } | ||
1163 | 2701 | |||
1164 | 2702 | |||
1165 | 2703 | /* ensure that all characters are valid in the dbus output string */ | ||
1166 | 2704 | static gchar * | ||
1167 | 2705 | escape_dbus_string (const gchar * input) | ||
1168 | 2706 | { | ||
1169 | 2707 | static const gchar *xdigits = "0123456789abcdef"; | ||
1170 | 2708 | GString *escaped; | ||
1171 | 2709 | gchar c; | ||
1172 | 2710 | |||
1173 | 2711 | g_return_val_if_fail (input != NULL, NULL); | ||
1174 | 2712 | |||
1175 | 2713 | escaped = g_string_new (NULL); | ||
1176 | 2714 | while ((c = *input++)) { | ||
1177 | 2715 | if (g_ascii_isalnum (c)) { | ||
1178 | 2716 | g_string_append_c (escaped, c); | ||
1179 | 2717 | } else { | ||
1180 | 2718 | g_string_append_c (escaped, '_'); | ||
1181 | 2719 | g_string_append_c (escaped, xdigits[c >> 4]); | ||
1182 | 2720 | g_string_append_c (escaped, xdigits[c & 0xf]); | ||
1183 | 2721 | } | ||
1184 | 2722 | } | ||
1185 | 2723 | |||
1186 | 2724 | return g_string_free (escaped, FALSE); | ||
1187 | 2725 | } | ||
1188 | 2726 | |||
1189 | 2206 | 2727 | ||
1190 | === modified file 'libubuntu-app-launch/ubuntu-app-launch.h' | |||
1191 | --- libubuntu-app-launch/ubuntu-app-launch.h 2015-02-25 22:20:14 +0000 | |||
1192 | +++ libubuntu-app-launch/ubuntu-app-launch.h 2015-08-07 02:13:47 +0000 | |||
1193 | @@ -18,6 +18,7 @@ | |||
1194 | 18 | */ | 18 | */ |
1195 | 19 | 19 | ||
1196 | 20 | #include <glib.h> | 20 | #include <glib.h> |
1197 | 21 | #include <mir_toolkit/mir_prompt_session.h> | ||
1198 | 21 | 22 | ||
1199 | 22 | #ifndef __UBUNTU_APP_LAUNCH_H__ | 23 | #ifndef __UBUNTU_APP_LAUNCH_H__ |
1200 | 23 | #define __UBUNTU_APP_LAUNCH_H__ 1 | 24 | #define __UBUNTU_APP_LAUNCH_H__ 1 |
1201 | @@ -141,6 +142,19 @@ | |||
1202 | 141 | gchar * ubuntu_app_launch_application_log_path (const gchar * appid); | 142 | gchar * ubuntu_app_launch_application_log_path (const gchar * appid); |
1203 | 142 | 143 | ||
1204 | 143 | /** | 144 | /** |
1205 | 145 | * ubuntu_app_launch_application_info: | ||
1206 | 146 | * @appid: ID of the application | ||
1207 | 147 | * @appdir: (allow-none) (transfer full): Directory for the application | ||
1208 | 148 | * @appdesktop: (allow-none) (transfer full): Relative path to desktop file | ||
1209 | 149 | * | ||
1210 | 150 | * | ||
1211 | 151 | * Return value: Path to a log file or NULL if unavailable | ||
1212 | 152 | */ | ||
1213 | 153 | gboolean ubuntu_app_launch_application_info (const gchar * appid, | ||
1214 | 154 | gchar ** appdir, | ||
1215 | 155 | gchar ** appdesktop); | ||
1216 | 156 | |||
1217 | 157 | /** | ||
1218 | 144 | * ubuntu_app_launch_observer_add_app_starting: | 158 | * ubuntu_app_launch_observer_add_app_starting: |
1219 | 145 | * @observer: (scope notified): Callback when an application is about to start | 159 | * @observer: (scope notified): Callback when an application is about to start |
1220 | 146 | * @user_data: (closure) (allow-none): Data to pass to the observer | 160 | * @user_data: (closure) (allow-none): Data to pass to the observer |
1221 | @@ -450,7 +464,7 @@ | |||
1222 | 450 | * @appid: App ID of the helper | 464 | * @appid: App ID of the helper |
1223 | 451 | * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper | 465 | * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper |
1224 | 452 | * | 466 | * |
1226 | 453 | * Start an untrusted helper for a specific @type on a given | 467 | * Start an untrusted helper for a specific @type of a given |
1227 | 454 | * @appid. We don't know how that is done specifically, as Upstart | 468 | * @appid. We don't know how that is done specifically, as Upstart |
1228 | 455 | * will call a helper for that type. And then execute it under the | 469 | * will call a helper for that type. And then execute it under the |
1229 | 456 | * Apparmor profile for that helper type. This function is different | 470 | * Apparmor profile for that helper type. This function is different |
1230 | @@ -465,6 +479,29 @@ | |||
1231 | 465 | const gchar * const * uris); | 479 | const gchar * const * uris); |
1232 | 466 | 480 | ||
1233 | 467 | /** | 481 | /** |
1234 | 482 | * ubuntu_app_launch_start_session_helper: | ||
1235 | 483 | * @type: Type of helper | ||
1236 | 484 | * @session: Mir Trusted Prompt Session to run the helper under | ||
1237 | 485 | * @appid: App ID of the helper | ||
1238 | 486 | * @uris: (allow-none) (array zero-terminated=1) (element-type utf8) (transfer none): A NULL terminated list of URIs to send to the helper | ||
1239 | 487 | * | ||
1240 | 488 | * Start an untrusted helper for a specific @type of a given | ||
1241 | 489 | * @appid running under a Mir Trusted Prompt Session @session. The | ||
1242 | 490 | * helper's MIR_SOCKET environment variable will be set appropriately | ||
1243 | 491 | * so that the helper will draw on the correct surfaces. Otherwise this | ||
1244 | 492 | * is the same as #ubuntu_app_launch_start_multiple_helper. | ||
1245 | 493 | * | ||
1246 | 494 | * It is important that all exec tools for @type call the function | ||
1247 | 495 | * #ubuntu_app_launch_helper_set_exec to set the exec line. | ||
1248 | 496 | * | ||
1249 | 497 | * Return value: The generated instance ID or NULL on failure | ||
1250 | 498 | */ | ||
1251 | 499 | gchar * ubuntu_app_launch_start_session_helper (const gchar * type, | ||
1252 | 500 | MirPromptSession * session, | ||
1253 | 501 | const gchar * appid, | ||
1254 | 502 | const gchar * const * uris); | ||
1255 | 503 | |||
1256 | 504 | /** | ||
1257 | 468 | * ubuntu_app_launch_stop_helper: | 505 | * ubuntu_app_launch_stop_helper: |
1258 | 469 | * @type: Type of helper | 506 | * @type: Type of helper |
1259 | 470 | * @appid: App ID of the helper | 507 | * @appid: App ID of the helper |
1260 | @@ -574,6 +611,24 @@ | |||
1261 | 574 | const gchar * helper_type, | 611 | const gchar * helper_type, |
1262 | 575 | gpointer user_data); | 612 | gpointer user_data); |
1263 | 576 | 613 | ||
1264 | 614 | /** | ||
1265 | 615 | * ubuntu_app_launch_helper_set_exec: | ||
1266 | 616 | * @execline: Exec line to be executed, in Desktop file format | ||
1267 | 617 | * @directory: (allow-none): The directory that the exec line should | ||
1268 | 618 | * be executed in. | ||
1269 | 619 | * | ||
1270 | 620 | * A function to be called by an untrusted helper exec | ||
1271 | 621 | * tool to set the exec line. The exec tool should determine | ||
1272 | 622 | * what should be executed from some sort of configuration | ||
1273 | 623 | * based on its type (usually a configuration file from a click | ||
1274 | 624 | * package). Once it determines the exec line it can set it | ||
1275 | 625 | * with this function and exit. | ||
1276 | 626 | * | ||
1277 | 627 | * Return Value: Whether we were able to set the exec line | ||
1278 | 628 | */ | ||
1279 | 629 | gboolean ubuntu_app_launch_helper_set_exec (const gchar * execline, | ||
1280 | 630 | const gchar * directory); | ||
1281 | 631 | |||
1282 | 577 | #ifdef __cplusplus | 632 | #ifdef __cplusplus |
1283 | 578 | } | 633 | } |
1284 | 579 | #endif | 634 | #endif |
1285 | 580 | 635 | ||
1286 | === modified file 'libubuntu-app-launch/ubuntu-app-launch.pc.in' | |||
1287 | --- libubuntu-app-launch/ubuntu-app-launch.pc.in 2014-04-30 15:45:23 +0000 | |||
1288 | +++ libubuntu-app-launch/ubuntu-app-launch.pc.in 2015-08-07 02:13:47 +0000 | |||
1289 | @@ -2,7 +2,7 @@ | |||
1290 | 2 | includedir=@includedir@ | 2 | includedir=@includedir@ |
1291 | 3 | 3 | ||
1292 | 4 | Cflags: -I${includedir}/libubuntu-app-launch-@apiversion@ | 4 | Cflags: -I${includedir}/libubuntu-app-launch-@apiversion@ |
1294 | 5 | Requires: glib-2.0 | 5 | Requires: glib-2.0 mirclient |
1295 | 6 | Libs: -L${libdir} -lubuntu-app-launch | 6 | Libs: -L${libdir} -lubuntu-app-launch |
1296 | 7 | 7 | ||
1297 | 8 | Name: libubuntu-app-launch | 8 | Name: libubuntu-app-launch |
1298 | 9 | 9 | ||
1299 | === added file 'socket-demangler.c' | |||
1300 | --- socket-demangler.c 1970-01-01 00:00:00 +0000 | |||
1301 | +++ socket-demangler.c 2015-08-07 02:13:47 +0000 | |||
1302 | @@ -0,0 +1,124 @@ | |||
1303 | 1 | /* | ||
1304 | 2 | * Copyright © 2014 Canonical Ltd. | ||
1305 | 3 | * | ||
1306 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
1307 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
1308 | 6 | * by the Free Software Foundation. | ||
1309 | 7 | * | ||
1310 | 8 | * This program is distributed in the hope that it will be useful, but | ||
1311 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
1312 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
1313 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
1314 | 12 | * | ||
1315 | 13 | * You should have received a copy of the GNU General Public License along | ||
1316 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
1317 | 15 | * | ||
1318 | 16 | * Authors: | ||
1319 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
1320 | 18 | */ | ||
1321 | 19 | |||
1322 | 20 | #define _POSIX_C_SOURCE 200112L | ||
1323 | 21 | |||
1324 | 22 | #include <gio/gio.h> | ||
1325 | 23 | #include <gio/gunixfdlist.h> | ||
1326 | 24 | |||
1327 | 25 | #include <stdio.h> | ||
1328 | 26 | #include <stdlib.h> | ||
1329 | 27 | #include <errno.h> | ||
1330 | 28 | #include <fcntl.h> | ||
1331 | 29 | |||
1332 | 30 | int | ||
1333 | 31 | main (int argc, char * argv[]) | ||
1334 | 32 | { | ||
1335 | 33 | const gchar * mir_name = g_getenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME"); | ||
1336 | 34 | const gchar * mir_socket = g_getenv("UBUNTU_APP_LAUNCH_DEMANGLE_PATH"); | ||
1337 | 35 | if (mir_socket == NULL || mir_socket[0] == '\0') { | ||
1338 | 36 | g_error("Unable to find Mir path for service"); | ||
1339 | 37 | return -1; | ||
1340 | 38 | } | ||
1341 | 39 | if (mir_name == NULL || mir_name[0] == '\0') { | ||
1342 | 40 | g_error("Unable to find Mir name for service"); | ||
1343 | 41 | return -1; | ||
1344 | 42 | } | ||
1345 | 43 | |||
1346 | 44 | g_debug("Mir socket connection to %s:%s", mir_name, mir_socket); | ||
1347 | 45 | |||
1348 | 46 | GError * error = NULL; | ||
1349 | 47 | GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, &error); | ||
1350 | 48 | |||
1351 | 49 | if (error != NULL) { | ||
1352 | 50 | g_error("Unable to get session bus: %s", error->message); | ||
1353 | 51 | g_error_free(error); | ||
1354 | 52 | return -1; | ||
1355 | 53 | } | ||
1356 | 54 | |||
1357 | 55 | GVariant * retval; | ||
1358 | 56 | GUnixFDList * fdlist; | ||
1359 | 57 | |||
1360 | 58 | retval = g_dbus_connection_call_with_unix_fd_list_sync( | ||
1361 | 59 | bus, | ||
1362 | 60 | mir_name, | ||
1363 | 61 | mir_socket, | ||
1364 | 62 | "com.canonical.UbuntuAppLaunch.SocketDemangler", | ||
1365 | 63 | "GetMirSocket", | ||
1366 | 64 | NULL, | ||
1367 | 65 | G_VARIANT_TYPE("(h)"), | ||
1368 | 66 | G_DBUS_CALL_FLAGS_NO_AUTO_START, | ||
1369 | 67 | -1, /* timeout */ | ||
1370 | 68 | NULL, /* fd list in */ | ||
1371 | 69 | &fdlist, | ||
1372 | 70 | NULL, /* cancelable */ | ||
1373 | 71 | &error); | ||
1374 | 72 | |||
1375 | 73 | g_clear_object(&bus); | ||
1376 | 74 | |||
1377 | 75 | if (error != NULL) { | ||
1378 | 76 | g_error("Unable to get Mir socket over dbus: %s", error->message); | ||
1379 | 77 | g_error_free(error); | ||
1380 | 78 | return -1; | ||
1381 | 79 | } | ||
1382 | 80 | |||
1383 | 81 | GVariant * outhandle = g_variant_get_child_value(retval, 0); | ||
1384 | 82 | |||
1385 | 83 | if (outhandle == NULL) { | ||
1386 | 84 | g_error("Unable to get data from function"); | ||
1387 | 85 | return -1; | ||
1388 | 86 | } | ||
1389 | 87 | |||
1390 | 88 | gint32 handle = g_variant_get_handle(outhandle); | ||
1391 | 89 | g_variant_unref(outhandle); | ||
1392 | 90 | g_variant_unref(retval); | ||
1393 | 91 | |||
1394 | 92 | if (handle >= g_unix_fd_list_get_length(fdlist)) { | ||
1395 | 93 | g_error("Handle is %d but the FD list only has %d entries", handle, g_unix_fd_list_get_length(fdlist)); | ||
1396 | 94 | g_clear_object(&fdlist); | ||
1397 | 95 | return -1; | ||
1398 | 96 | } | ||
1399 | 97 | |||
1400 | 98 | gint32 fd = g_unix_fd_list_get(fdlist, handle, &error); | ||
1401 | 99 | g_clear_object(&fdlist); | ||
1402 | 100 | |||
1403 | 101 | if (error != NULL) { | ||
1404 | 102 | g_error("Unable to Unix FD: %s", error->message); | ||
1405 | 103 | g_error_free(error); | ||
1406 | 104 | return -1; | ||
1407 | 105 | } | ||
1408 | 106 | |||
1409 | 107 | errno = 0; | ||
1410 | 108 | fcntl(fd, F_GETFD); | ||
1411 | 109 | if (errno != 0) { | ||
1412 | 110 | perror("File descriptor is invalid"); | ||
1413 | 111 | return -1; | ||
1414 | 112 | } | ||
1415 | 113 | |||
1416 | 114 | /* Make sure the FD doesn't close on exec */ | ||
1417 | 115 | fcntl(fd, F_SETFD, 0); | ||
1418 | 116 | |||
1419 | 117 | gchar * mirsocketbuf = g_strdup_printf("fd://%d", fd); | ||
1420 | 118 | setenv("MIR_SOCKET", mirsocketbuf, 1); | ||
1421 | 119 | g_debug("MIR_SOCKET=%s", mirsocketbuf); | ||
1422 | 120 | |||
1423 | 121 | g_free(mirsocketbuf); | ||
1424 | 122 | |||
1425 | 123 | return execvp(argv[1], argv + 1); | ||
1426 | 124 | } | ||
1427 | 0 | 125 | ||
1428 | === modified file 'tests/CMakeLists.txt' | |||
1429 | --- tests/CMakeLists.txt 2015-04-06 21:28:13 +0000 | |||
1430 | +++ tests/CMakeLists.txt 2015-08-07 02:13:47 +0000 | |||
1431 | @@ -32,15 +32,23 @@ | |||
1432 | 32 | 32 | ||
1433 | 33 | include_directories("${CMAKE_SOURCE_DIR}/libubuntu-app-launch") | 33 | include_directories("${CMAKE_SOURCE_DIR}/libubuntu-app-launch") |
1434 | 34 | add_definitions ( -DSPEW_UTILITY="${CMAKE_CURRENT_BINARY_DIR}/data-spew" ) | 34 | add_definitions ( -DSPEW_UTILITY="${CMAKE_CURRENT_BINARY_DIR}/data-spew" ) |
1435 | 35 | add_definitions ( -DSESSION_TEMP_FILE="${CMAKE_CURRENT_BINARY_DIR}/libual-test-session-start-temp" ) | ||
1436 | 36 | add_definitions ( -DSOCKET_DEMANGLER="${CMAKE_BINARY_DIR}/socket-demangler" ) | ||
1437 | 37 | add_definitions ( -DSOCKET_DEMANGLER_INSTALL="${pkglibexecdir}/socket-demangler" ) | ||
1438 | 38 | add_definitions ( -DSOCKET_TOOL="${CMAKE_CURRENT_BINARY_DIR}/socket-tool" ) | ||
1439 | 35 | 39 | ||
1440 | 36 | add_executable (libual-test | 40 | add_executable (libual-test |
1442 | 37 | libual-test.cc) | 41 | libual-test.cc |
1443 | 42 | mir-mock.cpp) | ||
1444 | 38 | target_link_libraries (libual-test gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} ubuntu-launcher) | 43 | target_link_libraries (libual-test gtest ${GTEST_LIBS} ${LIBUPSTART_LIBRARIES} ${DBUSTEST_LIBRARIES} ubuntu-launcher) |
1445 | 39 | 44 | ||
1446 | 40 | add_executable (data-spew | 45 | add_executable (data-spew |
1447 | 41 | data-spew.c) | 46 | data-spew.c) |
1448 | 42 | target_link_libraries (data-spew ${GLIB2_LIBRARIES}) | 47 | target_link_libraries (data-spew ${GLIB2_LIBRARIES}) |
1449 | 43 | 48 | ||
1450 | 49 | add_executable (socket-tool | ||
1451 | 50 | socket-tool.c) | ||
1452 | 51 | |||
1453 | 44 | add_test (NAME libual-test COMMAND libual-test) | 52 | add_test (NAME libual-test COMMAND libual-test) |
1454 | 45 | 53 | ||
1455 | 46 | # Failure Test | 54 | # Failure Test |
1456 | @@ -87,3 +95,9 @@ | |||
1457 | 87 | configure_file ("click-desktop-hook-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-desktop-hook-db/test.conf" @ONLY) | 95 | configure_file ("click-desktop-hook-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-desktop-hook-db/test.conf" @ONLY) |
1458 | 88 | configure_file ("desktop-hook-test.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/desktop-hook-test.sh" @ONLY) | 96 | configure_file ("desktop-hook-test.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/desktop-hook-test.sh" @ONLY) |
1459 | 89 | add_test (desktop-hook-test desktop-hook-test.sh) | 97 | add_test (desktop-hook-test desktop-hook-test.sh) |
1460 | 98 | |||
1461 | 99 | # XMir helper Test | ||
1462 | 100 | |||
1463 | 101 | configure_file ("xmir-helper-test.in" "${CMAKE_CURRENT_BINARY_DIR}/xmir-helper-test" @ONLY) | ||
1464 | 102 | add_test (xmir-helper-test xmir-helper-test) | ||
1465 | 103 | |||
1466 | 90 | 104 | ||
1467 | === added file 'tests/applications/noxmir.desktop' | |||
1468 | --- tests/applications/noxmir.desktop 1970-01-01 00:00:00 +0000 | |||
1469 | +++ tests/applications/noxmir.desktop 2015-08-07 02:13:47 +0000 | |||
1470 | @@ -0,0 +1,8 @@ | |||
1471 | 1 | [Desktop Entry] | ||
1472 | 2 | Name=No XMir Needed | ||
1473 | 3 | Type=Application | ||
1474 | 4 | Exec=noxmir | ||
1475 | 5 | NoDisplay=false | ||
1476 | 6 | Hidden=false | ||
1477 | 7 | Terminal=false | ||
1478 | 8 | X-Ubuntu-XMir-Enable=false | ||
1479 | 0 | 9 | ||
1480 | === added file 'tests/applications/xmir.desktop' | |||
1481 | --- tests/applications/xmir.desktop 1970-01-01 00:00:00 +0000 | |||
1482 | +++ tests/applications/xmir.desktop 2015-08-07 02:13:47 +0000 | |||
1483 | @@ -0,0 +1,8 @@ | |||
1484 | 1 | [Desktop Entry] | ||
1485 | 2 | Name=X Application | ||
1486 | 3 | Type=Application | ||
1487 | 4 | Exec=xfoo | ||
1488 | 5 | NoDisplay=false | ||
1489 | 6 | Hidden=false | ||
1490 | 7 | Terminal=false | ||
1491 | 8 | X-Ubuntu-XMir-Enable=true | ||
1492 | 0 | 9 | ||
1493 | === added file 'tests/click-app-dir/.click/info/com.test.mir.manifest' | |||
1494 | --- tests/click-app-dir/.click/info/com.test.mir.manifest 1970-01-01 00:00:00 +0000 | |||
1495 | +++ tests/click-app-dir/.click/info/com.test.mir.manifest 2015-08-07 02:13:47 +0000 | |||
1496 | @@ -0,0 +1,11 @@ | |||
1497 | 1 | { | ||
1498 | 2 | "version": "1", | ||
1499 | 3 | "hooks": { | ||
1500 | 4 | "mir": { | ||
1501 | 5 | "desktop": "xmir.desktop" | ||
1502 | 6 | }, | ||
1503 | 7 | "nomir": { | ||
1504 | 8 | "desktop": "noxmir.desktop" | ||
1505 | 9 | } | ||
1506 | 10 | } | ||
1507 | 11 | } | ||
1508 | 0 | 12 | ||
1509 | === added file 'tests/click-app-dir/noxmir.desktop' | |||
1510 | --- tests/click-app-dir/noxmir.desktop 1970-01-01 00:00:00 +0000 | |||
1511 | +++ tests/click-app-dir/noxmir.desktop 2015-08-07 02:13:47 +0000 | |||
1512 | @@ -0,0 +1,8 @@ | |||
1513 | 1 | [Desktop Entry] | ||
1514 | 2 | Name=No XMir Needed | ||
1515 | 3 | Type=Application | ||
1516 | 4 | Exec=noxmir | ||
1517 | 5 | NoDisplay=false | ||
1518 | 6 | Hidden=false | ||
1519 | 7 | Terminal=false | ||
1520 | 8 | X-Ubuntu-XMir-Enable=false | ||
1521 | 0 | 9 | ||
1522 | === added file 'tests/click-app-dir/xmir.desktop' | |||
1523 | --- tests/click-app-dir/xmir.desktop 1970-01-01 00:00:00 +0000 | |||
1524 | +++ tests/click-app-dir/xmir.desktop 2015-08-07 02:13:47 +0000 | |||
1525 | @@ -0,0 +1,8 @@ | |||
1526 | 1 | [Desktop Entry] | ||
1527 | 2 | Name=X Application | ||
1528 | 3 | Type=Application | ||
1529 | 4 | Exec=xfoo | ||
1530 | 5 | NoDisplay=false | ||
1531 | 6 | Hidden=false | ||
1532 | 7 | Terminal=false | ||
1533 | 8 | X-Ubuntu-XMir-Enable=true | ||
1534 | 0 | 9 | ||
1535 | === added symlink 'tests/click-root-dir/.click/users/test-user/com.test.mir' | |||
1536 | === target is u'../../../com.test.mir/1/' | |||
1537 | === added directory 'tests/click-root-dir/com.test.mir' | |||
1538 | === added symlink 'tests/click-root-dir/com.test.mir/1' | |||
1539 | === target is u'../../click-app-dir/' | |||
1540 | === modified file 'tests/exec-util-test.cc' | |||
1541 | --- tests/exec-util-test.cc 2014-08-26 02:21:57 +0000 | |||
1542 | +++ tests/exec-util-test.cc 2015-08-07 02:13:47 +0000 | |||
1543 | @@ -37,6 +37,8 @@ | |||
1544 | 37 | virtual void SetUp() { | 37 | virtual void SetUp() { |
1545 | 38 | g_setenv("UPSTART_JOB", "made-up-job", TRUE); | 38 | g_setenv("UPSTART_JOB", "made-up-job", TRUE); |
1546 | 39 | g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); | 39 | g_setenv("XDG_DATA_DIRS", CMAKE_SOURCE_DIR, TRUE); |
1547 | 40 | g_setenv("XDG_CACHE_HOME", CMAKE_SOURCE_DIR "/libertine-data", TRUE); | ||
1548 | 41 | g_setenv("UBUNTU_APP_LAUNCH_LIBERTINE_LAUNCH", "libertine-launch", TRUE); | ||
1549 | 40 | 42 | ||
1550 | 41 | service = dbus_test_service_new(NULL); | 43 | service = dbus_test_service_new(NULL); |
1551 | 42 | 44 | ||
1552 | @@ -271,3 +273,258 @@ | |||
1553 | 271 | EXPECT_TRUE(got_app_pid); | 273 | EXPECT_TRUE(got_app_pid); |
1554 | 272 | EXPECT_TRUE(got_instance_id); | 274 | EXPECT_TRUE(got_instance_id); |
1555 | 273 | } | 275 | } |
1556 | 276 | |||
1557 | 277 | TEST_F(ExecUtil, DesktopMir) | ||
1558 | 278 | { | ||
1559 | 279 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); | ||
1560 | 280 | |||
1561 | 281 | ASSERT_TRUE(ubuntu_app_launch_start_application("xmir", NULL)); | ||
1562 | 282 | |||
1563 | 283 | guint len = 0; | ||
1564 | 284 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); | ||
1565 | 285 | |||
1566 | 286 | ASSERT_EQ(1, len); | ||
1567 | 287 | ASSERT_NE(nullptr, calls); | ||
1568 | 288 | ASSERT_STREQ("Start", calls[0].name); | ||
1569 | 289 | |||
1570 | 290 | unsigned int i; | ||
1571 | 291 | |||
1572 | 292 | bool got_mir = false; | ||
1573 | 293 | |||
1574 | 294 | GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); | ||
1575 | 295 | GVariantIter iter; | ||
1576 | 296 | g_variant_iter_init(&iter, envarray); | ||
1577 | 297 | gchar * envvar = NULL; | ||
1578 | 298 | |||
1579 | 299 | while (g_variant_iter_loop(&iter, "s", &envvar)) { | ||
1580 | 300 | gchar * var = g_strdup(envvar); | ||
1581 | 301 | |||
1582 | 302 | gchar * equal = g_strstr_len(var, -1, "="); | ||
1583 | 303 | ASSERT_NE(equal, nullptr); | ||
1584 | 304 | |||
1585 | 305 | equal[0] = '\0'; | ||
1586 | 306 | gchar * value = &(equal[1]); | ||
1587 | 307 | |||
1588 | 308 | if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) { | ||
1589 | 309 | EXPECT_STREQ("1", value); | ||
1590 | 310 | got_mir = true; | ||
1591 | 311 | } | ||
1592 | 312 | |||
1593 | 313 | g_free(var); | ||
1594 | 314 | } | ||
1595 | 315 | |||
1596 | 316 | g_variant_unref(envarray); | ||
1597 | 317 | |||
1598 | 318 | EXPECT_TRUE(got_mir); | ||
1599 | 319 | } | ||
1600 | 320 | |||
1601 | 321 | TEST_F(ExecUtil, DesktopNoMir) | ||
1602 | 322 | { | ||
1603 | 323 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); | ||
1604 | 324 | |||
1605 | 325 | ASSERT_TRUE(ubuntu_app_launch_start_application("noxmir", NULL)); | ||
1606 | 326 | |||
1607 | 327 | guint len = 0; | ||
1608 | 328 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); | ||
1609 | 329 | |||
1610 | 330 | ASSERT_EQ(1, len); | ||
1611 | 331 | ASSERT_NE(nullptr, calls); | ||
1612 | 332 | ASSERT_STREQ("Start", calls[0].name); | ||
1613 | 333 | |||
1614 | 334 | unsigned int i; | ||
1615 | 335 | |||
1616 | 336 | bool got_mir = false; | ||
1617 | 337 | |||
1618 | 338 | GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); | ||
1619 | 339 | GVariantIter iter; | ||
1620 | 340 | g_variant_iter_init(&iter, envarray); | ||
1621 | 341 | gchar * envvar = NULL; | ||
1622 | 342 | |||
1623 | 343 | while (g_variant_iter_loop(&iter, "s", &envvar)) { | ||
1624 | 344 | gchar * var = g_strdup(envvar); | ||
1625 | 345 | |||
1626 | 346 | gchar * equal = g_strstr_len(var, -1, "="); | ||
1627 | 347 | ASSERT_NE(equal, nullptr); | ||
1628 | 348 | |||
1629 | 349 | equal[0] = '\0'; | ||
1630 | 350 | gchar * value = &(equal[1]); | ||
1631 | 351 | |||
1632 | 352 | if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) { | ||
1633 | 353 | EXPECT_STREQ("0", value); | ||
1634 | 354 | got_mir = true; | ||
1635 | 355 | } | ||
1636 | 356 | |||
1637 | 357 | g_free(var); | ||
1638 | 358 | } | ||
1639 | 359 | |||
1640 | 360 | g_variant_unref(envarray); | ||
1641 | 361 | |||
1642 | 362 | EXPECT_TRUE(got_mir); | ||
1643 | 363 | } | ||
1644 | 364 | |||
1645 | 365 | TEST_F(ExecUtil, ClickMir) | ||
1646 | 366 | { | ||
1647 | 367 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); | ||
1648 | 368 | |||
1649 | 369 | g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); | ||
1650 | 370 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); | ||
1651 | 371 | g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE); | ||
1652 | 372 | |||
1653 | 373 | ASSERT_TRUE(ubuntu_app_launch_start_application("com.test.mir_mir_1", NULL)); | ||
1654 | 374 | |||
1655 | 375 | guint len = 0; | ||
1656 | 376 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); | ||
1657 | 377 | |||
1658 | 378 | ASSERT_EQ(1, len); | ||
1659 | 379 | ASSERT_NE(nullptr, calls); | ||
1660 | 380 | ASSERT_STREQ("Start", calls[0].name); | ||
1661 | 381 | |||
1662 | 382 | unsigned int i; | ||
1663 | 383 | |||
1664 | 384 | bool got_mir = false; | ||
1665 | 385 | |||
1666 | 386 | GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); | ||
1667 | 387 | GVariantIter iter; | ||
1668 | 388 | g_variant_iter_init(&iter, envarray); | ||
1669 | 389 | gchar * envvar = NULL; | ||
1670 | 390 | |||
1671 | 391 | while (g_variant_iter_loop(&iter, "s", &envvar)) { | ||
1672 | 392 | gchar * var = g_strdup(envvar); | ||
1673 | 393 | |||
1674 | 394 | gchar * equal = g_strstr_len(var, -1, "="); | ||
1675 | 395 | ASSERT_NE(equal, nullptr); | ||
1676 | 396 | |||
1677 | 397 | equal[0] = '\0'; | ||
1678 | 398 | gchar * value = &(equal[1]); | ||
1679 | 399 | |||
1680 | 400 | if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) { | ||
1681 | 401 | EXPECT_STREQ("1", value); | ||
1682 | 402 | got_mir = true; | ||
1683 | 403 | } | ||
1684 | 404 | |||
1685 | 405 | g_free(var); | ||
1686 | 406 | } | ||
1687 | 407 | |||
1688 | 408 | g_variant_unref(envarray); | ||
1689 | 409 | |||
1690 | 410 | EXPECT_TRUE(got_mir); | ||
1691 | 411 | } | ||
1692 | 412 | |||
1693 | 413 | TEST_F(ExecUtil, ClickNoMir) | ||
1694 | 414 | { | ||
1695 | 415 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); | ||
1696 | 416 | |||
1697 | 417 | g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); | ||
1698 | 418 | g_setenv("TEST_CLICK_USER", "test-user", TRUE); | ||
1699 | 419 | g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE); | ||
1700 | 420 | |||
1701 | 421 | ASSERT_TRUE(ubuntu_app_launch_start_application("com.test.mir_nomir_1", NULL)); | ||
1702 | 422 | |||
1703 | 423 | guint len = 0; | ||
1704 | 424 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); | ||
1705 | 425 | |||
1706 | 426 | ASSERT_EQ(1, len); | ||
1707 | 427 | ASSERT_NE(nullptr, calls); | ||
1708 | 428 | ASSERT_STREQ("Start", calls[0].name); | ||
1709 | 429 | |||
1710 | 430 | unsigned int i; | ||
1711 | 431 | |||
1712 | 432 | bool got_mir = false; | ||
1713 | 433 | |||
1714 | 434 | GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); | ||
1715 | 435 | GVariantIter iter; | ||
1716 | 436 | g_variant_iter_init(&iter, envarray); | ||
1717 | 437 | gchar * envvar = NULL; | ||
1718 | 438 | |||
1719 | 439 | while (g_variant_iter_loop(&iter, "s", &envvar)) { | ||
1720 | 440 | gchar * var = g_strdup(envvar); | ||
1721 | 441 | |||
1722 | 442 | gchar * equal = g_strstr_len(var, -1, "="); | ||
1723 | 443 | ASSERT_NE(equal, nullptr); | ||
1724 | 444 | |||
1725 | 445 | equal[0] = '\0'; | ||
1726 | 446 | gchar * value = &(equal[1]); | ||
1727 | 447 | |||
1728 | 448 | if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) { | ||
1729 | 449 | EXPECT_STREQ("0", value); | ||
1730 | 450 | got_mir = true; | ||
1731 | 451 | } | ||
1732 | 452 | |||
1733 | 453 | g_free(var); | ||
1734 | 454 | } | ||
1735 | 455 | |||
1736 | 456 | g_variant_unref(envarray); | ||
1737 | 457 | |||
1738 | 458 | EXPECT_TRUE(got_mir); | ||
1739 | 459 | } | ||
1740 | 460 | |||
1741 | 461 | TEST_F(ExecUtil, LibertineExec) | ||
1742 | 462 | { | ||
1743 | 463 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); | ||
1744 | 464 | |||
1745 | 465 | ASSERT_TRUE(ubuntu_app_launch_start_application("container-name_test_0.0", NULL)); | ||
1746 | 466 | |||
1747 | 467 | guint len = 0; | ||
1748 | 468 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); | ||
1749 | 469 | |||
1750 | 470 | ASSERT_EQ(1, len); | ||
1751 | 471 | ASSERT_NE(nullptr, calls); | ||
1752 | 472 | ASSERT_STREQ("Start", calls[0].name); | ||
1753 | 473 | |||
1754 | 474 | unsigned int i; | ||
1755 | 475 | |||
1756 | 476 | bool got_app_exec = false; | ||
1757 | 477 | bool got_app_exec_policy = false; | ||
1758 | 478 | bool got_app_id = false; | ||
1759 | 479 | bool got_app_pid = false; | ||
1760 | 480 | bool got_instance_id = false; | ||
1761 | 481 | bool got_mir = false; | ||
1762 | 482 | |||
1763 | 483 | GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); | ||
1764 | 484 | GVariantIter iter; | ||
1765 | 485 | g_variant_iter_init(&iter, envarray); | ||
1766 | 486 | gchar * envvar = NULL; | ||
1767 | 487 | |||
1768 | 488 | while (g_variant_iter_loop(&iter, "s", &envvar)) { | ||
1769 | 489 | gchar * var = g_strdup(envvar); | ||
1770 | 490 | |||
1771 | 491 | gchar * equal = g_strstr_len(var, -1, "="); | ||
1772 | 492 | ASSERT_NE(equal, nullptr); | ||
1773 | 493 | |||
1774 | 494 | equal[0] = '\0'; | ||
1775 | 495 | gchar * value = &(equal[1]); | ||
1776 | 496 | |||
1777 | 497 | if (g_strcmp0(var, "APP_EXEC") == 0) { | ||
1778 | 498 | EXPECT_STREQ("libertine-launch \"container-name\" test", value); | ||
1779 | 499 | got_app_exec = true; | ||
1780 | 500 | } else if (g_strcmp0(var, "APP_EXEC_POLICY") == 0) { | ||
1781 | 501 | EXPECT_STREQ("unconfined", value); | ||
1782 | 502 | got_app_exec_policy = true; | ||
1783 | 503 | } else if (g_strcmp0(var, "APP_ID") == 0) { | ||
1784 | 504 | EXPECT_STREQ("container-name_test_0.0", value); | ||
1785 | 505 | got_app_id = true; | ||
1786 | 506 | } else if (g_strcmp0(var, "APP_LAUNCHER_PID") == 0) { | ||
1787 | 507 | EXPECT_EQ(getpid(), atoi(value)); | ||
1788 | 508 | got_app_pid = true; | ||
1789 | 509 | } else if (g_strcmp0(var, "INSTANCE_ID") == 0) { | ||
1790 | 510 | got_instance_id = true; | ||
1791 | 511 | } else if (g_strcmp0(var, "APP_XMIR_ENABLE") == 0) { | ||
1792 | 512 | EXPECT_STREQ("1", value); | ||
1793 | 513 | got_mir = true; | ||
1794 | 514 | } else { | ||
1795 | 515 | g_warning("Unknown variable! %s", var); | ||
1796 | 516 | EXPECT_TRUE(false); | ||
1797 | 517 | } | ||
1798 | 518 | |||
1799 | 519 | g_free(var); | ||
1800 | 520 | } | ||
1801 | 521 | |||
1802 | 522 | g_variant_unref(envarray); | ||
1803 | 523 | |||
1804 | 524 | EXPECT_TRUE(got_app_exec); | ||
1805 | 525 | EXPECT_TRUE(got_app_exec_policy); | ||
1806 | 526 | EXPECT_TRUE(got_app_id); | ||
1807 | 527 | EXPECT_TRUE(got_app_pid); | ||
1808 | 528 | EXPECT_TRUE(got_instance_id); | ||
1809 | 529 | EXPECT_TRUE(got_mir); | ||
1810 | 530 | } | ||
1811 | 274 | 531 | ||
1812 | === added directory 'tests/libertine-data' | |||
1813 | === added directory 'tests/libertine-data/libertine-container' | |||
1814 | === added directory 'tests/libertine-data/libertine-container/container-name' | |||
1815 | === added directory 'tests/libertine-data/libertine-container/container-name/usr' | |||
1816 | === added directory 'tests/libertine-data/libertine-container/container-name/usr/share' | |||
1817 | === added directory 'tests/libertine-data/libertine-container/container-name/usr/share/applications' | |||
1818 | === added file 'tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop' | |||
1819 | --- tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop 1970-01-01 00:00:00 +0000 | |||
1820 | +++ tests/libertine-data/libertine-container/container-name/usr/share/applications/test.desktop 2015-08-07 02:13:47 +0000 | |||
1821 | @@ -0,0 +1,4 @@ | |||
1822 | 1 | [Desktop Entry] | ||
1823 | 2 | Name=Test | ||
1824 | 3 | Type=Application | ||
1825 | 4 | Exec=test | ||
1826 | 0 | 5 | ||
1827 | === modified file 'tests/libual-test.cc' | |||
1828 | --- tests/libual-test.cc 2015-03-02 19:59:44 +0000 | |||
1829 | +++ tests/libual-test.cc 2015-08-07 02:13:47 +0000 | |||
1830 | @@ -17,13 +17,18 @@ | |||
1831 | 17 | * Ted Gould <ted.gould@canonical.com> | 17 | * Ted Gould <ted.gould@canonical.com> |
1832 | 18 | */ | 18 | */ |
1833 | 19 | 19 | ||
1834 | 20 | #include <future> | ||
1835 | 21 | #include <thread> | ||
1836 | 22 | |||
1837 | 20 | #include <gtest/gtest.h> | 23 | #include <gtest/gtest.h> |
1838 | 21 | #include <gio/gio.h> | 24 | #include <gio/gio.h> |
1839 | 22 | #include <zeitgeist.h> | 25 | #include <zeitgeist.h> |
1840 | 26 | #include "mir-mock.h" | ||
1841 | 23 | 27 | ||
1842 | 24 | extern "C" { | 28 | extern "C" { |
1843 | 25 | #include "ubuntu-app-launch.h" | 29 | #include "ubuntu-app-launch.h" |
1844 | 26 | #include "libdbustest/dbus-test.h" | 30 | #include "libdbustest/dbus-test.h" |
1845 | 31 | #include <fcntl.h> | ||
1846 | 27 | } | 32 | } |
1847 | 28 | 33 | ||
1848 | 29 | class LibUAL : public ::testing::Test | 34 | class LibUAL : public ::testing::Test |
1849 | @@ -108,6 +113,13 @@ | |||
1850 | 108 | " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", | 113 | " ret = dbus.ObjectPath('/com/test/untrusted/helper')\n", |
1851 | 109 | NULL); | 114 | NULL); |
1852 | 110 | 115 | ||
1853 | 116 | dbus_test_dbus_mock_object_add_method(mock, obj, | ||
1854 | 117 | "SetEnv", | ||
1855 | 118 | G_VARIANT_TYPE("(assb)"), | ||
1856 | 119 | NULL, | ||
1857 | 120 | "", | ||
1858 | 121 | NULL); | ||
1859 | 122 | |||
1860 | 111 | /* Click App */ | 123 | /* Click App */ |
1861 | 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); |
1862 | 113 | 125 | ||
1863 | @@ -266,50 +278,64 @@ | |||
1864 | 266 | } | 278 | } |
1865 | 267 | ASSERT_EQ(nullptr, bus); | 279 | ASSERT_EQ(nullptr, bus); |
1866 | 268 | } | 280 | } |
1871 | 269 | 281 | ||
1872 | 270 | bool check_env (GVariant * env_array, const gchar * var, const gchar * value) { | 282 | GVariant * find_env (GVariant * env_array, const gchar * var) { |
1873 | 271 | GVariantIter iter; | 283 | int i; |
1870 | 272 | g_variant_iter_init(&iter, env_array); | ||
1874 | 273 | gchar * envvar = NULL; | 284 | gchar * envvar = NULL; |
1878 | 274 | bool found = false; | 285 | GVariant * retval = nullptr; |
1879 | 275 | 286 | ||
1880 | 276 | while (g_variant_iter_loop(&iter, "s", &envvar)) { | 287 | for (i = 0; i < g_variant_n_children(env_array); i++) { |
1881 | 288 | GVariant * child = g_variant_get_child_value(env_array, i); | ||
1882 | 289 | const gchar * envvar = g_variant_get_string(child, nullptr); | ||
1883 | 290 | |||
1884 | 277 | if (g_str_has_prefix(envvar, var)) { | 291 | if (g_str_has_prefix(envvar, var)) { |
1886 | 278 | if (found) { | 292 | if (retval != nullptr) { |
1887 | 279 | g_warning("Found the env var more than once!"); | 293 | g_warning("Found the env var more than once!"); |
1889 | 280 | return false; | 294 | g_variant_unref(retval); |
1890 | 295 | return nullptr; | ||
1891 | 281 | } | 296 | } |
1892 | 282 | 297 | ||
1902 | 283 | if (value != NULL) { | 298 | retval = child; |
1903 | 284 | gchar * combined = g_strdup_printf("%s=%s", var, value); | 299 | } else { |
1904 | 285 | if (g_strcmp0(envvar, combined) == 0) { | 300 | g_variant_unref(child); |
1896 | 286 | found = true; | ||
1897 | 287 | } | ||
1898 | 288 | g_free(combined); | ||
1899 | 289 | } else { | ||
1900 | 290 | found = true; | ||
1901 | 291 | } | ||
1905 | 292 | } | 301 | } |
1906 | 293 | } | 302 | } |
1907 | 294 | 303 | ||
1909 | 295 | if (!found) { | 304 | if (!retval) { |
1910 | 296 | gchar * envstr = g_variant_print(env_array, FALSE); | 305 | gchar * envstr = g_variant_print(env_array, FALSE); |
1912 | 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); |
1913 | 298 | g_free(envstr); | 307 | g_free(envstr); |
1914 | 299 | } | 308 | } |
1915 | 300 | 309 | ||
1916 | 310 | return retval; | ||
1917 | 311 | } | ||
1918 | 312 | |||
1919 | 313 | bool check_env (GVariant * env_array, const gchar * var, const gchar * value) { | ||
1920 | 314 | bool found = false; | ||
1921 | 315 | GVariant * val = find_env(env_array, var); | ||
1922 | 316 | if (val == nullptr) | ||
1923 | 317 | return false; | ||
1924 | 318 | |||
1925 | 319 | const gchar * envvar = g_variant_get_string(val, nullptr); | ||
1926 | 320 | |||
1927 | 321 | gchar * combined = g_strdup_printf("%s=%s", var, value); | ||
1928 | 322 | if (g_strcmp0(envvar, combined) == 0) { | ||
1929 | 323 | found = true; | ||
1930 | 324 | } | ||
1931 | 325 | |||
1932 | 326 | g_variant_unref(val); | ||
1933 | 327 | |||
1934 | 301 | return found; | 328 | return found; |
1935 | 302 | } | 329 | } |
1936 | 303 | 330 | ||
1943 | 304 | static gboolean pause_helper (gpointer pmainloop) { | 331 | void pause (guint time = 0) { |
1938 | 305 | g_main_loop_quit(static_cast<GMainLoop *>(pmainloop)); | ||
1939 | 306 | return G_SOURCE_REMOVE; | ||
1940 | 307 | } | ||
1941 | 308 | |||
1942 | 309 | void pause (guint time) { | ||
1944 | 310 | if (time > 0) { | 332 | if (time > 0) { |
1945 | 311 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); | 333 | GMainLoop * mainloop = g_main_loop_new(NULL, FALSE); |
1947 | 312 | g_timeout_add(time, pause_helper, mainloop); | 334 | |
1948 | 335 | g_timeout_add(time, [](gpointer pmainloop) -> gboolean { | ||
1949 | 336 | g_main_loop_quit(static_cast<GMainLoop *>(pmainloop)); | ||
1950 | 337 | return G_SOURCE_REMOVE; | ||
1951 | 338 | }, mainloop); | ||
1952 | 313 | 339 | ||
1953 | 314 | g_main_loop_run(mainloop); | 340 | g_main_loop_run(mainloop); |
1954 | 315 | 341 | ||
1955 | @@ -1446,3 +1472,147 @@ | |||
1956 | 1446 | 1472 | ||
1957 | 1447 | g_free(oomadjfile); | 1473 | g_free(oomadjfile); |
1958 | 1448 | } | 1474 | } |
1959 | 1475 | |||
1960 | 1476 | TEST_F(LibUAL, StartSessionHelper) | ||
1961 | 1477 | { | ||
1962 | 1478 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/untrusted/helper", "com.ubuntu.Upstart0_6.Job", NULL); | ||
1963 | 1479 | MirConnection * conn = mir_connect_sync("libual-test", "start-session-helper"); // Mocked, doesn't need cleaning up | ||
1964 | 1480 | MirPromptSession * msession = mir_connection_create_prompt_session_sync(conn, 5, nullptr, nullptr); | ||
1965 | 1481 | |||
1966 | 1482 | /* Building a temporary file and making an FD for it */ | ||
1967 | 1483 | const char * filedata = "This is some data that we should get on the other side\n"; | ||
1968 | 1484 | ASSERT_TRUE(g_file_set_contents(SESSION_TEMP_FILE, filedata, strlen(filedata), nullptr) == TRUE); | ||
1969 | 1485 | int mirfd = open(SESSION_TEMP_FILE, 0); | ||
1970 | 1486 | mir_mock_set_trusted_fd(mirfd); | ||
1971 | 1487 | |||
1972 | 1488 | /* Basic make sure we can send the event */ | ||
1973 | 1489 | gchar * instance_id = ubuntu_app_launch_start_session_helper("untrusted-type", msession, "com.test.multiple_first_1.2.3", NULL); | ||
1974 | 1490 | ASSERT_NE(nullptr, instance_id); | ||
1975 | 1491 | |||
1976 | 1492 | guint len = 0; | ||
1977 | 1493 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); | ||
1978 | 1494 | EXPECT_NE(nullptr, calls); | ||
1979 | 1495 | EXPECT_EQ(1, len); | ||
1980 | 1496 | |||
1981 | 1497 | EXPECT_STREQ("Start", calls->name); | ||
1982 | 1498 | EXPECT_EQ(2, g_variant_n_children(calls->params)); | ||
1983 | 1499 | |||
1984 | 1500 | GVariant * block = g_variant_get_child_value(calls->params, 1); | ||
1985 | 1501 | EXPECT_TRUE(g_variant_get_boolean(block)); | ||
1986 | 1502 | g_variant_unref(block); | ||
1987 | 1503 | |||
1988 | 1504 | /* Check the environment */ | ||
1989 | 1505 | GVariant * env = g_variant_get_child_value(calls->params, 0); | ||
1990 | 1506 | EXPECT_TRUE(check_env(env, "APP_ID", "com.test.multiple_first_1.2.3")); | ||
1991 | 1507 | EXPECT_TRUE(check_env(env, "HELPER_TYPE", "untrusted-type")); | ||
1992 | 1508 | EXPECT_TRUE(check_env(env, "INSTANCE_ID", instance_id)); | ||
1993 | 1509 | |||
1994 | 1510 | GVariant * mnamev = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_NAME"); | ||
1995 | 1511 | ASSERT_NE(nullptr, mnamev); /* Have to assert because, eh, GVariant */ | ||
1996 | 1512 | EXPECT_STREQ(g_dbus_connection_get_unique_name(bus), g_variant_get_string(mnamev, nullptr) + strlen("UBUNTU_APP_LAUNCH_DEMANGLE_NAME=")); | ||
1997 | 1513 | GVariant * mpathv = find_env(env, "UBUNTU_APP_LAUNCH_DEMANGLE_PATH"); | ||
1998 | 1514 | ASSERT_NE(nullptr, mpathv); /* Have to assert because, eh, GVariant */ | ||
1999 | 1515 | |||
2000 | 1516 | g_variant_unref(env); | ||
2001 | 1517 | |||
2002 | 1518 | /* Setup environment for call */ | ||
2003 | 1519 | const gchar * mname = g_variant_get_string(mnamev, nullptr); | ||
2004 | 1520 | mname += strlen("UBUNTU_APP_LAUNCH_DEMANGLE_NAME="); | ||
2005 | 1521 | g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", mname, TRUE); | ||
2006 | 1522 | g_variant_unref(mnamev); | ||
2007 | 1523 | |||
2008 | 1524 | const gchar * mpath = g_variant_get_string(mpathv, nullptr); | ||
2009 | 1525 | mpath += strlen("UBUNTU_APP_LAUNCH_DEMANGLE_PATH="); | ||
2010 | 1526 | g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_PATH", mpath, TRUE); | ||
2011 | 1527 | g_variant_unref(mpathv); | ||
2012 | 1528 | |||
2013 | 1529 | /* Exec our tool */ | ||
2014 | 1530 | std::promise<std::string> outputpromise; | ||
2015 | 1531 | std::thread t([&outputpromise]() { | ||
2016 | 1532 | gchar * socketstdout = nullptr; | ||
2017 | 1533 | GError * error = nullptr; | ||
2018 | 1534 | g_unsetenv("G_MESSAGES_DEBUG"); | ||
2019 | 1535 | |||
2020 | 1536 | g_spawn_command_line_sync( | ||
2021 | 1537 | SOCKET_DEMANGLER " " SOCKET_TOOL, | ||
2022 | 1538 | &socketstdout, | ||
2023 | 1539 | nullptr, | ||
2024 | 1540 | nullptr, | ||
2025 | 1541 | &error); | ||
2026 | 1542 | |||
2027 | 1543 | if (error != nullptr) { | ||
2028 | 1544 | fprintf(stderr, "Unable to spawn '" SOCKET_DEMANGLER " " SOCKET_TOOL "': %s\n", error->message); | ||
2029 | 1545 | g_error_free(error); | ||
2030 | 1546 | outputpromise.set_value(std::string("")); | ||
2031 | 1547 | } else { | ||
2032 | 1548 | outputpromise.set_value(std::string(socketstdout)); | ||
2033 | 1549 | g_free(socketstdout); | ||
2034 | 1550 | } | ||
2035 | 1551 | }); | ||
2036 | 1552 | t.detach(); | ||
2037 | 1553 | |||
2038 | 1554 | auto outputfuture = outputpromise.get_future(); | ||
2039 | 1555 | while (outputfuture.wait_for(std::chrono::milliseconds{1}) != std::future_status::ready) { | ||
2040 | 1556 | pause(); | ||
2041 | 1557 | } | ||
2042 | 1558 | |||
2043 | 1559 | ASSERT_STREQ(filedata, outputfuture.get().c_str()); | ||
2044 | 1560 | |||
2045 | 1561 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); | ||
2046 | 1562 | |||
2047 | 1563 | return; | ||
2048 | 1564 | } | ||
2049 | 1565 | |||
2050 | 1566 | TEST_F(LibUAL, SetExec) | ||
2051 | 1567 | { | ||
2052 | 1568 | DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/ubuntu/Upstart", "com.ubuntu.Upstart0_6", NULL); | ||
2053 | 1569 | |||
2054 | 1570 | const char * exec = "lets exec this"; | ||
2055 | 1571 | |||
2056 | 1572 | g_setenv("UPSTART_JOB", "fubar", TRUE); | ||
2057 | 1573 | g_unsetenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME"); | ||
2058 | 1574 | EXPECT_TRUE(ubuntu_app_launch_helper_set_exec(exec, NULL)); | ||
2059 | 1575 | |||
2060 | 1576 | guint len = 0; | ||
2061 | 1577 | const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL); | ||
2062 | 1578 | ASSERT_NE(nullptr, calls); | ||
2063 | 1579 | EXPECT_EQ(1, len); | ||
2064 | 1580 | |||
2065 | 1581 | gchar * appexecstr = g_strdup_printf("APP_EXEC=%s", exec); | ||
2066 | 1582 | GVariant * appexecenv = g_variant_get_child_value(calls[0].params, 1); | ||
2067 | 1583 | EXPECT_STREQ(appexecstr, g_variant_get_string(appexecenv, nullptr)); | ||
2068 | 1584 | g_variant_unref(appexecenv); | ||
2069 | 1585 | g_free(appexecstr); | ||
2070 | 1586 | |||
2071 | 1587 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); | ||
2072 | 1588 | |||
2073 | 1589 | /* Now check for the demangler */ | ||
2074 | 1590 | g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", g_dbus_connection_get_unique_name(bus), TRUE); | ||
2075 | 1591 | EXPECT_TRUE(ubuntu_app_launch_helper_set_exec(exec, NULL)); | ||
2076 | 1592 | |||
2077 | 1593 | calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL); | ||
2078 | 1594 | ASSERT_NE(nullptr, calls); | ||
2079 | 1595 | EXPECT_EQ(1, len); | ||
2080 | 1596 | |||
2081 | 1597 | gchar * demangleexecstr = g_strdup_printf("APP_EXEC=%s %s", SOCKET_DEMANGLER_INSTALL, exec); | ||
2082 | 1598 | appexecenv = g_variant_get_child_value(calls[0].params, 1); | ||
2083 | 1599 | EXPECT_STREQ(demangleexecstr, g_variant_get_string(appexecenv, nullptr)); | ||
2084 | 1600 | g_variant_unref(appexecenv); | ||
2085 | 1601 | g_free(demangleexecstr); | ||
2086 | 1602 | |||
2087 | 1603 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); | ||
2088 | 1604 | |||
2089 | 1605 | /* Now check for the directory */ | ||
2090 | 1606 | g_setenv("UBUNTU_APP_LAUNCH_DEMANGLE_NAME", g_dbus_connection_get_unique_name(bus), TRUE); | ||
2091 | 1607 | EXPECT_TRUE(ubuntu_app_launch_helper_set_exec(exec, "/not/a/real/directory")); | ||
2092 | 1608 | |||
2093 | 1609 | calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "SetEnv", &len, NULL); | ||
2094 | 1610 | ASSERT_NE(nullptr, calls); | ||
2095 | 1611 | EXPECT_EQ(2, len); | ||
2096 | 1612 | |||
2097 | 1613 | appexecenv = g_variant_get_child_value(calls[1].params, 1); | ||
2098 | 1614 | EXPECT_STREQ("APP_DIR=/not/a/real/directory", g_variant_get_string(appexecenv, nullptr)); | ||
2099 | 1615 | g_variant_unref(appexecenv); | ||
2100 | 1616 | |||
2101 | 1617 | ASSERT_TRUE(dbus_test_dbus_mock_object_clear_method_calls(mock, obj, NULL)); | ||
2102 | 1618 | } | ||
2103 | 1449 | 1619 | ||
2104 | === added file 'tests/link-farm/com.test.mir_mir_1.desktop' | |||
2105 | --- tests/link-farm/com.test.mir_mir_1.desktop 1970-01-01 00:00:00 +0000 | |||
2106 | +++ tests/link-farm/com.test.mir_mir_1.desktop 2015-08-07 02:13:47 +0000 | |||
2107 | @@ -0,0 +1,1 @@ | |||
2108 | 1 | Needs to exist | ||
2109 | 0 | 2 | ||
2110 | === added file 'tests/link-farm/com.test.mir_nomir_1.desktop' | |||
2111 | --- tests/link-farm/com.test.mir_nomir_1.desktop 1970-01-01 00:00:00 +0000 | |||
2112 | +++ tests/link-farm/com.test.mir_nomir_1.desktop 2015-08-07 02:13:47 +0000 | |||
2113 | @@ -0,0 +1,1 @@ | |||
2114 | 1 | Needs to exist | ||
2115 | 0 | 2 | ||
2116 | === added file 'tests/mir-mock.cpp' | |||
2117 | --- tests/mir-mock.cpp 1970-01-01 00:00:00 +0000 | |||
2118 | +++ tests/mir-mock.cpp 2015-08-07 02:13:47 +0000 | |||
2119 | @@ -0,0 +1,106 @@ | |||
2120 | 1 | |||
2121 | 2 | #include "mir-mock.h" | ||
2122 | 3 | |||
2123 | 4 | #include <iostream> | ||
2124 | 5 | #include <thread> | ||
2125 | 6 | |||
2126 | 7 | #include <mir_toolkit/mir_connection.h> | ||
2127 | 8 | #include <mir_toolkit/mir_prompt_session.h> | ||
2128 | 9 | |||
2129 | 10 | static const char * valid_trust_session = "In the circle of trust"; | ||
2130 | 11 | static bool valid_trust_connection = true; | ||
2131 | 12 | static pid_t last_trust_pid = 0; | ||
2132 | 13 | static int trusted_fd = 1234; | ||
2133 | 14 | |||
2134 | 15 | MirPromptSession * | ||
2135 | 16 | mir_connection_create_prompt_session_sync(MirConnection * connection, pid_t pid, void (*)(MirPromptSession *, MirPromptSessionState, void*data), void * context) { | ||
2136 | 17 | last_trust_pid = pid; | ||
2137 | 18 | |||
2138 | 19 | if (valid_trust_connection) { | ||
2139 | 20 | return (MirPromptSession *)valid_trust_session; | ||
2140 | 21 | } else { | ||
2141 | 22 | return nullptr; | ||
2142 | 23 | } | ||
2143 | 24 | } | ||
2144 | 25 | |||
2145 | 26 | void | ||
2146 | 27 | mir_prompt_session_release_sync (MirPromptSession * session) | ||
2147 | 28 | { | ||
2148 | 29 | if (reinterpret_cast<char *>(session) != valid_trust_session) { | ||
2149 | 30 | std::cerr << "Releasing a Mir Trusted Prompt that isn't valid" << std::endl; | ||
2150 | 31 | exit(1); | ||
2151 | 32 | } | ||
2152 | 33 | } | ||
2153 | 34 | |||
2154 | 35 | MirWaitHandle * | ||
2155 | 36 | mir_prompt_session_new_fds_for_prompt_providers (MirPromptSession * session, unsigned int numfds, mir_client_fd_callback cb, void * data) { | ||
2156 | 37 | if (reinterpret_cast<char *>(session) != valid_trust_session) { | ||
2157 | 38 | std::cerr << "Releasing a Mir Trusted Prompt that isn't valid" << std::endl; | ||
2158 | 39 | exit(1); | ||
2159 | 40 | } | ||
2160 | 41 | |||
2161 | 42 | /* TODO: Put in another thread to be more mir like */ | ||
2162 | 43 | std::thread * thread = new std::thread([session, numfds, cb, data]() { | ||
2163 | 44 | int fdlist[numfds]; | ||
2164 | 45 | |||
2165 | 46 | for (int i = 0; i < numfds; i++) | ||
2166 | 47 | fdlist[i] = trusted_fd; | ||
2167 | 48 | |||
2168 | 49 | cb(session, numfds, fdlist, data); | ||
2169 | 50 | }); | ||
2170 | 51 | |||
2171 | 52 | return reinterpret_cast<MirWaitHandle *>(thread); | ||
2172 | 53 | } | ||
2173 | 54 | |||
2174 | 55 | void | ||
2175 | 56 | mir_wait_for (MirWaitHandle * wait) | ||
2176 | 57 | { | ||
2177 | 58 | auto thread = reinterpret_cast<std::thread *>(wait); | ||
2178 | 59 | |||
2179 | 60 | if (thread->joinable()) | ||
2180 | 61 | thread->join(); | ||
2181 | 62 | |||
2182 | 63 | delete thread; | ||
2183 | 64 | } | ||
2184 | 65 | |||
2185 | 66 | static const char * valid_connection_str = "Valid Mir Connection"; | ||
2186 | 67 | static std::pair<std::string, std::string> last_connection; | ||
2187 | 68 | static bool valid_connection = true; | ||
2188 | 69 | |||
2189 | 70 | void | ||
2190 | 71 | mir_mock_connect_return_valid (bool valid) | ||
2191 | 72 | { | ||
2192 | 73 | valid_connection = valid; | ||
2193 | 74 | } | ||
2194 | 75 | |||
2195 | 76 | std::pair<std::string, std::string> | ||
2196 | 77 | mir_mock_connect_last_connect (void) | ||
2197 | 78 | { | ||
2198 | 79 | return last_connection; | ||
2199 | 80 | } | ||
2200 | 81 | |||
2201 | 82 | MirConnection * | ||
2202 | 83 | mir_connect_sync (char const * server, char const * appname) | ||
2203 | 84 | { | ||
2204 | 85 | last_connection = std::pair<std::string, std::string>(server, appname); | ||
2205 | 86 | |||
2206 | 87 | if (valid_connection) { | ||
2207 | 88 | return (MirConnection *)(valid_connection_str); | ||
2208 | 89 | } else { | ||
2209 | 90 | return nullptr; | ||
2210 | 91 | } | ||
2211 | 92 | } | ||
2212 | 93 | |||
2213 | 94 | void | ||
2214 | 95 | mir_connection_release (MirConnection * con) | ||
2215 | 96 | { | ||
2216 | 97 | if (reinterpret_cast<char *>(con) != valid_connection_str) { | ||
2217 | 98 | std::cerr << "Releasing a Mir Connection that isn't valid" << std::endl; | ||
2218 | 99 | exit(1); | ||
2219 | 100 | } | ||
2220 | 101 | } | ||
2221 | 102 | |||
2222 | 103 | void mir_mock_set_trusted_fd (int fd) | ||
2223 | 104 | { | ||
2224 | 105 | trusted_fd = fd; | ||
2225 | 106 | } | ||
2226 | 0 | 107 | ||
2227 | === added file 'tests/mir-mock.h' | |||
2228 | --- tests/mir-mock.h 1970-01-01 00:00:00 +0000 | |||
2229 | +++ tests/mir-mock.h 2015-08-07 02:13:47 +0000 | |||
2230 | @@ -0,0 +1,12 @@ | |||
2231 | 1 | |||
2232 | 2 | #ifndef MIR_MOCK_H | ||
2233 | 3 | #define MIR_MOCK_H 1 | ||
2234 | 4 | |||
2235 | 5 | #include <string> | ||
2236 | 6 | #include <utility> | ||
2237 | 7 | |||
2238 | 8 | void mir_mock_connect_return_valid (bool valid); | ||
2239 | 9 | std::pair<std::string, std::string> mir_mock_connect_last_connect (void); | ||
2240 | 10 | void mir_mock_set_trusted_fd (int fd); | ||
2241 | 11 | |||
2242 | 12 | #endif // MIR_MOCK_H | ||
2243 | 0 | 13 | ||
2244 | === added file 'tests/socket-tool.c' | |||
2245 | --- tests/socket-tool.c 1970-01-01 00:00:00 +0000 | |||
2246 | +++ tests/socket-tool.c 2015-08-07 02:13:47 +0000 | |||
2247 | @@ -0,0 +1,28 @@ | |||
2248 | 1 | |||
2249 | 2 | #include <stdlib.h> | ||
2250 | 3 | #include <stdio.h> | ||
2251 | 4 | #include <unistd.h> | ||
2252 | 5 | |||
2253 | 6 | int | ||
2254 | 7 | main (int argc, char * argv[]) | ||
2255 | 8 | { | ||
2256 | 9 | const char * fdstr = getenv("MIR_SOCKET"); | ||
2257 | 10 | if (!fdstr) { | ||
2258 | 11 | fprintf(stderr, "No MIR_SOCKET defined\n"); | ||
2259 | 12 | return 1; | ||
2260 | 13 | } | ||
2261 | 14 | |||
2262 | 15 | int fdnum = 0; | ||
2263 | 16 | sscanf(fdstr, "fd://%d", &fdnum); | ||
2264 | 17 | if (fdnum == 0) { | ||
2265 | 18 | fprintf(stderr, "Unable to get FD number\n"); | ||
2266 | 19 | return 1; | ||
2267 | 20 | } | ||
2268 | 21 | |||
2269 | 22 | char inchar; | ||
2270 | 23 | while (read(fdnum, &inchar, 1) == 1) | ||
2271 | 24 | fwrite(&inchar, 1, 1, stdout); | ||
2272 | 25 | |||
2273 | 26 | close(fdnum); | ||
2274 | 27 | return 0; | ||
2275 | 28 | } | ||
2276 | 0 | 29 | ||
2277 | === added file 'tests/xmir-helper-exec.sh' | |||
2278 | --- tests/xmir-helper-exec.sh 1970-01-01 00:00:00 +0000 | |||
2279 | +++ tests/xmir-helper-exec.sh 2015-08-07 02:13:47 +0000 | |||
2280 | @@ -0,0 +1,3 @@ | |||
2281 | 1 | #!/bin/bash | ||
2282 | 2 | |||
2283 | 3 | echo $DISPLAY | ||
2284 | 0 | 4 | ||
2285 | === added file 'tests/xmir-helper-test.in' | |||
2286 | --- tests/xmir-helper-test.in 1970-01-01 00:00:00 +0000 | |||
2287 | +++ tests/xmir-helper-test.in 2015-08-07 02:13:47 +0000 | |||
2288 | @@ -0,0 +1,25 @@ | |||
2289 | 1 | #!/bin/bash | ||
2290 | 2 | |||
2291 | 3 | echo -n "Testing XMir Helper… " | ||
2292 | 4 | |||
2293 | 5 | export UBUNTU_APP_LAUNCH_XMIR_PATH="@CMAKE_CURRENT_SOURCE_DIR@/xmir-mock.sh" | ||
2294 | 6 | |||
2295 | 7 | TESTVALUE=`@CMAKE_BINARY_DIR@/xmir-helper com.mir.test_mirtest_1.2.3 @CMAKE_CURRENT_SOURCE_DIR@/xmir-helper-exec.sh` | ||
2296 | 8 | |||
2297 | 9 | if [ $TESTVALUE == ":42" ]; then | ||
2298 | 10 | echo "PASSED" | ||
2299 | 11 | else | ||
2300 | 12 | echo "FAILED" | ||
2301 | 13 | exit 1 | ||
2302 | 14 | fi | ||
2303 | 15 | |||
2304 | 16 | echo -n "Testing an evil XMir helper… " | ||
2305 | 17 | |||
2306 | 18 | export UBUNTU_APP_LAUNCH_XMIR_PATH="@CMAKE_CURRENT_SOURCE_DIR@/xmir-mock-evil.sh" | ||
2307 | 19 | |||
2308 | 20 | if @CMAKE_BINARY_DIR@/xmir-helper com.mir.test_mirtest_1.2.3 @CMAKE_CURRENT_SOURCE_DIR@/xmir-helper-exec.sh ; then | ||
2309 | 21 | echo "FAILED" | ||
2310 | 22 | exit 1 | ||
2311 | 23 | else | ||
2312 | 24 | echo "PASSED" | ||
2313 | 25 | fi | ||
2314 | 0 | 26 | ||
2315 | === added file 'tests/xmir-mock.sh' | |||
2316 | --- tests/xmir-mock.sh 1970-01-01 00:00:00 +0000 | |||
2317 | +++ tests/xmir-mock.sh 2015-08-07 02:13:47 +0000 | |||
2318 | @@ -0,0 +1,22 @@ | |||
2319 | 1 | #!/bin/bash | ||
2320 | 2 | |||
2321 | 3 | if [ $1 != "-displayfd" ]; then | ||
2322 | 4 | echo "-displayfd missing" | ||
2323 | 5 | exit 1 | ||
2324 | 6 | fi | ||
2325 | 7 | |||
2326 | 8 | if [ $3 != "-mir" ]; then | ||
2327 | 9 | echo "-mir missing" | ||
2328 | 10 | exit 1 | ||
2329 | 11 | fi | ||
2330 | 12 | |||
2331 | 13 | if [ $4 != "com.mir.test_mirtest_1.2.3" ]; then | ||
2332 | 14 | echo "AppID wrong" | ||
2333 | 15 | exit 1 | ||
2334 | 16 | fi | ||
2335 | 17 | |||
2336 | 18 | echo "42" >&$2 | ||
2337 | 19 | |||
2338 | 20 | # Ensure that our "XMir" runs longer than | ||
2339 | 21 | # the test, if it exits first that's a failure | ||
2340 | 22 | sleep 1 | ||
2341 | 0 | 23 | ||
2342 | === modified file 'ubuntu-app-test/CMakeLists.txt' | |||
2343 | --- ubuntu-app-test/CMakeLists.txt 2015-03-05 14:35:26 +0000 | |||
2344 | +++ ubuntu-app-test/CMakeLists.txt 2015-08-07 02:13:47 +0000 | |||
2345 | @@ -1,6 +1,4 @@ | |||
2346 | 1 | add_subdirectory(data) | 1 | add_subdirectory(data) |
2347 | 2 | |||
2348 | 3 | if (${MIR_FOUND}) | ||
2349 | 4 | add_subdirectory(src) | 2 | add_subdirectory(src) |
2350 | 5 | 3 | ||
2351 | 6 | # testing & coverage | 4 | # testing & coverage |
2352 | @@ -8,9 +6,3 @@ | |||
2353 | 8 | add_subdirectory(tests) | 6 | add_subdirectory(tests) |
2354 | 9 | endif () | 7 | endif () |
2355 | 10 | 8 | ||
2356 | 11 | else () | ||
2357 | 12 | |||
2358 | 13 | install(PROGRAMS ubuntu-app-test DESTINATION "${CMAKE_INSTALL_FULL_BINDIR}/app-test") | ||
2359 | 14 | |||
2360 | 15 | endif () | ||
2361 | 16 | |||
2362 | 17 | 9 | ||
2363 | === removed file 'ubuntu-app-test/ubuntu-app-test' | |||
2364 | --- ubuntu-app-test/ubuntu-app-test 2015-03-05 14:35:26 +0000 | |||
2365 | +++ ubuntu-app-test/ubuntu-app-test 1970-01-01 00:00:00 +0000 | |||
2366 | @@ -1,6 +0,0 @@ | |||
2367 | 1 | #!/bin/sh | ||
2368 | 2 | |||
2369 | 3 | # Used for Architectures that don't have Mir, otherwise we build the executable | ||
2370 | 4 | |||
2371 | 5 | echo "ubuntu-app-test doesn't work on this architecture, sorry" | ||
2372 | 6 | exit 1 | ||
2373 | 7 | 0 | ||
2374 | === modified file 'upstart-jobs/application-click.conf.in' | |||
2375 | --- upstart-jobs/application-click.conf.in 2015-01-23 18:12:29 +0000 | |||
2376 | +++ upstart-jobs/application-click.conf.in 2015-08-07 02:13:47 +0000 | |||
2377 | @@ -12,6 +12,9 @@ | |||
2378 | 12 | env APP_DIR | 12 | env APP_DIR |
2379 | 13 | env APP_DESKTOP_FILE_PATH | 13 | env APP_DESKTOP_FILE_PATH |
2380 | 14 | 14 | ||
2381 | 15 | env APP_XMIR_ENABLE=0 | ||
2382 | 16 | export APP_XMIR_ENABLE | ||
2383 | 17 | |||
2384 | 15 | env UBUNTU_APP_LAUNCH_ARCH="@ubuntu_app_launch_arch@" | 18 | env UBUNTU_APP_LAUNCH_ARCH="@ubuntu_app_launch_arch@" |
2385 | 16 | export UBUNTU_APP_LAUNCH_ARCH | 19 | export UBUNTU_APP_LAUNCH_ARCH |
2386 | 17 | 20 | ||
2387 | 18 | 21 | ||
2388 | === modified file 'upstart-jobs/application-legacy.conf.in' | |||
2389 | --- upstart-jobs/application-legacy.conf.in 2015-01-23 18:12:29 +0000 | |||
2390 | +++ upstart-jobs/application-legacy.conf.in 2015-08-07 02:13:47 +0000 | |||
2391 | @@ -12,6 +12,9 @@ | |||
2392 | 12 | env APP_URIS | 12 | env APP_URIS |
2393 | 13 | env APP_DESKTOP_FILE_PATH | 13 | env APP_DESKTOP_FILE_PATH |
2394 | 14 | 14 | ||
2395 | 15 | env APP_XMIR_ENABLE=1 | ||
2396 | 16 | export APP_XMIR_ENABLE | ||
2397 | 17 | |||
2398 | 15 | # This will be set to "unconfined" by desktop-exec if there is no confinement defined | 18 | # This will be set to "unconfined" by desktop-exec if there is no confinement defined |
2399 | 16 | apparmor switch $APP_EXEC_POLICY | 19 | apparmor switch $APP_EXEC_POLICY |
2400 | 17 | cgroup freezer | 20 | cgroup freezer |
2401 | 18 | 21 | ||
2402 | === added file 'xmir-helper.c' | |||
2403 | --- xmir-helper.c 1970-01-01 00:00:00 +0000 | |||
2404 | +++ xmir-helper.c 2015-08-07 02:13:47 +0000 | |||
2405 | @@ -0,0 +1,117 @@ | |||
2406 | 1 | /* | ||
2407 | 2 | * Copyright © 2014 Canonical Ltd. | ||
2408 | 3 | * | ||
2409 | 4 | * This program is free software: you can redistribute it and/or modify it | ||
2410 | 5 | * under the terms of the GNU General Public License version 3, as published | ||
2411 | 6 | * by the Free Software Foundation. | ||
2412 | 7 | * | ||
2413 | 8 | * This program is distributed in the hope that it will be useful, but | ||
2414 | 9 | * WITHOUT ANY WARRANTY; without even the implied warranties of | ||
2415 | 10 | * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR | ||
2416 | 11 | * PURPOSE. See the GNU General Public License for more details. | ||
2417 | 12 | * | ||
2418 | 13 | * You should have received a copy of the GNU General Public License along | ||
2419 | 14 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
2420 | 15 | * | ||
2421 | 16 | * Authors: | ||
2422 | 17 | * Ted Gould <ted.gould@canonical.com> | ||
2423 | 18 | */ | ||
2424 | 19 | |||
2425 | 20 | #define _POSIX_C_SOURCE 200212L | ||
2426 | 21 | |||
2427 | 22 | #include <unistd.h> | ||
2428 | 23 | #include <stdio.h> | ||
2429 | 24 | #include <stdlib.h> | ||
2430 | 25 | #include <sys/types.h> | ||
2431 | 26 | #include <sys/socket.h> | ||
2432 | 27 | #include <signal.h> | ||
2433 | 28 | |||
2434 | 29 | void | ||
2435 | 30 | sigchild_handler (int signal) | ||
2436 | 31 | { | ||
2437 | 32 | fprintf(stderr, "XMir has closed unexpectedly\n"); | ||
2438 | 33 | exit(1); | ||
2439 | 34 | } | ||
2440 | 35 | |||
2441 | 36 | struct sigaction sigchild_action = { | ||
2442 | 37 | .sa_handler = sigchild_handler, | ||
2443 | 38 | .sa_flags = SA_NOCLDWAIT | ||
2444 | 39 | }; | ||
2445 | 40 | |||
2446 | 41 | int | ||
2447 | 42 | main (int argc, char * argv[]) | ||
2448 | 43 | { | ||
2449 | 44 | if (argc < 3) { | ||
2450 | 45 | fprintf(stderr, "xmir-helper needs more arguments: xmir-helper $(appid) $(thing to exec)\n"); | ||
2451 | 46 | return 1; | ||
2452 | 47 | } | ||
2453 | 48 | |||
2454 | 49 | /* Make nice variables for the things we need */ | ||
2455 | 50 | char * appid = argv[1]; | ||
2456 | 51 | char * xmir = getenv("UBUNTU_APP_LAUNCH_XMIR_PATH"); | ||
2457 | 52 | if (xmir == NULL) { | ||
2458 | 53 | xmir = "/usr/bin/Xmir"; | ||
2459 | 54 | } | ||
2460 | 55 | |||
2461 | 56 | /* Build a socket pair to get the connection back from XMir */ | ||
2462 | 57 | int sockets[2]; | ||
2463 | 58 | if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) != 0) { | ||
2464 | 59 | fprintf(stderr, "Unable to create socketpair for communicating with XMir\n"); | ||
2465 | 60 | return 1; | ||
2466 | 61 | } | ||
2467 | 62 | |||
2468 | 63 | /* Give them nice names, the compiler will optimize out */ | ||
2469 | 64 | int xmirsocket = sockets[0]; | ||
2470 | 65 | int helpersocket = sockets[1]; | ||
2471 | 66 | |||
2472 | 67 | /* Watch for the child dying */ | ||
2473 | 68 | if (sigaction(SIGCHLD, &sigchild_action, NULL) != 0) { | ||
2474 | 69 | fprintf(stderr, "Unable to setup child signal handler\n"); | ||
2475 | 70 | return 1; | ||
2476 | 71 | } | ||
2477 | 72 | |||
2478 | 73 | /* Start XMir */ | ||
2479 | 74 | if (fork() == 0) { | ||
2480 | 75 | /* XMir start here */ | ||
2481 | 76 | /* GOAL: XMir -displayfd ${xmirsocket} -mir ${appid} */ | ||
2482 | 77 | char socketbuf[16] = {0}; | ||
2483 | 78 | snprintf(socketbuf, 16, "%d", xmirsocket); | ||
2484 | 79 | |||
2485 | 80 | char * xmirexec[6] = { | ||
2486 | 81 | xmir, | ||
2487 | 82 | "-displayfd", | ||
2488 | 83 | socketbuf, | ||
2489 | 84 | "-mir", | ||
2490 | 85 | appid, | ||
2491 | 86 | NULL | ||
2492 | 87 | }; | ||
2493 | 88 | |||
2494 | 89 | return execv(xmir, xmirexec); | ||
2495 | 90 | } | ||
2496 | 91 | |||
2497 | 92 | /* Wait to get the display number from XMir */ | ||
2498 | 93 | char readbuf[16] = {0}; | ||
2499 | 94 | if (read(helpersocket, readbuf, 16) == 0) { | ||
2500 | 95 | fprintf(stderr, "Not reading anything from XMir\n"); | ||
2501 | 96 | return 1; | ||
2502 | 97 | } | ||
2503 | 98 | |||
2504 | 99 | int i; | ||
2505 | 100 | for (i = 0; i < sizeof(readbuf); i++) { | ||
2506 | 101 | if (readbuf[i] == '\n') { | ||
2507 | 102 | readbuf[i] = '\0'; | ||
2508 | 103 | break; | ||
2509 | 104 | } | ||
2510 | 105 | } | ||
2511 | 106 | |||
2512 | 107 | char displaynumber[16] = {0}; | ||
2513 | 108 | snprintf(displaynumber, 16, ":%s", readbuf); | ||
2514 | 109 | |||
2515 | 110 | /* Set up the display variable */ | ||
2516 | 111 | setenv("DISPLAY", displaynumber, 1); | ||
2517 | 112 | |||
2518 | 113 | /* Now that we have everything setup, we can execute */ | ||
2519 | 114 | char ** nargv = &argv[2]; | ||
2520 | 115 | int execret = execvp(nargv[0], nargv); | ||
2521 | 116 | return execret; | ||
2522 | 117 | } | ||
2523 | 0 | 118 | ||
2524 | === modified file 'zg-report-app.c' | |||
2525 | --- zg-report-app.c 2014-09-10 14:54:01 +0000 | |||
2526 | +++ zg-report-app.c 2015-08-07 02:13:47 +0000 | |||
2527 | @@ -39,7 +39,7 @@ | |||
2528 | 39 | result = zeitgeist_log_insert_event_finish(ZEITGEIST_LOG(obj), res, &error); | 39 | result = zeitgeist_log_insert_event_finish(ZEITGEIST_LOG(obj), res, &error); |
2529 | 40 | 40 | ||
2530 | 41 | if (error != NULL) { | 41 | if (error != NULL) { |
2532 | 42 | g_error("Unable to submit Zeitgeist Event: %s", error->message); | 42 | g_warning("Unable to submit Zeitgeist Event: %s", error->message); |
2533 | 43 | g_error_free(error); | 43 | g_error_free(error); |
2534 | 44 | } | 44 | } |
2535 | 45 | 45 |