Merge lp:~ted/ubuntu-app-launch/xmir-support into lp:ubuntu-app-launch/15.10
- xmir-support
- Merge into trunk.15.10
Status: | Merged |
---|---|
Approved by: | Christopher Townsend |
Approved revision: | 140 |
Merged at revision: | 205 |
Proposed branch: | lp:~ted/ubuntu-app-launch/xmir-support |
Merge into: | lp:ubuntu-app-launch/15.10 |
Diff against target: |
795 lines (+445/-171) 20 files modified
CMakeLists.txt (+11/-1) exec-line-exec-trace.tp (+6/-0) exec-line-exec.c (+14/-0) libubuntu-app-launch/click-exec.c (+8/-0) libubuntu-app-launch/desktop-exec.c (+8/-0) tests/CMakeLists.txt (+6/-0) 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 (+178/-170) tests/link-farm/com.test.mir_mir_1.desktop (+1/-0) tests/link-farm/com.test.mir_nomir_1.desktop (+1/-0) tests/xmir-helper-exec.sh (+3/-0) tests/xmir-helper-test.in (+25/-0) tests/xmir-mock.sh (+22/-0) upstart-jobs/application-click.conf.in (+1/-0) upstart-jobs/application-legacy.conf.in (+1/-0) xmir-helper.c (+117/-0) |
To merge this branch: | bzr merge lp:~ted/ubuntu-app-launch/xmir-support |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Christopher Townsend | Approve | ||
Charles Kerr (community) | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+263529@code.launchpad.net |
This proposal supersedes a proposal from 2015-04-22.
Commit message
Start XMir for applications that enable it
Description of the change
PS Jenkins bot (ps-jenkins) wrote : | # |
Christopher Townsend (townsend) wrote : | # |
This was discussed on IRC, but I'll put it here as well for the record.
The crash seen in bug #1472097 is due to the '-rootless' option passed to Xmir. For a final solution, '-rootless' is desired, but short term, we need to figure out whether '-rootless' can be fixed in fairly quick manner or if it needs to be removed from this MP.
As this MP needs to land soon for PD, we need to figure out which option is best for the short term.
Aside from the '-rootless' issue, looks good and works well once I removed '-rootless' in my test.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:135
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Suggestions/
Ted Gould (ted) wrote : | # |
On Mon, 2015-08-10 at 19:12 +0000, Charles Kerr wrote:
> > +TEST_F(ExecUtil, DesktopNoMir)
>
> This is so similar to the previous test, seems like a good candidate for extract-method
Done, now this test takes forever to compile :-)
> > + if (argc < 3) {
> > + fprintf(stderr, "xmir-helper needs more arguments: xmir-helper $(appid) $(thing to exec)\n");
>
> might append "..." to make varargs explicit
Fixed. r139
> > + return 1;
> > + }
> > +
> > + /* Make nice variables for the things we need */
> > + char * appid = argv[1];
> > + char * xmir = getenv(
>
> appid and xmir should both be const
>
> also, g_getenv() returns a const gchar* so this should have warned -- do you have warnings turned off in the tests dir?
Verified that we're -Wall and -Werror. But we're using getenv() here so
it's not returning const. Which turns out to be a good thing where in
that exec() can't take a const array. Eh, stdlib :-(
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:140
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Charles Kerr (charlesk) wrote : | # |
Approved wrt the glib and testing; not reviewing Townsend's bits
Christopher Townsend (townsend) wrote : | # |
This works now.
Note: I did see a crash when starting an app, but I think it's due to something else, not this MP. Unfortunately, I cannot try to reproduce again as unity-system-
Preview Diff
1 | === modified file 'CMakeLists.txt' |
2 | --- CMakeLists.txt 2015-05-19 22:33:37 +0000 |
3 | +++ CMakeLists.txt 2015-08-17 21:35:03 +0000 |
4 | @@ -79,7 +79,9 @@ |
5 | |
6 | include_directories(${CMAKE_CURRENT_SOURCE_DIR}) |
7 | |
8 | -set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -fPIC") |
9 | +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") |
10 | + |
11 | +add_definitions( -DXMIR_HELPER="${pkglibexecdir}/xmir-helper" ) |
12 | |
13 | #################### |
14 | # Helpers |
15 | @@ -136,6 +138,14 @@ |
16 | install(TARGETS application-failed RUNTIME DESTINATION "${pkglibexecdir}") |
17 | |
18 | #################### |
19 | +# xmir-helper |
20 | +#################### |
21 | + |
22 | +add_executable(xmir-helper xmir-helper.c) |
23 | +set_target_properties(xmir-helper PROPERTIES OUTPUT_NAME "xmir-helper") |
24 | +install(TARGETS xmir-helper RUNTIME DESTINATION "${pkglibexecdir}") |
25 | + |
26 | +#################### |
27 | # untrusted-helper-type-end |
28 | #################### |
29 | |
30 | |
31 | === modified file 'exec-line-exec-trace.tp' |
32 | --- exec-line-exec-trace.tp 2014-08-11 17:19:57 +0000 |
33 | +++ exec-line-exec-trace.tp 2015-08-17 21:35:03 +0000 |
34 | @@ -5,6 +5,12 @@ |
35 | ctf_string(appid, appid) |
36 | ) |
37 | ) |
38 | +TRACEPOINT_EVENT(ubuntu_app_launch, exec_parse_complete, |
39 | + TP_ARGS(const char *, appid), |
40 | + TP_FIELDS( |
41 | + ctf_string(appid, appid) |
42 | + ) |
43 | +) |
44 | TRACEPOINT_EVENT(ubuntu_app_launch, exec_pre_exec, |
45 | TP_ARGS(const char *, appid), |
46 | TP_FIELDS( |
47 | |
48 | === modified file 'exec-line-exec.c' |
49 | --- exec-line-exec.c 2014-08-11 17:19:57 +0000 |
50 | +++ exec-line-exec.c 2015-08-17 21:35:03 +0000 |
51 | @@ -139,6 +139,20 @@ |
52 | return 1; |
53 | } |
54 | |
55 | + ual_tracepoint(exec_parse_complete, app_id); |
56 | + |
57 | + if (g_getenv("MIR_SOCKET") != NULL && g_strcmp0(g_getenv("APP_XMIR_ENABLE"), "1") == 0) { |
58 | + g_debug("XMir Helper being used"); |
59 | + |
60 | + /* xmir-helper $(APP_ID) $(COMMAND) */ |
61 | + const gchar * appid = g_getenv("APP_ID"); |
62 | + g_array_prepend_val(newargv, appid); |
63 | + |
64 | + /* Pulling into the heap instead of the code page */ |
65 | + char * xmir_helper = g_strdup(XMIR_HELPER); |
66 | + g_array_prepend_val(newargv, xmir_helper); |
67 | + } |
68 | + |
69 | /* Now exec */ |
70 | gchar ** nargv = (gchar**)g_array_free(newargv, FALSE); |
71 | |
72 | |
73 | === modified file 'libubuntu-app-launch/click-exec.c' |
74 | --- libubuntu-app-launch/click-exec.c 2014-08-22 21:04:13 +0000 |
75 | +++ libubuntu-app-launch/click-exec.c 2015-08-17 21:35:03 +0000 |
76 | @@ -136,6 +136,14 @@ |
77 | return FALSE; |
78 | } |
79 | |
80 | + if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { |
81 | + if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { |
82 | + env_handle_add(handle, "APP_XMIR_ENABLE", "1"); |
83 | + } else { |
84 | + env_handle_add(handle, "APP_XMIR_ENABLE", "0"); |
85 | + } |
86 | + } |
87 | + |
88 | /* This string is quoted using desktop file quoting: |
89 | http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */ |
90 | gchar * exec = desktop_to_exec(keyfile, desktopfile); |
91 | |
92 | === modified file 'libubuntu-app-launch/desktop-exec.c' |
93 | --- libubuntu-app-launch/desktop-exec.c 2014-08-22 21:06:00 +0000 |
94 | +++ libubuntu-app-launch/desktop-exec.c 2015-08-17 21:35:03 +0000 |
95 | @@ -118,6 +118,14 @@ |
96 | env_handle_add(handle, "APP_EXEC_POLICY", "unconfined"); |
97 | } |
98 | |
99 | + if (g_key_file_has_key(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { |
100 | + if (g_key_file_get_boolean(keyfile, "Desktop Entry", "X-Ubuntu-XMir-Enable", NULL)) { |
101 | + env_handle_add(handle, "APP_XMIR_ENABLE", "1"); |
102 | + } else { |
103 | + env_handle_add(handle, "APP_XMIR_ENABLE", "0"); |
104 | + } |
105 | + } |
106 | + |
107 | /* This string is quoted using desktop file quoting: |
108 | http://standards.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html#exec-variables */ |
109 | gchar * execline = desktop_to_exec(keyfile, app_id); |
110 | |
111 | === modified file 'tests/CMakeLists.txt' |
112 | --- tests/CMakeLists.txt 2015-05-13 18:40:49 +0000 |
113 | +++ tests/CMakeLists.txt 2015-08-17 21:35:03 +0000 |
114 | @@ -95,3 +95,9 @@ |
115 | configure_file ("click-desktop-hook-db/test.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/click-desktop-hook-db/test.conf" @ONLY) |
116 | configure_file ("desktop-hook-test.sh.in" "${CMAKE_CURRENT_BINARY_DIR}/desktop-hook-test.sh" @ONLY) |
117 | add_test (desktop-hook-test desktop-hook-test.sh) |
118 | + |
119 | +# XMir helper Test |
120 | + |
121 | +configure_file ("xmir-helper-test.in" "${CMAKE_CURRENT_BINARY_DIR}/xmir-helper-test" @ONLY) |
122 | +add_test (xmir-helper-test xmir-helper-test) |
123 | + |
124 | |
125 | === added file 'tests/applications/noxmir.desktop' |
126 | --- tests/applications/noxmir.desktop 1970-01-01 00:00:00 +0000 |
127 | +++ tests/applications/noxmir.desktop 2015-08-17 21:35:03 +0000 |
128 | @@ -0,0 +1,8 @@ |
129 | +[Desktop Entry] |
130 | +Name=No XMir Needed |
131 | +Type=Application |
132 | +Exec=noxmir |
133 | +NoDisplay=false |
134 | +Hidden=false |
135 | +Terminal=false |
136 | +X-Ubuntu-XMir-Enable=false |
137 | |
138 | === added file 'tests/applications/xmir.desktop' |
139 | --- tests/applications/xmir.desktop 1970-01-01 00:00:00 +0000 |
140 | +++ tests/applications/xmir.desktop 2015-08-17 21:35:03 +0000 |
141 | @@ -0,0 +1,8 @@ |
142 | +[Desktop Entry] |
143 | +Name=X Application |
144 | +Type=Application |
145 | +Exec=xfoo |
146 | +NoDisplay=false |
147 | +Hidden=false |
148 | +Terminal=false |
149 | +X-Ubuntu-XMir-Enable=true |
150 | |
151 | === added file 'tests/click-app-dir/.click/info/com.test.mir.manifest' |
152 | --- tests/click-app-dir/.click/info/com.test.mir.manifest 1970-01-01 00:00:00 +0000 |
153 | +++ tests/click-app-dir/.click/info/com.test.mir.manifest 2015-08-17 21:35:03 +0000 |
154 | @@ -0,0 +1,11 @@ |
155 | +{ |
156 | + "version": "1", |
157 | + "hooks": { |
158 | + "mir": { |
159 | + "desktop": "xmir.desktop" |
160 | + }, |
161 | + "nomir": { |
162 | + "desktop": "noxmir.desktop" |
163 | + } |
164 | + } |
165 | +} |
166 | |
167 | === added file 'tests/click-app-dir/noxmir.desktop' |
168 | --- tests/click-app-dir/noxmir.desktop 1970-01-01 00:00:00 +0000 |
169 | +++ tests/click-app-dir/noxmir.desktop 2015-08-17 21:35:03 +0000 |
170 | @@ -0,0 +1,8 @@ |
171 | +[Desktop Entry] |
172 | +Name=No XMir Needed |
173 | +Type=Application |
174 | +Exec=noxmir |
175 | +NoDisplay=false |
176 | +Hidden=false |
177 | +Terminal=false |
178 | +X-Ubuntu-XMir-Enable=false |
179 | |
180 | === added file 'tests/click-app-dir/xmir.desktop' |
181 | --- tests/click-app-dir/xmir.desktop 1970-01-01 00:00:00 +0000 |
182 | +++ tests/click-app-dir/xmir.desktop 2015-08-17 21:35:03 +0000 |
183 | @@ -0,0 +1,8 @@ |
184 | +[Desktop Entry] |
185 | +Name=X Application |
186 | +Type=Application |
187 | +Exec=xfoo |
188 | +NoDisplay=false |
189 | +Hidden=false |
190 | +Terminal=false |
191 | +X-Ubuntu-XMir-Enable=true |
192 | |
193 | === added symlink 'tests/click-root-dir/.click/users/test-user/com.test.mir' |
194 | === target is u'../../../com.test.mir/1/' |
195 | === added directory 'tests/click-root-dir/com.test.mir' |
196 | === added symlink 'tests/click-root-dir/com.test.mir/1' |
197 | === target is u'../../click-app-dir/' |
198 | === modified file 'tests/exec-util-test.cc' |
199 | --- tests/exec-util-test.cc 2014-08-26 02:21:57 +0000 |
200 | +++ tests/exec-util-test.cc 2015-08-17 21:35:03 +0000 |
201 | @@ -17,6 +17,9 @@ |
202 | * Ted Gould <ted.gould@canonical.com> |
203 | */ |
204 | |
205 | +#include <map> |
206 | +#include <functional> |
207 | + |
208 | #include <gtest/gtest.h> |
209 | #include <libdbustest/dbus-test.h> |
210 | #include <gio/gio.h> |
211 | @@ -88,186 +91,191 @@ |
212 | cleartry++; |
213 | } |
214 | } |
215 | + |
216 | + inline void StartCheckEnv (const std::string& appid, std::map<std::string, std::function<void(const gchar *)>> enums) { |
217 | + std::map<std::string, bool> env_found; |
218 | + DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", nullptr); |
219 | + |
220 | + g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); |
221 | + g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
222 | + g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE); |
223 | + |
224 | + ASSERT_TRUE(ubuntu_app_launch_start_application(appid.c_str(), nullptr)); |
225 | + |
226 | + guint len = 0; |
227 | + const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, nullptr); |
228 | + |
229 | + ASSERT_EQ(1, len); |
230 | + ASSERT_NE(nullptr, calls); |
231 | + ASSERT_STREQ("Start", calls[0].name); |
232 | + |
233 | + GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); |
234 | + GVariantIter iter; |
235 | + g_variant_iter_init(&iter, envarray); |
236 | + gchar * envvar = NULL; |
237 | + |
238 | + while (g_variant_iter_loop(&iter, "s", &envvar)) { |
239 | + g_debug("Looking at variable: %s", envvar); |
240 | + gchar * var = g_strdup(envvar); |
241 | + |
242 | + gchar * equal = g_strstr_len(var, -1, "="); |
243 | + ASSERT_NE(equal, nullptr); |
244 | + |
245 | + equal[0] = '\0'; |
246 | + gchar * value = &(equal[1]); |
247 | + |
248 | + /* Test the variable */ |
249 | + auto varfunc = enums[var]; |
250 | + EXPECT_NE(nullptr, varfunc); |
251 | + if (varfunc) |
252 | + varfunc(value); |
253 | + |
254 | + /* Mark it as found */ |
255 | + env_found[var] = true; |
256 | + |
257 | + g_free(var); |
258 | + } |
259 | + |
260 | + g_variant_unref(envarray); |
261 | + |
262 | + for(auto enumval : enums) { |
263 | + EXPECT_TRUE(env_found[enumval.first]); |
264 | + } |
265 | + } |
266 | }; |
267 | |
268 | +static void |
269 | +nocheck (const gchar *) |
270 | +{ |
271 | +} |
272 | + |
273 | TEST_F(ExecUtil, ClickExec) |
274 | { |
275 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); |
276 | - |
277 | - g_setenv("TEST_CLICK_DB", "click-db-dir", TRUE); |
278 | - g_setenv("TEST_CLICK_USER", "test-user", TRUE); |
279 | - g_setenv("UBUNTU_APP_LAUNCH_LINK_FARM", CMAKE_SOURCE_DIR "/link-farm", TRUE); |
280 | - |
281 | - ASSERT_TRUE(ubuntu_app_launch_start_application("com.test.good_application_1.2.3", NULL)); |
282 | - |
283 | - guint len = 0; |
284 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
285 | - |
286 | - ASSERT_EQ(1, len); |
287 | - ASSERT_NE(nullptr, calls); |
288 | - ASSERT_STREQ("Start", calls[0].name); |
289 | - |
290 | - unsigned int i; |
291 | - |
292 | - bool got_app_isolation = false; |
293 | - bool got_cache_home = false; |
294 | - bool got_config_home = false; |
295 | - bool got_data_home = false; |
296 | - bool got_runtime_dir = false; |
297 | - bool got_data_dirs = false; |
298 | - bool got_temp_dir = false; |
299 | - bool got_shader_dir = false; |
300 | - bool got_app_dir = false; |
301 | - bool got_app_exec = false; |
302 | - bool got_app_id = false; |
303 | - bool got_app_pid = false; |
304 | - bool got_app_desktop_path = false; |
305 | - |
306 | #define APP_DIR CMAKE_SOURCE_DIR "/click-root-dir/.click/users/test-user/com.test.good" |
307 | |
308 | - GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); |
309 | - GVariantIter iter; |
310 | - g_variant_iter_init(&iter, envarray); |
311 | - gchar * envvar = NULL; |
312 | - |
313 | - while (g_variant_iter_loop(&iter, "s", &envvar)) { |
314 | - gchar * var = g_strdup(envvar); |
315 | - |
316 | - gchar * equal = g_strstr_len(var, -1, "="); |
317 | - ASSERT_NE(equal, nullptr); |
318 | - |
319 | - equal[0] = '\0'; |
320 | - gchar * value = &(equal[1]); |
321 | - |
322 | - if (g_strcmp0(var, "UBUNTU_APPLICATION_ISOLATION") == 0) { |
323 | - EXPECT_STREQ("1", value); |
324 | - got_app_isolation = true; |
325 | - } else if (g_strcmp0(var, "XDG_CACHE_HOME") == 0) { |
326 | - got_cache_home = true; |
327 | - } else if (g_strcmp0(var, "XDG_CONFIG_HOME") == 0) { |
328 | - got_config_home = true; |
329 | - } else if (g_strcmp0(var, "XDG_DATA_HOME") == 0) { |
330 | - got_data_home = true; |
331 | - } else if (g_strcmp0(var, "XDG_RUNTIME_DIR") == 0) { |
332 | - got_runtime_dir = true; |
333 | - } else if (g_strcmp0(var, "XDG_DATA_DIRS") == 0) { |
334 | - EXPECT_TRUE(g_str_has_prefix(value, APP_DIR ":")); |
335 | - got_data_dirs = true; |
336 | - } else if (g_strcmp0(var, "TMPDIR") == 0) { |
337 | - EXPECT_TRUE(g_str_has_suffix(value, "com.test.good")); |
338 | - got_temp_dir = true; |
339 | - } else if (g_strcmp0(var, "__GL_SHADER_DISK_CACHE_PATH") == 0) { |
340 | - EXPECT_TRUE(g_str_has_suffix(value, "com.test.good")); |
341 | - got_shader_dir = true; |
342 | - } else if (g_strcmp0(var, "APP_DIR") == 0) { |
343 | - EXPECT_STREQ(APP_DIR, value); |
344 | - got_app_dir = true; |
345 | - } else if (g_strcmp0(var, "APP_EXEC") == 0) { |
346 | - EXPECT_STREQ("foo", value); |
347 | - got_app_exec = true; |
348 | - } else if (g_strcmp0(var, "APP_ID") == 0) { |
349 | - EXPECT_STREQ("com.test.good_application_1.2.3", value); |
350 | - got_app_id = true; |
351 | - } else if (g_strcmp0(var, "APP_LAUNCHER_PID") == 0) { |
352 | - EXPECT_EQ(getpid(), atoi(value)); |
353 | - got_app_pid = true; |
354 | - } else if (g_strcmp0(var, "APP_DESKTOP_FILE_PATH") == 0) { |
355 | - EXPECT_STREQ(APP_DIR "/application.desktop", value); |
356 | - got_app_desktop_path = true; |
357 | - } else { |
358 | - g_warning("Unknown variable! %s", var); |
359 | - EXPECT_TRUE(false); |
360 | - } |
361 | - |
362 | - g_free(var); |
363 | - } |
364 | - |
365 | - g_variant_unref(envarray); |
366 | + StartCheckEnv("com.test.good_application_1.2.3", { |
367 | + {"UBUNTU_APPLICATION_ISOLATION", [](const gchar * value) { |
368 | + EXPECT_STREQ("1", value); }}, |
369 | + {"XDG_CACHE_HOME", nocheck}, |
370 | + {"XDG_CONFIG_HOME", nocheck}, |
371 | + {"XDG_DATA_HOME", nocheck}, |
372 | + {"XDG_RUNTIME_DIR", nocheck}, |
373 | + {"XDG_DATA_DIRS", [](const gchar * value) { |
374 | + EXPECT_TRUE(g_str_has_prefix(value, APP_DIR ":")); }}, |
375 | + {"TMPDIR", [](const gchar * value) { |
376 | + EXPECT_TRUE(g_str_has_suffix(value, "com.test.good")); }}, |
377 | + {"__GL_SHADER_DISK_CACHE_PATH", [](const gchar * value) { |
378 | + EXPECT_TRUE(g_str_has_suffix(value, "com.test.good")); }}, |
379 | + {"APP_DIR", [](const gchar * value) { |
380 | + EXPECT_STREQ(APP_DIR, value); }}, |
381 | + {"APP_EXEC", [](const gchar * value) { |
382 | + EXPECT_STREQ("foo", value); }}, |
383 | + {"APP_ID", [](const gchar * value) { |
384 | + EXPECT_STREQ("com.test.good_application_1.2.3", value); }}, |
385 | + {"APP_LAUNCHER_PID", [](const gchar * value) { |
386 | + EXPECT_EQ(getpid(), atoi(value)); }}, |
387 | + {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
388 | + EXPECT_STREQ(APP_DIR "/application.desktop", value); }}, |
389 | + }); |
390 | |
391 | #undef APP_DIR |
392 | - |
393 | - EXPECT_TRUE(got_app_isolation); |
394 | - EXPECT_TRUE(got_cache_home); |
395 | - EXPECT_TRUE(got_config_home); |
396 | - EXPECT_TRUE(got_data_home); |
397 | - EXPECT_TRUE(got_runtime_dir); |
398 | - EXPECT_TRUE(got_data_dirs); |
399 | - EXPECT_TRUE(got_temp_dir); |
400 | - EXPECT_TRUE(got_shader_dir); |
401 | - EXPECT_TRUE(got_app_dir); |
402 | - EXPECT_TRUE(got_app_exec); |
403 | - EXPECT_TRUE(got_app_id); |
404 | - EXPECT_TRUE(got_app_pid); |
405 | - EXPECT_TRUE(got_app_desktop_path); |
406 | } |
407 | |
408 | TEST_F(ExecUtil, DesktopExec) |
409 | { |
410 | - DbusTestDbusMockObject * obj = dbus_test_dbus_mock_get_object(mock, "/com/test/job", "com.ubuntu.Upstart0_6.Job", NULL); |
411 | - |
412 | - ASSERT_TRUE(ubuntu_app_launch_start_application("foo", NULL)); |
413 | - |
414 | - guint len = 0; |
415 | - const DbusTestDbusMockCall * calls = dbus_test_dbus_mock_object_get_method_calls(mock, obj, "Start", &len, NULL); |
416 | - |
417 | - ASSERT_EQ(1, len); |
418 | - ASSERT_NE(nullptr, calls); |
419 | - ASSERT_STREQ("Start", calls[0].name); |
420 | - |
421 | - unsigned int i; |
422 | - |
423 | - bool got_app_exec = false; |
424 | - bool got_app_desktop_path = false; |
425 | - bool got_app_exec_policy = false; |
426 | - bool got_app_id = false; |
427 | - bool got_app_pid = false; |
428 | - bool got_instance_id = false; |
429 | - |
430 | - GVariant * envarray = g_variant_get_child_value(calls[0].params, 0); |
431 | - GVariantIter iter; |
432 | - g_variant_iter_init(&iter, envarray); |
433 | - gchar * envvar = NULL; |
434 | - |
435 | - while (g_variant_iter_loop(&iter, "s", &envvar)) { |
436 | - gchar * var = g_strdup(envvar); |
437 | - |
438 | - gchar * equal = g_strstr_len(var, -1, "="); |
439 | - ASSERT_NE(equal, nullptr); |
440 | - |
441 | - equal[0] = '\0'; |
442 | - gchar * value = &(equal[1]); |
443 | - |
444 | - if (g_strcmp0(var, "APP_EXEC") == 0) { |
445 | - EXPECT_STREQ("foo", value); |
446 | - got_app_exec = true; |
447 | - } else if (g_strcmp0(var, "APP_DESKTOP_FILE_PATH") == 0) { |
448 | - EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/foo.desktop", value); |
449 | - got_app_desktop_path = true; |
450 | - } else if (g_strcmp0(var, "APP_EXEC_POLICY") == 0) { |
451 | - EXPECT_STREQ("unconfined", value); |
452 | - got_app_exec_policy = true; |
453 | - } else if (g_strcmp0(var, "APP_ID") == 0) { |
454 | - EXPECT_STREQ("foo", value); |
455 | - got_app_id = true; |
456 | - } else if (g_strcmp0(var, "APP_LAUNCHER_PID") == 0) { |
457 | - EXPECT_EQ(getpid(), atoi(value)); |
458 | - got_app_pid = true; |
459 | - } else if (g_strcmp0(var, "INSTANCE_ID") == 0) { |
460 | - got_instance_id = true; |
461 | - } else { |
462 | - g_warning("Unknown variable! %s", var); |
463 | - EXPECT_TRUE(false); |
464 | - } |
465 | - |
466 | - g_free(var); |
467 | - } |
468 | - |
469 | - g_variant_unref(envarray); |
470 | - |
471 | - EXPECT_TRUE(got_app_exec); |
472 | - EXPECT_TRUE(got_app_desktop_path); |
473 | - EXPECT_TRUE(got_app_exec_policy); |
474 | - EXPECT_TRUE(got_app_id); |
475 | - EXPECT_TRUE(got_app_pid); |
476 | - EXPECT_TRUE(got_instance_id); |
477 | + StartCheckEnv("foo", { |
478 | + {"APP_EXEC", [](const gchar * value) { |
479 | + EXPECT_STREQ("foo", value); }}, |
480 | + {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
481 | + EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/foo.desktop", value); }}, |
482 | + {"APP_EXEC_POLICY", [](const gchar * value) { |
483 | + EXPECT_STREQ("unconfined", value); }}, |
484 | + {"APP_ID", [](const gchar * value) { |
485 | + EXPECT_STREQ("foo", value); }}, |
486 | + {"INSTANCE_ID", nocheck}, |
487 | + {"APP_LAUNCHER_PID", [](const gchar * value) { |
488 | + EXPECT_EQ(getpid(), atoi(value)); }}, |
489 | + }); |
490 | +} |
491 | + |
492 | +TEST_F(ExecUtil, DesktopMir) |
493 | +{ |
494 | + StartCheckEnv("xmir", { |
495 | + {"APP_EXEC", [](const gchar * value) { |
496 | + EXPECT_STREQ("xfoo", value); }}, |
497 | + {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
498 | + EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/xmir.desktop", value); }}, |
499 | + {"APP_EXEC_POLICY", [](const gchar * value) { |
500 | + EXPECT_STREQ("unconfined", value); }}, |
501 | + {"APP_ID", [](const gchar * value) { |
502 | + EXPECT_STREQ("xmir", value); }}, |
503 | + {"INSTANCE_ID", nocheck}, |
504 | + {"APP_LAUNCHER_PID", [](const gchar * value) { |
505 | + EXPECT_EQ(getpid(), atoi(value)); }}, |
506 | + {"APP_XMIR_ENABLE", [](const gchar * value) { |
507 | + EXPECT_STREQ("1", value); }}, |
508 | + }); |
509 | +} |
510 | + |
511 | +TEST_F(ExecUtil, DesktopNoMir) |
512 | +{ |
513 | + StartCheckEnv("noxmir", { |
514 | + {"APP_EXEC", [](const gchar * value) { |
515 | + EXPECT_STREQ("noxmir", value); }}, |
516 | + {"APP_DESKTOP_FILE_PATH", [](const gchar * value) { |
517 | + EXPECT_STREQ(CMAKE_SOURCE_DIR "/applications/noxmir.desktop", value); }}, |
518 | + {"APP_EXEC_POLICY", [](const gchar * value) { |
519 | + EXPECT_STREQ("unconfined", value); }}, |
520 | + {"APP_ID", [](const gchar * value) { |
521 | + EXPECT_STREQ("noxmir", value); }}, |
522 | + {"INSTANCE_ID", nocheck}, |
523 | + {"APP_LAUNCHER_PID", [](const gchar * value) { |
524 | + EXPECT_EQ(getpid(), atoi(value)); }}, |
525 | + {"APP_XMIR_ENABLE", [](const gchar * value) { |
526 | + EXPECT_STREQ("0", value); }}, |
527 | + }); |
528 | +} |
529 | + |
530 | +TEST_F(ExecUtil, ClickMir) |
531 | +{ |
532 | + StartCheckEnv("com.test.mir_mir_1", { |
533 | + {"UBUNTU_APPLICATION_ISOLATION", nocheck}, |
534 | + {"XDG_CACHE_HOME", nocheck}, |
535 | + {"XDG_CONFIG_HOME", nocheck}, |
536 | + {"XDG_DATA_HOME", nocheck}, |
537 | + {"XDG_RUNTIME_DIR", nocheck}, |
538 | + {"XDG_DATA_DIRS", nocheck}, |
539 | + {"TMPDIR", nocheck}, |
540 | + {"__GL_SHADER_DISK_CACHE_PATH", nocheck}, |
541 | + {"APP_DIR", nocheck}, |
542 | + {"APP_EXEC", nocheck}, |
543 | + {"APP_ID", [](const gchar * value) { |
544 | + EXPECT_STREQ("com.test.mir_mir_1", value); }}, |
545 | + {"APP_LAUNCHER_PID", nocheck}, |
546 | + {"APP_DESKTOP_FILE_PATH", nocheck}, |
547 | + {"APP_XMIR_ENABLE", [](const gchar * value) { |
548 | + EXPECT_STREQ("1", value); }}, |
549 | + }); |
550 | +} |
551 | + |
552 | +TEST_F(ExecUtil, ClickNoMir) |
553 | +{ |
554 | + StartCheckEnv("com.test.mir_nomir_1", { |
555 | + {"UBUNTU_APPLICATION_ISOLATION", nocheck}, |
556 | + {"XDG_CACHE_HOME", nocheck}, |
557 | + {"XDG_CONFIG_HOME", nocheck}, |
558 | + {"XDG_DATA_HOME", nocheck}, |
559 | + {"XDG_RUNTIME_DIR", nocheck}, |
560 | + {"XDG_DATA_DIRS", nocheck}, |
561 | + {"TMPDIR", nocheck}, |
562 | + {"__GL_SHADER_DISK_CACHE_PATH", nocheck}, |
563 | + {"APP_DIR", nocheck}, |
564 | + {"APP_EXEC", nocheck}, |
565 | + {"APP_ID", [](const gchar * value) { |
566 | + EXPECT_STREQ("com.test.mir_nomir_1", value); }}, |
567 | + {"APP_LAUNCHER_PID", nocheck}, |
568 | + {"APP_DESKTOP_FILE_PATH", nocheck}, |
569 | + {"APP_XMIR_ENABLE", [](const gchar * value) { |
570 | + EXPECT_STREQ("0", value); }}, |
571 | + }); |
572 | } |
573 | |
574 | === added file 'tests/link-farm/com.test.mir_mir_1.desktop' |
575 | --- tests/link-farm/com.test.mir_mir_1.desktop 1970-01-01 00:00:00 +0000 |
576 | +++ tests/link-farm/com.test.mir_mir_1.desktop 2015-08-17 21:35:03 +0000 |
577 | @@ -0,0 +1,1 @@ |
578 | +Needs to exist |
579 | |
580 | === added file 'tests/link-farm/com.test.mir_nomir_1.desktop' |
581 | --- tests/link-farm/com.test.mir_nomir_1.desktop 1970-01-01 00:00:00 +0000 |
582 | +++ tests/link-farm/com.test.mir_nomir_1.desktop 2015-08-17 21:35:03 +0000 |
583 | @@ -0,0 +1,1 @@ |
584 | +Needs to exist |
585 | |
586 | === added file 'tests/xmir-helper-exec.sh' |
587 | --- tests/xmir-helper-exec.sh 1970-01-01 00:00:00 +0000 |
588 | +++ tests/xmir-helper-exec.sh 2015-08-17 21:35:03 +0000 |
589 | @@ -0,0 +1,3 @@ |
590 | +#!/bin/bash |
591 | + |
592 | +echo $DISPLAY |
593 | |
594 | === added file 'tests/xmir-helper-test.in' |
595 | --- tests/xmir-helper-test.in 1970-01-01 00:00:00 +0000 |
596 | +++ tests/xmir-helper-test.in 2015-08-17 21:35:03 +0000 |
597 | @@ -0,0 +1,25 @@ |
598 | +#!/bin/bash |
599 | + |
600 | +echo -n "Testing XMir Helper… " |
601 | + |
602 | +export UBUNTU_APP_LAUNCH_XMIR_PATH="@CMAKE_CURRENT_SOURCE_DIR@/xmir-mock.sh" |
603 | + |
604 | +TESTVALUE=`@CMAKE_BINARY_DIR@/xmir-helper com.mir.test_mirtest_1.2.3 @CMAKE_CURRENT_SOURCE_DIR@/xmir-helper-exec.sh` |
605 | + |
606 | +if [ $TESTVALUE == ":42" ]; then |
607 | + echo "PASSED" |
608 | +else |
609 | + echo "FAILED" |
610 | + exit 1 |
611 | +fi |
612 | + |
613 | +echo -n "Testing an evil XMir helper… " |
614 | + |
615 | +export UBUNTU_APP_LAUNCH_XMIR_PATH="@CMAKE_CURRENT_SOURCE_DIR@/xmir-mock-evil.sh" |
616 | + |
617 | +if @CMAKE_BINARY_DIR@/xmir-helper com.mir.test_mirtest_1.2.3 @CMAKE_CURRENT_SOURCE_DIR@/xmir-helper-exec.sh ; then |
618 | + echo "FAILED" |
619 | + exit 1 |
620 | +else |
621 | + echo "PASSED" |
622 | +fi |
623 | |
624 | === added file 'tests/xmir-mock.sh' |
625 | --- tests/xmir-mock.sh 1970-01-01 00:00:00 +0000 |
626 | +++ tests/xmir-mock.sh 2015-08-17 21:35:03 +0000 |
627 | @@ -0,0 +1,22 @@ |
628 | +#!/bin/bash |
629 | + |
630 | +if [ $1 != "-displayfd" ]; then |
631 | + echo "-displayfd missing" |
632 | + exit 1 |
633 | +fi |
634 | + |
635 | +if [ $3 != "-mir" ]; then |
636 | + echo "-mir missing" |
637 | + exit 1 |
638 | +fi |
639 | + |
640 | +if [ $4 != "com.mir.test_mirtest_1.2.3" ]; then |
641 | + echo "AppID wrong" |
642 | + exit 1 |
643 | +fi |
644 | + |
645 | +echo "42" >&$2 |
646 | + |
647 | +# Ensure that our "XMir" runs longer than |
648 | +# the test, if it exits first that's a failure |
649 | +sleep 1 |
650 | |
651 | === modified file 'upstart-jobs/application-click.conf.in' |
652 | --- upstart-jobs/application-click.conf.in 2015-01-23 18:12:29 +0000 |
653 | +++ upstart-jobs/application-click.conf.in 2015-08-17 21:35:03 +0000 |
654 | @@ -11,6 +11,7 @@ |
655 | env APP_URIS |
656 | env APP_DIR |
657 | env APP_DESKTOP_FILE_PATH |
658 | +env APP_XMIR_ENABLE |
659 | |
660 | env UBUNTU_APP_LAUNCH_ARCH="@ubuntu_app_launch_arch@" |
661 | export UBUNTU_APP_LAUNCH_ARCH |
662 | |
663 | === modified file 'upstart-jobs/application-legacy.conf.in' |
664 | --- upstart-jobs/application-legacy.conf.in 2015-01-23 18:12:29 +0000 |
665 | +++ upstart-jobs/application-legacy.conf.in 2015-08-17 21:35:03 +0000 |
666 | @@ -11,6 +11,7 @@ |
667 | env APP_EXEC_POLICY="" |
668 | env APP_URIS |
669 | env APP_DESKTOP_FILE_PATH |
670 | +env APP_XMIR_ENABLE |
671 | |
672 | # This will be set to "unconfined" by desktop-exec if there is no confinement defined |
673 | apparmor switch $APP_EXEC_POLICY |
674 | |
675 | === added file 'xmir-helper.c' |
676 | --- xmir-helper.c 1970-01-01 00:00:00 +0000 |
677 | +++ xmir-helper.c 2015-08-17 21:35:03 +0000 |
678 | @@ -0,0 +1,117 @@ |
679 | +/* |
680 | + * Copyright © 2014 Canonical Ltd. |
681 | + * |
682 | + * This program is free software: you can redistribute it and/or modify it |
683 | + * under the terms of the GNU General Public License version 3, as published |
684 | + * by the Free Software Foundation. |
685 | + * |
686 | + * This program is distributed in the hope that it will be useful, but |
687 | + * WITHOUT ANY WARRANTY; without even the implied warranties of |
688 | + * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR |
689 | + * PURPOSE. See the GNU General Public License for more details. |
690 | + * |
691 | + * You should have received a copy of the GNU General Public License along |
692 | + * with this program. If not, see <http://www.gnu.org/licenses/>. |
693 | + * |
694 | + * Authors: |
695 | + * Ted Gould <ted.gould@canonical.com> |
696 | + */ |
697 | + |
698 | +#define _POSIX_C_SOURCE 200212L |
699 | + |
700 | +#include <unistd.h> |
701 | +#include <stdio.h> |
702 | +#include <stdlib.h> |
703 | +#include <sys/types.h> |
704 | +#include <sys/socket.h> |
705 | +#include <signal.h> |
706 | + |
707 | +void |
708 | +sigchild_handler (int signal) |
709 | +{ |
710 | + fprintf(stderr, "XMir has closed unexpectedly\n"); |
711 | + exit(1); |
712 | +} |
713 | + |
714 | +struct sigaction sigchild_action = { |
715 | + .sa_handler = sigchild_handler, |
716 | + .sa_flags = SA_NOCLDWAIT |
717 | +}; |
718 | + |
719 | +int |
720 | +main (int argc, char * argv[]) |
721 | +{ |
722 | + if (argc < 3) { |
723 | + fprintf(stderr, "xmir-helper needs more arguments: xmir-helper $(appid) $(thing to exec) ... \n"); |
724 | + return 1; |
725 | + } |
726 | + |
727 | + /* Make nice variables for the things we need */ |
728 | + char * appid = argv[1]; |
729 | + char * xmir = getenv("UBUNTU_APP_LAUNCH_XMIR_PATH"); |
730 | + if (xmir == NULL) { |
731 | + xmir = "/usr/bin/Xmir"; |
732 | + } |
733 | + |
734 | + /* Build a socket pair to get the connection back from XMir */ |
735 | + int sockets[2]; |
736 | + if (socketpair(AF_LOCAL, SOCK_STREAM, 0, sockets) != 0) { |
737 | + fprintf(stderr, "Unable to create socketpair for communicating with XMir\n"); |
738 | + return 1; |
739 | + } |
740 | + |
741 | + /* Give them nice names, the compiler will optimize out */ |
742 | + int xmirsocket = sockets[0]; |
743 | + int helpersocket = sockets[1]; |
744 | + |
745 | + /* Watch for the child dying */ |
746 | + if (sigaction(SIGCHLD, &sigchild_action, NULL) != 0) { |
747 | + fprintf(stderr, "Unable to setup child signal handler\n"); |
748 | + return 1; |
749 | + } |
750 | + |
751 | + /* Start XMir */ |
752 | + if (fork() == 0) { |
753 | + /* XMir start here */ |
754 | + /* GOAL: XMir -displayfd ${xmirsocket} -mir ${appid} */ |
755 | + char socketbuf[16] = {0}; |
756 | + snprintf(socketbuf, 16, "%d", xmirsocket); |
757 | + |
758 | + char * xmirexec[6] = { |
759 | + xmir, |
760 | + "-displayfd", |
761 | + socketbuf, |
762 | + "-mir", |
763 | + appid, |
764 | + NULL |
765 | + }; |
766 | + |
767 | + return execv(xmir, xmirexec); |
768 | + } |
769 | + |
770 | + /* Wait to get the display number from XMir */ |
771 | + char readbuf[16] = {0}; |
772 | + if (read(helpersocket, readbuf, 16) == 0) { |
773 | + fprintf(stderr, "Not reading anything from XMir\n"); |
774 | + return 1; |
775 | + } |
776 | + |
777 | + int i; |
778 | + for (i = 0; i < sizeof(readbuf); i++) { |
779 | + if (readbuf[i] == '\n') { |
780 | + readbuf[i] = '\0'; |
781 | + break; |
782 | + } |
783 | + } |
784 | + |
785 | + char displaynumber[16] = {0}; |
786 | + snprintf(displaynumber, 16, ":%s", readbuf); |
787 | + |
788 | + /* Set up the display variable */ |
789 | + setenv("DISPLAY", displaynumber, 1); |
790 | + |
791 | + /* Now that we have everything setup, we can execute */ |
792 | + char ** nargv = &argv[2]; |
793 | + int execret = execvp(nargv[0], nargv); |
794 | + return execret; |
795 | +} |
PASSED: Continuous integration, rev:134 jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- ci/7/ jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- wily-amd64- ci/7 jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- wily-armhf- ci/7 jenkins. qa.ubuntu. com/job/ ubuntu- app-launch- wily-i386- ci/7
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/ubuntu- app-launch- ci/7/rebuild
http://