Merge lp:~ted/ubuntu-app-launch/xmir-support into lp:ubuntu-app-launch/15.10

Proposed by Ted Gould on 2015-07-01
Status: Merged
Approved by: Christopher Townsend on 2015-08-13
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
Reviewer Review Type Date Requested Status
Christopher Townsend 2015-07-01 Approve on 2015-08-13
Charles Kerr (community) Approve on 2015-08-11
PS Jenkins bot (community) continuous-integration Approve on 2015-08-11
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

To post a comment you must log in.
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.

review: Needs Information
135. By Ted Gould on 2015-08-06

Remove the -rootless flag

Charles Kerr (charlesk) wrote :

Suggestions/questions inline

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("UBUNTU_APP_LAUNCH_XMIR_PATH");
>
> 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 :-(

136. By Ted Gould on 2015-08-11

Refactor test into a helper function

137. By Ted Gould on 2015-08-11

Porting some more cases

138. By Ted Gould on 2015-08-11

Changing the click mir tests over

139. By Ted Gould on 2015-08-11

Mention varargs

140. By Ted Gould on 2015-08-11

Remove std=c11

Charles Kerr (charlesk) wrote :

Approved wrt the glib and testing; not reviewing Townsend's bits

review: Approve
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-compositor was transitioned before Mir and not the Unity 8 desktop session is broken.

review: Approve
141. By Ted Gould on 2015-08-17

Don't set a default value for XMIR_ENABLE

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-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+}

Subscribers

People subscribed via source and target branches