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 defaults.list
100 * XDG_DATA_HOME/applications will contain myapp.desktop
101 * and myapp2.desktop, and no mimeapps.list
114 GError *error = NULL;
116 dir = g_get_current_dir ();
117 xdgdatahome = g_build_filename (dir, "xdgdatahome", NULL);
118 xdgdatadir = g_build_filename (dir, "xdgdatadir", NULL);
119 g_test_message ("setting XDG_DATA_HOME to '%s'\n", xdgdatahome);
120 g_setenv ("XDG_DATA_HOME", xdgdatahome, TRUE);
121 g_test_message ("setting XDG_DATA_DIRS to '%s'\n", xdgdatadir);
122 g_setenv ("XDG_DATA_DIRS", xdgdatadir, TRUE);
124 appdir = g_build_filename (xdgdatadir, "applications", NULL);
125 g_test_message ("creating '%s'\n", appdir);
126 res = g_mkdir_with_parents (appdir, 0700);
129 name = g_build_filename (appdir, "defaults.list", NULL);
130 g_test_message ("creating '%s'\n", name);
131 g_file_set_contents (name, defaults_data, -1, &error);
132 g_assert_no_error (error);
135 apphome = g_build_filename (xdgdatahome, "applications", NULL);
136 g_test_message ("creating '%s'\n", apphome);
137 res = g_mkdir_with_parents (apphome, 0700);
140 name = g_build_filename (apphome, "myapp.desktop", NULL);
141 g_test_message ("creating '%s'\n", name);
142 g_file_set_contents (name, myapp_data, -1, &error);
143 g_assert_no_error (error);
146 name = g_build_filename (apphome, "myapp2.desktop", NULL);
147 g_test_message ("creating '%s'\n", name);
148 g_file_set_contents (name, myapp2_data, -1, &error);
149 g_assert_no_error (error);
152 name = g_build_filename (apphome, "myapp3.desktop", NULL);
153 g_test_message ("creating '%s'\n", name);
154 g_file_set_contents (name, myapp3_data, -1, &error);
155 g_assert_no_error (error);
158 name = g_build_filename (apphome, "myapp4.desktop", NULL);
159 g_test_message ("creating '%s'\n", name);
160 g_file_set_contents (name, myapp4_data, -1, &error);
161 g_assert_no_error (error);
164 name = g_build_filename (apphome, "myapp5.desktop", NULL);
165 g_test_message ("creating '%s'\n", name);
166 g_file_set_contents (name, myapp5_data, -1, &error);
167 g_assert_no_error (error);
170 name = g_build_filename (apphome, "nosuchapp.desktop", NULL);
171 g_test_message ("creating '%s'\n", name);
172 g_file_set_contents (name, nosuchapp_data, -1, &error);
173 g_assert_no_error (error);
176 mimeapps = g_build_filename (apphome, "mimeapps.list", NULL);
177 g_test_message ("removing '%s'\n", mimeapps);
180 name = g_build_filename (apphome, "mimeinfo.cache", NULL);
181 g_test_message ("creating '%s'\n", name);
182 g_file_set_contents (name, mimecache_data, -1, &error);
183 g_assert_no_error (error);
187 g_free (xdgdatahome);
199 GError *error = NULL;
202 const gchar *contenttype = "application/pdf";
204 /* clear things out */
205 g_app_info_reset_type_associations (contenttype);
207 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
208 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
210 def = g_app_info_get_default_for_type (contenttype, FALSE);
211 list = g_app_info_get_recommended_for_type (contenttype);
212 g_assert (def == NULL);
213 g_assert (list == NULL);
215 /* 1. add a non-default association */
216 g_app_info_add_supports_type (appinfo, contenttype, &error);
217 g_assert_no_error (error);
219 def = g_app_info_get_default_for_type (contenttype, FALSE);
220 list = g_app_info_get_recommended_for_type (contenttype);
221 g_assert (g_app_info_equal (def, appinfo));
222 g_assert_cmpint (g_list_length (list), ==, 1);
223 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
224 g_object_unref (def);
225 g_list_free_full (list, g_object_unref);
227 /* 2. add another non-default association */
228 g_app_info_add_supports_type (appinfo2, contenttype, &error);
229 g_assert_no_error (error);
231 def = g_app_info_get_default_for_type (contenttype, FALSE);
232 list = g_app_info_get_recommended_for_type (contenttype);
233 g_assert (g_app_info_equal (def, appinfo));
234 g_assert_cmpint (g_list_length (list), ==, 2);
235 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
236 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
237 g_object_unref (def);
238 g_list_free_full (list, g_object_unref);
240 /* 3. make the first app the default */
241 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
242 g_assert_no_error (error);
244 def = g_app_info_get_default_for_type (contenttype, FALSE);
245 list = g_app_info_get_recommended_for_type (contenttype);
246 g_assert (g_app_info_equal (def, appinfo));
247 g_assert_cmpint (g_list_length (list), ==, 2);
248 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
249 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
250 g_object_unref (def);
251 g_list_free_full (list, g_object_unref);
253 /* 4. make the second app the last used one */
254 g_app_info_set_as_last_used_for_type (appinfo2, contenttype, &error);
255 g_assert_no_error (error);
257 def = g_app_info_get_default_for_type (contenttype, FALSE);
258 list = g_app_info_get_recommended_for_type (contenttype);
259 g_assert (g_app_info_equal (def, appinfo));
260 g_assert_cmpint (g_list_length (list), ==, 2);
261 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo2));
262 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo));
263 g_object_unref (def);
264 g_list_free_full (list, g_object_unref);
266 /* 5. reset everything */
267 g_app_info_reset_type_associations (contenttype);
269 def = g_app_info_get_default_for_type (contenttype, FALSE);
270 list = g_app_info_get_recommended_for_type (contenttype);
271 g_assert (def == NULL);
272 g_assert (list == NULL);
274 g_object_unref (appinfo);
275 g_object_unref (appinfo2);
278 /* Repeat the same tests, this time checking that we handle
279 * mimeapps.list as expected. These tests are different from
280 * the ones in test_mime_api() in that we directly parse
281 * mimeapps.list to verify the results.
284 test_mime_file (void)
289 GError *error = NULL;
297 const gchar *contenttype = "application/pdf";
299 dir = g_get_current_dir ();
300 mimeapps = g_build_filename (dir, "xdgdatahome", "applications", "mimeapps.list", NULL);
302 /* clear things out */
303 g_app_info_reset_type_associations (contenttype);
305 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
306 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
308 def = g_app_info_get_default_for_type (contenttype, FALSE);
309 list = g_app_info_get_recommended_for_type (contenttype);
310 g_assert (def == NULL);
311 g_assert (list == NULL);
313 /* 1. add a non-default association */
314 g_app_info_add_supports_type (appinfo, contenttype, &error);
315 g_assert_no_error (error);
317 keyfile = g_key_file_new ();
318 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
319 g_assert_no_error (error);
321 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
322 g_assert_no_error (error);
323 g_assert (strv_equal (assoc, "myapp.desktop", NULL));
326 /* we've unset XDG_DATA_DIRS so there should be no default */
327 assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
328 g_assert (error != NULL);
329 g_clear_error (&error);
331 g_key_file_free (keyfile);
333 /* 2. add another non-default association */
334 g_app_info_add_supports_type (appinfo2, contenttype, &error);
335 g_assert_no_error (error);
337 keyfile = g_key_file_new ();
338 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
339 g_assert_no_error (error);
341 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
342 g_assert_no_error (error);
343 g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
346 assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
347 g_assert (error != NULL);
348 g_clear_error (&error);
350 g_key_file_free (keyfile);
352 /* 3. make the first app the default */
353 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
354 g_assert_no_error (error);
356 keyfile = g_key_file_new ();
357 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
358 g_assert_no_error (error);
360 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
361 g_assert_no_error (error);
362 g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
365 str = g_key_file_get_string (keyfile, "Default Applications", contenttype, &error);
366 g_assert_no_error (error);
367 g_assert_cmpstr (str, ==, "myapp.desktop");
370 g_key_file_free (keyfile);
372 /* 4. make the second app the last used one */
373 g_app_info_set_as_last_used_for_type (appinfo2, contenttype, &error);
374 g_assert_no_error (error);
376 keyfile = g_key_file_new ();
377 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
378 g_assert_no_error (error);
380 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
381 g_assert_no_error (error);
382 g_assert (strv_equal (assoc, "myapp2.desktop", "myapp.desktop", NULL));
385 g_key_file_free (keyfile);
387 /* 5. reset everything */
388 g_app_info_reset_type_associations (contenttype);
390 keyfile = g_key_file_new ();
391 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
392 g_assert_no_error (error);
394 res = g_key_file_has_key (keyfile, "Added Associations", contenttype, NULL);
397 res = g_key_file_has_key (keyfile, "Default Applications", contenttype, NULL);
400 g_key_file_free (keyfile);
402 g_object_unref (appinfo);
403 g_object_unref (appinfo2);
409 /* test interaction between defaults.list and mimeapps.list */
411 test_mime_default (void)
416 GError *error = NULL;
419 const gchar *contenttype = "image/png";
421 /* clear things out */
422 g_app_info_reset_type_associations (contenttype);
424 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
425 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
426 appinfo3 = (GAppInfo*)g_desktop_app_info_new ("myapp3.desktop");
428 /* myapp3 is set as the default in defaults.list */
429 def = g_app_info_get_default_for_type (contenttype, FALSE);
430 list = g_app_info_get_recommended_for_type (contenttype);
431 g_assert (g_app_info_equal (def, appinfo3));
432 g_assert_cmpint (g_list_length (list), ==, 1);
433 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo3));
434 g_object_unref (def);
435 g_list_free_full (list, g_object_unref);
437 /* 1. add a non-default association */
438 g_app_info_add_supports_type (appinfo, contenttype, &error);
439 g_assert_no_error (error);
441 def = g_app_info_get_default_for_type (contenttype, FALSE);
442 list = g_app_info_get_recommended_for_type (contenttype);
443 g_assert (g_app_info_equal (def, appinfo3)); /* default is unaffected */
444 g_assert_cmpint (g_list_length (list), ==, 2);
445 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
446 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo3));
447 g_object_unref (def);
448 g_list_free_full (list, g_object_unref);
450 /* 2. add another non-default association */
451 g_app_info_add_supports_type (appinfo2, contenttype, &error);
452 g_assert_no_error (error);
454 def = g_app_info_get_default_for_type (contenttype, FALSE);
455 list = g_app_info_get_recommended_for_type (contenttype);
456 g_assert (g_app_info_equal (def, appinfo3));
457 g_assert_cmpint (g_list_length (list), ==, 3);
458 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
459 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
460 g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
461 g_object_unref (def);
462 g_list_free_full (list, g_object_unref);
464 /* 3. make the first app the default */
465 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
466 g_assert_no_error (error);
468 def = g_app_info_get_default_for_type (contenttype, FALSE);
469 list = g_app_info_get_recommended_for_type (contenttype);
470 g_assert (g_app_info_equal (def, appinfo));
471 g_assert_cmpint (g_list_length (list), ==, 3);
472 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
473 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
474 g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
475 g_object_unref (def);
476 g_list_free_full (list, g_object_unref);
478 g_object_unref (appinfo);
479 g_object_unref (appinfo2);
480 g_object_unref (appinfo3);
483 /* test interaction between mimeinfo.cache, defaults.list and mimeapps.list
484 * to ensure g_app_info_set_as_last_used_for_type doesn't incorrectly
488 test_mime_default_last_used (void)
492 GError *error = NULL;
495 const gchar *contenttype = "image/bmp";
497 /* clear things out */
498 g_app_info_reset_type_associations (contenttype);
500 appinfo4 = (GAppInfo*)g_desktop_app_info_new ("myapp4.desktop");
501 appinfo5 = (GAppInfo*)g_desktop_app_info_new ("myapp5.desktop");
503 /* myapp4 is set as the default in defaults.list */
504 /* myapp4 and myapp5 can both handle image/bmp */
505 def = g_app_info_get_default_for_type (contenttype, FALSE);
506 list = g_app_info_get_recommended_for_type (contenttype);
507 g_assert (g_app_info_equal (def, appinfo4));
508 g_assert_cmpint (g_list_length (list), ==, 2);
509 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
510 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
511 g_object_unref (def);
512 g_list_free_full (list, g_object_unref);
514 /* 1. set default (myapp4) as last used */
515 g_app_info_set_as_last_used_for_type (appinfo4, contenttype, &error);
516 g_assert_no_error (error);
518 def = g_app_info_get_default_for_type (contenttype, FALSE);
519 list = g_app_info_get_recommended_for_type (contenttype);
520 g_assert (g_app_info_equal (def, appinfo4)); /* default is unaffected */
521 g_assert_cmpint (g_list_length (list), ==, 2);
522 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
523 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
524 g_object_unref (def);
525 g_list_free_full (list, g_object_unref);
527 /* 2. set other (myapp5) as last used */
528 g_app_info_set_as_last_used_for_type (appinfo5, contenttype, &error);
529 g_assert_no_error (error);
531 def = g_app_info_get_default_for_type (contenttype, FALSE);
532 list = g_app_info_get_recommended_for_type (contenttype);
533 g_assert (g_app_info_equal (def, appinfo4));
534 g_assert_cmpint (g_list_length (list), ==, 2);
535 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
536 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
537 g_object_unref (def);
538 g_list_free_full (list, g_object_unref);
540 /* 3. change the default to myapp5 */
541 g_app_info_set_as_default_for_type (appinfo5, contenttype, &error);
542 g_assert_no_error (error);
544 def = g_app_info_get_default_for_type (contenttype, FALSE);
545 list = g_app_info_get_recommended_for_type (contenttype);
546 g_assert (g_app_info_equal (def, appinfo5));
547 g_assert_cmpint (g_list_length (list), ==, 2);
548 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
549 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
550 g_object_unref (def);
551 g_list_free_full (list, g_object_unref);
553 /* 4. set myapp4 as last used */
554 g_app_info_set_as_last_used_for_type (appinfo4, contenttype, &error);
555 g_assert_no_error (error);
557 def = g_app_info_get_default_for_type (contenttype, FALSE);
558 list = g_app_info_get_recommended_for_type (contenttype);
559 g_assert (g_app_info_equal (def, appinfo5));
560 g_assert_cmpint (g_list_length (list), ==, 2);
561 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
562 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
563 g_object_unref (def);
564 g_list_free_full (list, g_object_unref);
566 /* 5. set myapp5 as last used again */
567 g_app_info_set_as_last_used_for_type (appinfo5, contenttype, &error);
568 g_assert_no_error (error);
570 def = g_app_info_get_default_for_type (contenttype, FALSE);
571 list = g_app_info_get_recommended_for_type (contenttype);
572 g_assert (g_app_info_equal (def, appinfo5));
573 g_assert_cmpint (g_list_length (list), ==, 2);
574 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
575 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
576 g_object_unref (def);
577 g_list_free_full (list, g_object_unref);
579 g_object_unref (appinfo4);
580 g_object_unref (appinfo5);
584 test_scheme_handler (void)
586 GAppInfo *info, *info5;
588 info5 = (GAppInfo*)g_desktop_app_info_new ("myapp5.desktop");
589 info = g_app_info_get_default_for_uri_scheme ("ftp");
590 g_assert (g_app_info_equal (info, info5));
592 g_object_unref (info);
593 g_object_unref (info5);
596 /* test that g_app_info_* ignores desktop files with nonexisting executables
599 test_mime_ignore_nonexisting (void)
603 appinfo = (GAppInfo*)g_desktop_app_info_new ("nosuchapp.desktop");
604 g_assert (appinfo == NULL);
612 all = g_app_info_get_all ();
614 for (l = all; l; l = l->next)
615 g_assert (G_IS_APP_INFO (l->data));
617 g_list_free_full (all, g_object_unref);
621 main (int argc, char *argv[])
623 g_test_init (&argc, &argv, NULL);
627 g_test_add_func ("/appinfo/mime/api", test_mime_api);
628 g_test_add_func ("/appinfo/mime/default", test_mime_default);
629 g_test_add_func ("/appinfo/mime/file", test_mime_file);
630 g_test_add_func ("/appinfo/mime/scheme-handler", test_scheme_handler);
631 g_test_add_func ("/appinfo/mime/default-last-used", test_mime_default_last_used);
632 g_test_add_func ("/appinfo/mime/ignore-nonexisting", test_mime_ignore_nonexisting);
633 g_test_add_func ("/appinfo/all", test_all);
635 return g_test_run ();