1 #include <glib/gstdio.h>
3 #include <gio/gdesktopappinfo.h>
6 strv_equal (gchar
**strv
, ...)
15 va_start (list
, strv
);
18 str
= va_arg (list
, const gchar
*);
21 if (g_strcmp0 (str
, strv
[count
]) != 0)
31 res
= g_strv_length (strv
) == count
;
36 const gchar
*myapp_data
=
44 const gchar
*myapp2_data
=
52 const gchar
*myapp3_data
=
59 "MimeType=image/png;";
61 const gchar
*myapp4_data
=
68 "MimeType=image/bmp;";
70 const gchar
*myapp5_data
=
77 "MimeType=image/bmp;x-scheme-handler/ftp;";
79 const gchar
*nosuchapp_data
=
84 "Exec=no_such_application %f\n"
87 const gchar
*defaults_data
=
88 "[Default Applications]\n"
89 "image/bmp=myapp4.desktop;\n"
90 "image/png=myapp3.desktop;\n"
91 "x-scheme-handler/ftp=myapp5.desktop;\n";
93 const gchar
*mimecache_data
=
95 "image/bmp=myapp4.desktop;myapp5.desktop;\n"
96 "image/png=myapp3.desktop;\n";
98 /* Set up XDG_DATA_HOME and XDG_DATA_DIRS.
99 * XDG_DATA_DIRS/applications will contain mimeapps.list
100 * XDG_DATA_HOME/applications will contain myapp.desktop
101 * and myapp2.desktop, and no mimeapps.list
107 gchar
*xdgconfighome
;
115 GError
*error
= NULL
;
117 dir
= g_get_current_dir ();
118 xdgconfighome
= g_build_filename (dir
, "xdgconfighome", NULL
);
119 xdgdatahome
= g_build_filename (dir
, "xdgdatahome", NULL
);
120 xdgdatadir
= g_build_filename (dir
, "xdgdatadir", NULL
);
121 g_test_message ("setting XDG_CONFIG_HOME to '%s'\n", xdgconfighome
);
122 g_setenv ("XDG_CONFIG_HOME", xdgconfighome
, TRUE
);
123 g_test_message ("setting XDG_DATA_HOME to '%s'\n", xdgdatahome
);
124 g_setenv ("XDG_DATA_HOME", xdgdatahome
, TRUE
);
125 g_test_message ("setting XDG_DATA_DIRS to '%s'\n", xdgdatadir
);
126 g_setenv ("XDG_DATA_DIRS", xdgdatadir
, TRUE
);
128 appdir
= g_build_filename (xdgdatadir
, "applications", NULL
);
129 g_test_message ("creating '%s'\n", appdir
);
130 res
= g_mkdir_with_parents (appdir
, 0700);
133 name
= g_build_filename (appdir
, "mimeapps.list", NULL
);
134 g_test_message ("creating '%s'\n", name
);
135 g_file_set_contents (name
, defaults_data
, -1, &error
);
136 g_assert_no_error (error
);
139 apphome
= g_build_filename (xdgdatahome
, "applications", NULL
);
140 g_test_message ("creating '%s'\n", apphome
);
141 res
= g_mkdir_with_parents (apphome
, 0700);
144 name
= g_build_filename (apphome
, "myapp.desktop", NULL
);
145 g_test_message ("creating '%s'\n", name
);
146 g_file_set_contents (name
, myapp_data
, -1, &error
);
147 g_assert_no_error (error
);
150 name
= g_build_filename (apphome
, "myapp2.desktop", NULL
);
151 g_test_message ("creating '%s'\n", name
);
152 g_file_set_contents (name
, myapp2_data
, -1, &error
);
153 g_assert_no_error (error
);
156 name
= g_build_filename (apphome
, "myapp3.desktop", NULL
);
157 g_test_message ("creating '%s'\n", name
);
158 g_file_set_contents (name
, myapp3_data
, -1, &error
);
159 g_assert_no_error (error
);
162 name
= g_build_filename (apphome
, "myapp4.desktop", NULL
);
163 g_test_message ("creating '%s'\n", name
);
164 g_file_set_contents (name
, myapp4_data
, -1, &error
);
165 g_assert_no_error (error
);
168 name
= g_build_filename (apphome
, "myapp5.desktop", NULL
);
169 g_test_message ("creating '%s'\n", name
);
170 g_file_set_contents (name
, myapp5_data
, -1, &error
);
171 g_assert_no_error (error
);
174 name
= g_build_filename (apphome
, "nosuchapp.desktop", NULL
);
175 g_test_message ("creating '%s'\n", name
);
176 g_file_set_contents (name
, nosuchapp_data
, -1, &error
);
177 g_assert_no_error (error
);
180 mimeapps
= g_build_filename (apphome
, "mimeapps.list", NULL
);
181 g_test_message ("removing '%s'\n", mimeapps
);
184 name
= g_build_filename (apphome
, "mimeinfo.cache", NULL
);
185 g_test_message ("creating '%s'\n", name
);
186 g_file_set_contents (name
, mimecache_data
, -1, &error
);
187 g_assert_no_error (error
);
191 g_free (xdgconfighome
);
192 g_free (xdgdatahome
);
204 GError
*error
= NULL
;
207 const gchar
*contenttype
= "application/pdf";
209 /* clear things out */
210 g_app_info_reset_type_associations (contenttype
);
212 appinfo
= (GAppInfo
*)g_desktop_app_info_new ("myapp.desktop");
213 appinfo2
= (GAppInfo
*)g_desktop_app_info_new ("myapp2.desktop");
215 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
216 list
= g_app_info_get_recommended_for_type (contenttype
);
217 g_assert (def
== NULL
);
218 g_assert (list
== NULL
);
220 /* 1. add a non-default association */
221 g_app_info_add_supports_type (appinfo
, contenttype
, &error
);
222 g_assert_no_error (error
);
224 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
225 list
= g_app_info_get_recommended_for_type (contenttype
);
226 g_assert (g_app_info_equal (def
, appinfo
));
227 g_assert_cmpint (g_list_length (list
), ==, 1);
228 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo
));
229 g_object_unref (def
);
230 g_list_free_full (list
, g_object_unref
);
232 /* 2. add another non-default association */
233 g_app_info_add_supports_type (appinfo2
, contenttype
, &error
);
234 g_assert_no_error (error
);
236 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
237 list
= g_app_info_get_recommended_for_type (contenttype
);
238 g_assert (g_app_info_equal (def
, appinfo
));
239 g_assert_cmpint (g_list_length (list
), ==, 2);
240 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo
));
241 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo2
));
242 g_object_unref (def
);
243 g_list_free_full (list
, g_object_unref
);
245 /* 3. make the first app the default */
246 g_app_info_set_as_default_for_type (appinfo
, contenttype
, &error
);
247 g_assert_no_error (error
);
249 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
250 list
= g_app_info_get_recommended_for_type (contenttype
);
251 g_assert (g_app_info_equal (def
, appinfo
));
252 g_assert_cmpint (g_list_length (list
), ==, 2);
253 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo
));
254 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo2
));
255 g_object_unref (def
);
256 g_list_free_full (list
, g_object_unref
);
258 /* 4. make the second app the last used one */
259 g_app_info_set_as_last_used_for_type (appinfo2
, contenttype
, &error
);
260 g_assert_no_error (error
);
262 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
263 list
= g_app_info_get_recommended_for_type (contenttype
);
264 g_assert (g_app_info_equal (def
, appinfo
));
265 g_assert_cmpint (g_list_length (list
), ==, 2);
266 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo2
));
267 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo
));
268 g_object_unref (def
);
269 g_list_free_full (list
, g_object_unref
);
271 /* 5. reset everything */
272 g_app_info_reset_type_associations (contenttype
);
274 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
275 list
= g_app_info_get_recommended_for_type (contenttype
);
276 g_assert (def
== NULL
);
277 g_assert (list
== NULL
);
279 g_object_unref (appinfo
);
280 g_object_unref (appinfo2
);
283 /* Repeat the same tests, this time checking that we handle
284 * mimeapps.list as expected. These tests are different from
285 * the ones in test_mime_api() in that we directly parse
286 * mimeapps.list to verify the results.
289 test_mime_file (void)
294 GError
*error
= NULL
;
302 const gchar
*contenttype
= "application/pdf";
304 dir
= g_get_current_dir ();
305 mimeapps
= g_build_filename (dir
, "xdgconfighome", "mimeapps.list", NULL
);
307 /* clear things out */
308 g_app_info_reset_type_associations (contenttype
);
310 appinfo
= (GAppInfo
*)g_desktop_app_info_new ("myapp.desktop");
311 appinfo2
= (GAppInfo
*)g_desktop_app_info_new ("myapp2.desktop");
313 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
314 list
= g_app_info_get_recommended_for_type (contenttype
);
315 g_assert (def
== NULL
);
316 g_assert (list
== NULL
);
318 /* 1. add a non-default association */
319 g_app_info_add_supports_type (appinfo
, contenttype
, &error
);
320 g_assert_no_error (error
);
322 keyfile
= g_key_file_new ();
323 g_key_file_load_from_file (keyfile
, mimeapps
, G_KEY_FILE_NONE
, &error
);
324 g_assert_no_error (error
);
326 assoc
= g_key_file_get_string_list (keyfile
, "Added Associations", contenttype
, NULL
, &error
);
327 g_assert_no_error (error
);
328 g_assert (strv_equal (assoc
, "myapp.desktop", NULL
));
331 /* we've unset XDG_DATA_DIRS so there should be no default */
332 assoc
= g_key_file_get_string_list (keyfile
, "Default Applications", contenttype
, NULL
, &error
);
333 g_assert (error
!= NULL
);
334 g_clear_error (&error
);
336 g_key_file_free (keyfile
);
338 /* 2. add another non-default association */
339 g_app_info_add_supports_type (appinfo2
, contenttype
, &error
);
340 g_assert_no_error (error
);
342 keyfile
= g_key_file_new ();
343 g_key_file_load_from_file (keyfile
, mimeapps
, G_KEY_FILE_NONE
, &error
);
344 g_assert_no_error (error
);
346 assoc
= g_key_file_get_string_list (keyfile
, "Added Associations", contenttype
, NULL
, &error
);
347 g_assert_no_error (error
);
348 g_assert (strv_equal (assoc
, "myapp.desktop", "myapp2.desktop", NULL
));
351 assoc
= g_key_file_get_string_list (keyfile
, "Default Applications", contenttype
, NULL
, &error
);
352 g_assert (error
!= NULL
);
353 g_clear_error (&error
);
355 g_key_file_free (keyfile
);
357 /* 3. make the first app the default */
358 g_app_info_set_as_default_for_type (appinfo
, contenttype
, &error
);
359 g_assert_no_error (error
);
361 keyfile
= g_key_file_new ();
362 g_key_file_load_from_file (keyfile
, mimeapps
, G_KEY_FILE_NONE
, &error
);
363 g_assert_no_error (error
);
365 assoc
= g_key_file_get_string_list (keyfile
, "Added Associations", contenttype
, NULL
, &error
);
366 g_assert_no_error (error
);
367 g_assert (strv_equal (assoc
, "myapp.desktop", "myapp2.desktop", NULL
));
370 str
= g_key_file_get_string (keyfile
, "Default Applications", contenttype
, &error
);
371 g_assert_no_error (error
);
372 g_assert_cmpstr (str
, ==, "myapp.desktop");
375 g_key_file_free (keyfile
);
377 /* 4. make the second app the last used one */
378 g_app_info_set_as_last_used_for_type (appinfo2
, contenttype
, &error
);
379 g_assert_no_error (error
);
381 keyfile
= g_key_file_new ();
382 g_key_file_load_from_file (keyfile
, mimeapps
, G_KEY_FILE_NONE
, &error
);
383 g_assert_no_error (error
);
385 assoc
= g_key_file_get_string_list (keyfile
, "Added Associations", contenttype
, NULL
, &error
);
386 g_assert_no_error (error
);
387 g_assert (strv_equal (assoc
, "myapp2.desktop", "myapp.desktop", NULL
));
390 g_key_file_free (keyfile
);
392 /* 5. reset everything */
393 g_app_info_reset_type_associations (contenttype
);
395 keyfile
= g_key_file_new ();
396 g_key_file_load_from_file (keyfile
, mimeapps
, G_KEY_FILE_NONE
, &error
);
397 g_assert_no_error (error
);
399 res
= g_key_file_has_key (keyfile
, "Added Associations", contenttype
, NULL
);
402 res
= g_key_file_has_key (keyfile
, "Default Applications", contenttype
, NULL
);
405 g_key_file_free (keyfile
);
407 g_object_unref (appinfo
);
408 g_object_unref (appinfo2
);
414 /* test interaction between mimeapps.list at different levels */
416 test_mime_default (void)
421 GError
*error
= NULL
;
424 const gchar
*contenttype
= "image/png";
426 /* clear things out */
427 g_app_info_reset_type_associations (contenttype
);
429 appinfo
= (GAppInfo
*)g_desktop_app_info_new ("myapp.desktop");
430 appinfo2
= (GAppInfo
*)g_desktop_app_info_new ("myapp2.desktop");
431 appinfo3
= (GAppInfo
*)g_desktop_app_info_new ("myapp3.desktop");
433 /* myapp3 is set as the default in defaults.list */
434 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
435 list
= g_app_info_get_recommended_for_type (contenttype
);
436 g_assert (g_app_info_equal (def
, appinfo3
));
437 g_assert_cmpint (g_list_length (list
), ==, 1);
438 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo3
));
439 g_object_unref (def
);
440 g_list_free_full (list
, g_object_unref
);
442 /* 1. add a non-default association */
443 g_app_info_add_supports_type (appinfo
, contenttype
, &error
);
444 g_assert_no_error (error
);
446 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
447 list
= g_app_info_get_recommended_for_type (contenttype
);
448 g_assert (g_app_info_equal (def
, appinfo3
)); /* default is unaffected */
449 g_assert_cmpint (g_list_length (list
), ==, 2);
450 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo
));
451 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo3
));
452 g_object_unref (def
);
453 g_list_free_full (list
, g_object_unref
);
455 /* 2. add another non-default association */
456 g_app_info_add_supports_type (appinfo2
, contenttype
, &error
);
457 g_assert_no_error (error
);
459 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
460 list
= g_app_info_get_recommended_for_type (contenttype
);
461 g_assert (g_app_info_equal (def
, appinfo3
));
462 g_assert_cmpint (g_list_length (list
), ==, 3);
463 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo
));
464 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo2
));
465 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->next
->data
, appinfo3
));
466 g_object_unref (def
);
467 g_list_free_full (list
, g_object_unref
);
469 /* 3. make the first app the default */
470 g_app_info_set_as_default_for_type (appinfo
, contenttype
, &error
);
471 g_assert_no_error (error
);
473 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
474 list
= g_app_info_get_recommended_for_type (contenttype
);
475 g_assert (g_app_info_equal (def
, appinfo
));
476 g_assert_cmpint (g_list_length (list
), ==, 3);
477 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo
));
478 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo2
));
479 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->next
->data
, appinfo3
));
480 g_object_unref (def
);
481 g_list_free_full (list
, g_object_unref
);
483 g_object_unref (appinfo
);
484 g_object_unref (appinfo2
);
485 g_object_unref (appinfo3
);
488 /* test interaction between mimeinfo.cache, defaults.list and mimeapps.list
489 * to ensure g_app_info_set_as_last_used_for_type doesn't incorrectly
493 test_mime_default_last_used (void)
497 GError
*error
= NULL
;
500 const gchar
*contenttype
= "image/bmp";
502 /* clear things out */
503 g_app_info_reset_type_associations (contenttype
);
505 appinfo4
= (GAppInfo
*)g_desktop_app_info_new ("myapp4.desktop");
506 appinfo5
= (GAppInfo
*)g_desktop_app_info_new ("myapp5.desktop");
508 /* myapp4 is set as the default in defaults.list */
509 /* myapp4 and myapp5 can both handle image/bmp */
510 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
511 list
= g_app_info_get_recommended_for_type (contenttype
);
512 g_assert (g_app_info_equal (def
, appinfo4
));
513 g_assert_cmpint (g_list_length (list
), ==, 2);
514 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo4
));
515 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo5
));
516 g_object_unref (def
);
517 g_list_free_full (list
, g_object_unref
);
519 /* 1. set default (myapp4) as last used */
520 g_app_info_set_as_last_used_for_type (appinfo4
, contenttype
, &error
);
521 g_assert_no_error (error
);
523 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
524 list
= g_app_info_get_recommended_for_type (contenttype
);
525 g_assert (g_app_info_equal (def
, appinfo4
)); /* default is unaffected */
526 g_assert_cmpint (g_list_length (list
), ==, 2);
527 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo4
));
528 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo5
));
529 g_object_unref (def
);
530 g_list_free_full (list
, g_object_unref
);
532 /* 2. set other (myapp5) as last used */
533 g_app_info_set_as_last_used_for_type (appinfo5
, contenttype
, &error
);
534 g_assert_no_error (error
);
536 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
537 list
= g_app_info_get_recommended_for_type (contenttype
);
538 g_assert (g_app_info_equal (def
, appinfo4
));
539 g_assert_cmpint (g_list_length (list
), ==, 2);
540 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo5
));
541 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo4
));
542 g_object_unref (def
);
543 g_list_free_full (list
, g_object_unref
);
545 /* 3. change the default to myapp5 */
546 g_app_info_set_as_default_for_type (appinfo5
, contenttype
, &error
);
547 g_assert_no_error (error
);
549 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
550 list
= g_app_info_get_recommended_for_type (contenttype
);
551 g_assert (g_app_info_equal (def
, appinfo5
));
552 g_assert_cmpint (g_list_length (list
), ==, 2);
553 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo5
));
554 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo4
));
555 g_object_unref (def
);
556 g_list_free_full (list
, g_object_unref
);
558 /* 4. set myapp4 as last used */
559 g_app_info_set_as_last_used_for_type (appinfo4
, contenttype
, &error
);
560 g_assert_no_error (error
);
562 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
563 list
= g_app_info_get_recommended_for_type (contenttype
);
564 g_assert (g_app_info_equal (def
, appinfo5
));
565 g_assert_cmpint (g_list_length (list
), ==, 2);
566 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo4
));
567 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo5
));
568 g_object_unref (def
);
569 g_list_free_full (list
, g_object_unref
);
571 /* 5. set myapp5 as last used again */
572 g_app_info_set_as_last_used_for_type (appinfo5
, contenttype
, &error
);
573 g_assert_no_error (error
);
575 def
= g_app_info_get_default_for_type (contenttype
, FALSE
);
576 list
= g_app_info_get_recommended_for_type (contenttype
);
577 g_assert (g_app_info_equal (def
, appinfo5
));
578 g_assert_cmpint (g_list_length (list
), ==, 2);
579 g_assert (g_app_info_equal ((GAppInfo
*)list
->data
, appinfo5
));
580 g_assert (g_app_info_equal ((GAppInfo
*)list
->next
->data
, appinfo4
));
581 g_object_unref (def
);
582 g_list_free_full (list
, g_object_unref
);
584 g_object_unref (appinfo4
);
585 g_object_unref (appinfo5
);
589 test_scheme_handler (void)
591 GAppInfo
*info
, *info5
;
593 info5
= (GAppInfo
*)g_desktop_app_info_new ("myapp5.desktop");
594 info
= g_app_info_get_default_for_uri_scheme ("ftp");
595 g_assert (g_app_info_equal (info
, info5
));
597 g_object_unref (info
);
598 g_object_unref (info5
);
601 /* test that g_app_info_* ignores desktop files with nonexisting executables
604 test_mime_ignore_nonexisting (void)
608 appinfo
= (GAppInfo
*)g_desktop_app_info_new ("nosuchapp.desktop");
609 g_assert (appinfo
== NULL
);
617 all
= g_app_info_get_all ();
619 for (l
= all
; l
; l
= l
->next
)
620 g_assert (G_IS_APP_INFO (l
->data
));
622 g_list_free_full (all
, g_object_unref
);
626 main (int argc
, char *argv
[])
628 g_test_init (&argc
, &argv
, NULL
);
632 g_test_add_func ("/appinfo/mime/api", test_mime_api
);
633 g_test_add_func ("/appinfo/mime/default", test_mime_default
);
634 g_test_add_func ("/appinfo/mime/file", test_mime_file
);
635 g_test_add_func ("/appinfo/mime/scheme-handler", test_scheme_handler
);
636 g_test_add_func ("/appinfo/mime/default-last-used", test_mime_default_last_used
);
637 g_test_add_func ("/appinfo/mime/ignore-nonexisting", test_mime_ignore_nonexisting
);
638 g_test_add_func ("/appinfo/all", test_all
);
640 return g_test_run ();