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 =
60 const gchar *myapp4_data =
67 "MimeType=image/bmp;";
69 const gchar *myapp5_data =
76 "MimeType=image/bmp;x-scheme-handler/ftp;";
78 const gchar *nosuchapp_data =
83 "Exec=no_such_application %f\n"
86 const gchar *defaults_data =
87 "[Default Applications]\n"
88 "image/bmp=myapp4.desktop;\n"
89 "image/png=myapp3.desktop;\n"
90 "x-scheme-handler/ftp=myapp5.desktop;\n";
92 const gchar *mimecache_data =
94 "image/bmp=myapp4.desktop;myapp5.desktop;\n";
96 /* Set up XDG_DATA_HOME and XDG_DATA_DIRS.
97 * XDG_DATA_DIRS/applications will contain defaults.list
98 * XDG_DATA_HOME/applications will contain myapp.desktop
99 * and myapp2.desktop, and no mimeapps.list
112 GError *error = NULL;
114 dir = g_get_current_dir ();
115 xdgdatahome = g_build_filename (dir, "xdgdatahome", NULL);
116 xdgdatadir = g_build_filename (dir, "xdgdatadir", NULL);
117 g_test_message ("setting XDG_DATA_HOME to '%s'\n", xdgdatahome);
118 g_setenv ("XDG_DATA_HOME", xdgdatahome, TRUE);
119 g_test_message ("setting XDG_DATA_DIRS to '%s'\n", xdgdatadir);
120 g_setenv ("XDG_DATA_DIRS", xdgdatadir, TRUE);
122 appdir = g_build_filename (xdgdatadir, "applications", NULL);
123 g_test_message ("creating '%s'\n", appdir);
124 res = g_mkdir_with_parents (appdir, 0700);
127 name = g_build_filename (appdir, "defaults.list", NULL);
128 g_test_message ("creating '%s'\n", name);
129 g_file_set_contents (name, defaults_data, -1, &error);
130 g_assert_no_error (error);
133 apphome = g_build_filename (xdgdatahome, "applications", NULL);
134 g_test_message ("creating '%s'\n", apphome);
135 res = g_mkdir_with_parents (apphome, 0700);
138 name = g_build_filename (apphome, "myapp.desktop", NULL);
139 g_test_message ("creating '%s'\n", name);
140 g_file_set_contents (name, myapp_data, -1, &error);
141 g_assert_no_error (error);
144 name = g_build_filename (apphome, "myapp2.desktop", NULL);
145 g_test_message ("creating '%s'\n", name);
146 g_file_set_contents (name, myapp2_data, -1, &error);
147 g_assert_no_error (error);
150 name = g_build_filename (apphome, "myapp3.desktop", NULL);
151 g_test_message ("creating '%s'\n", name);
152 g_file_set_contents (name, myapp3_data, -1, &error);
153 g_assert_no_error (error);
156 name = g_build_filename (apphome, "myapp4.desktop", NULL);
157 g_test_message ("creating '%s'\n", name);
158 g_file_set_contents (name, myapp4_data, -1, &error);
159 g_assert_no_error (error);
162 name = g_build_filename (apphome, "myapp5.desktop", NULL);
163 g_test_message ("creating '%s'\n", name);
164 g_file_set_contents (name, myapp5_data, -1, &error);
165 g_assert_no_error (error);
168 name = g_build_filename (apphome, "nosuchapp.desktop", NULL);
169 g_test_message ("creating '%s'\n", name);
170 g_file_set_contents (name, nosuchapp_data, -1, &error);
171 g_assert_no_error (error);
174 mimeapps = g_build_filename (apphome, "mimeapps.list", NULL);
175 g_test_message ("removing '%s'\n", mimeapps);
178 name = g_build_filename (apphome, "mimeinfo.cache", NULL);
179 g_test_message ("creating '%s'\n", name);
180 g_file_set_contents (name, mimecache_data, -1, &error);
181 g_assert_no_error (error);
185 g_free (xdgdatahome);
197 GError *error = NULL;
200 const gchar *contenttype = "application/pdf";
202 /* clear things out */
203 g_app_info_reset_type_associations (contenttype);
205 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
206 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
208 def = g_app_info_get_default_for_type (contenttype, FALSE);
209 list = g_app_info_get_recommended_for_type (contenttype);
210 g_assert (def == NULL);
211 g_assert (list == NULL);
213 /* 1. add a non-default association */
214 g_app_info_add_supports_type (appinfo, contenttype, &error);
215 g_assert_no_error (error);
217 def = g_app_info_get_default_for_type (contenttype, FALSE);
218 list = g_app_info_get_recommended_for_type (contenttype);
219 g_assert (g_app_info_equal (def, appinfo));
220 g_assert_cmpint (g_list_length (list), ==, 1);
221 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
222 g_object_unref (def);
223 g_list_free_full (list, g_object_unref);
225 /* 2. add another non-default association */
226 g_app_info_add_supports_type (appinfo2, contenttype, &error);
227 g_assert_no_error (error);
229 def = g_app_info_get_default_for_type (contenttype, FALSE);
230 list = g_app_info_get_recommended_for_type (contenttype);
231 g_assert (g_app_info_equal (def, appinfo));
232 g_assert_cmpint (g_list_length (list), ==, 2);
233 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
234 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
235 g_object_unref (def);
236 g_list_free_full (list, g_object_unref);
238 /* 3. make the first app the default */
239 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
240 g_assert_no_error (error);
242 def = g_app_info_get_default_for_type (contenttype, FALSE);
243 list = g_app_info_get_recommended_for_type (contenttype);
244 g_assert (g_app_info_equal (def, appinfo));
245 g_assert_cmpint (g_list_length (list), ==, 2);
246 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
247 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
248 g_object_unref (def);
249 g_list_free_full (list, g_object_unref);
251 /* 4. make the second app the last used one */
252 g_app_info_set_as_last_used_for_type (appinfo2, contenttype, &error);
253 g_assert_no_error (error);
255 def = g_app_info_get_default_for_type (contenttype, FALSE);
256 list = g_app_info_get_recommended_for_type (contenttype);
257 g_assert (g_app_info_equal (def, appinfo));
258 g_assert_cmpint (g_list_length (list), ==, 2);
259 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo2));
260 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo));
261 g_object_unref (def);
262 g_list_free_full (list, g_object_unref);
264 /* 5. reset everything */
265 g_app_info_reset_type_associations (contenttype);
267 def = g_app_info_get_default_for_type (contenttype, FALSE);
268 list = g_app_info_get_recommended_for_type (contenttype);
269 g_assert (def == NULL);
270 g_assert (list == NULL);
272 g_object_unref (appinfo);
273 g_object_unref (appinfo2);
276 /* Repeat the same tests, this time checking that we handle
277 * mimeapps.list as expected. These tests are different from
278 * the ones in test_mime_api() in that we directly parse
279 * mimeapps.list to verify the results.
282 test_mime_file (void)
287 GError *error = NULL;
295 const gchar *contenttype = "application/pdf";
297 dir = g_get_current_dir ();
298 mimeapps = g_build_filename (dir, "xdgdatahome", "applications", "mimeapps.list", NULL);
300 /* clear things out */
301 g_app_info_reset_type_associations (contenttype);
303 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
304 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
306 def = g_app_info_get_default_for_type (contenttype, FALSE);
307 list = g_app_info_get_recommended_for_type (contenttype);
308 g_assert (def == NULL);
309 g_assert (list == NULL);
311 /* 1. add a non-default association */
312 g_app_info_add_supports_type (appinfo, contenttype, &error);
313 g_assert_no_error (error);
315 keyfile = g_key_file_new ();
316 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
317 g_assert_no_error (error);
319 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
320 g_assert_no_error (error);
321 g_assert (strv_equal (assoc, "myapp.desktop", NULL));
324 /* we've unset XDG_DATA_DIRS so there should be no default */
325 assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
326 g_assert (error != NULL);
327 g_clear_error (&error);
329 g_key_file_free (keyfile);
331 /* 2. add another non-default association */
332 g_app_info_add_supports_type (appinfo2, contenttype, &error);
333 g_assert_no_error (error);
335 keyfile = g_key_file_new ();
336 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
337 g_assert_no_error (error);
339 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
340 g_assert_no_error (error);
341 g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
344 assoc = g_key_file_get_string_list (keyfile, "Default Applications", contenttype, NULL, &error);
345 g_assert (error != NULL);
346 g_clear_error (&error);
348 g_key_file_free (keyfile);
350 /* 3. make the first app the default */
351 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
352 g_assert_no_error (error);
354 keyfile = g_key_file_new ();
355 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
356 g_assert_no_error (error);
358 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
359 g_assert_no_error (error);
360 g_assert (strv_equal (assoc, "myapp.desktop", "myapp2.desktop", NULL));
363 str = g_key_file_get_string (keyfile, "Default Applications", contenttype, &error);
364 g_assert_no_error (error);
365 g_assert_cmpstr (str, ==, "myapp.desktop");
368 g_key_file_free (keyfile);
370 /* 4. make the second app the last used one */
371 g_app_info_set_as_last_used_for_type (appinfo2, contenttype, &error);
372 g_assert_no_error (error);
374 keyfile = g_key_file_new ();
375 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
376 g_assert_no_error (error);
378 assoc = g_key_file_get_string_list (keyfile, "Added Associations", contenttype, NULL, &error);
379 g_assert_no_error (error);
380 g_assert (strv_equal (assoc, "myapp2.desktop", "myapp.desktop", NULL));
383 g_key_file_free (keyfile);
385 /* 5. reset everything */
386 g_app_info_reset_type_associations (contenttype);
388 keyfile = g_key_file_new ();
389 g_key_file_load_from_file (keyfile, mimeapps, G_KEY_FILE_NONE, &error);
390 g_assert_no_error (error);
392 res = g_key_file_has_key (keyfile, "Added Associations", contenttype, NULL);
395 res = g_key_file_has_key (keyfile, "Default Applications", contenttype, NULL);
398 g_key_file_free (keyfile);
400 g_object_unref (appinfo);
401 g_object_unref (appinfo2);
407 /* test interaction between defaults.list and mimeapps.list */
409 test_mime_default (void)
414 GError *error = NULL;
417 const gchar *contenttype = "image/png";
419 /* clear things out */
420 g_app_info_reset_type_associations (contenttype);
422 appinfo = (GAppInfo*)g_desktop_app_info_new ("myapp.desktop");
423 appinfo2 = (GAppInfo*)g_desktop_app_info_new ("myapp2.desktop");
424 appinfo3 = (GAppInfo*)g_desktop_app_info_new ("myapp3.desktop");
426 /* myapp3 is set as the default in defaults.list */
427 def = g_app_info_get_default_for_type (contenttype, FALSE);
428 list = g_app_info_get_recommended_for_type (contenttype);
429 g_assert (g_app_info_equal (def, appinfo3));
430 g_assert_cmpint (g_list_length (list), ==, 1);
431 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo3));
432 g_object_unref (def);
433 g_list_free_full (list, g_object_unref);
435 /* 1. add a non-default association */
436 g_app_info_add_supports_type (appinfo, contenttype, &error);
437 g_assert_no_error (error);
439 def = g_app_info_get_default_for_type (contenttype, FALSE);
440 list = g_app_info_get_recommended_for_type (contenttype);
441 g_assert (g_app_info_equal (def, appinfo3)); /* default is unaffected */
442 g_assert_cmpint (g_list_length (list), ==, 2);
443 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
444 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo3));
445 g_object_unref (def);
446 g_list_free_full (list, g_object_unref);
448 /* 2. add another non-default association */
449 g_app_info_add_supports_type (appinfo2, contenttype, &error);
450 g_assert_no_error (error);
452 def = g_app_info_get_default_for_type (contenttype, FALSE);
453 list = g_app_info_get_recommended_for_type (contenttype);
454 g_assert (g_app_info_equal (def, appinfo3));
455 g_assert_cmpint (g_list_length (list), ==, 3);
456 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
457 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
458 g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
459 g_object_unref (def);
460 g_list_free_full (list, g_object_unref);
462 /* 3. make the first app the default */
463 g_app_info_set_as_default_for_type (appinfo, contenttype, &error);
464 g_assert_no_error (error);
466 def = g_app_info_get_default_for_type (contenttype, FALSE);
467 list = g_app_info_get_recommended_for_type (contenttype);
468 g_assert (g_app_info_equal (def, appinfo));
469 g_assert_cmpint (g_list_length (list), ==, 3);
470 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo));
471 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo2));
472 g_assert (g_app_info_equal ((GAppInfo*)list->next->next->data, appinfo3));
473 g_object_unref (def);
474 g_list_free_full (list, g_object_unref);
476 g_object_unref (appinfo);
477 g_object_unref (appinfo2);
478 g_object_unref (appinfo3);
481 /* test interaction between mimeinfo.cache, defaults.list and mimeapps.list
482 * to ensure g_app_info_set_as_last_used_for_type doesn't incorrectly
486 test_mime_default_last_used (void)
490 GError *error = NULL;
493 const gchar *contenttype = "image/bmp";
495 /* clear things out */
496 g_app_info_reset_type_associations (contenttype);
498 appinfo4 = (GAppInfo*)g_desktop_app_info_new ("myapp4.desktop");
499 appinfo5 = (GAppInfo*)g_desktop_app_info_new ("myapp5.desktop");
501 /* myapp4 is set as the default in defaults.list */
502 /* myapp4 and myapp5 can both handle image/bmp */
503 def = g_app_info_get_default_for_type (contenttype, FALSE);
504 list = g_app_info_get_recommended_for_type (contenttype);
505 g_assert (g_app_info_equal (def, appinfo4));
506 g_assert_cmpint (g_list_length (list), ==, 2);
507 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
508 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
509 g_object_unref (def);
510 g_list_free_full (list, g_object_unref);
512 /* 1. set default (myapp4) as last used */
513 g_app_info_set_as_last_used_for_type (appinfo4, contenttype, &error);
514 g_assert_no_error (error);
516 def = g_app_info_get_default_for_type (contenttype, FALSE);
517 list = g_app_info_get_recommended_for_type (contenttype);
518 g_assert (g_app_info_equal (def, appinfo4)); /* default is unaffected */
519 g_assert_cmpint (g_list_length (list), ==, 2);
520 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
521 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
522 g_object_unref (def);
523 g_list_free_full (list, g_object_unref);
525 /* 2. set other (myapp5) as last used */
526 g_app_info_set_as_last_used_for_type (appinfo5, contenttype, &error);
527 g_assert_no_error (error);
529 def = g_app_info_get_default_for_type (contenttype, FALSE);
530 list = g_app_info_get_recommended_for_type (contenttype);
531 g_assert (g_app_info_equal (def, appinfo4));
532 g_assert_cmpint (g_list_length (list), ==, 2);
533 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
534 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
535 g_object_unref (def);
536 g_list_free_full (list, g_object_unref);
538 /* 3. change the default to myapp5 */
539 g_app_info_set_as_default_for_type (appinfo5, contenttype, &error);
540 g_assert_no_error (error);
542 def = g_app_info_get_default_for_type (contenttype, FALSE);
543 list = g_app_info_get_recommended_for_type (contenttype);
544 g_assert (g_app_info_equal (def, appinfo5));
545 g_assert_cmpint (g_list_length (list), ==, 2);
546 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
547 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
548 g_object_unref (def);
549 g_list_free_full (list, g_object_unref);
551 /* 4. set myapp4 as last used */
552 g_app_info_set_as_last_used_for_type (appinfo4, contenttype, &error);
553 g_assert_no_error (error);
555 def = g_app_info_get_default_for_type (contenttype, FALSE);
556 list = g_app_info_get_recommended_for_type (contenttype);
557 g_assert (g_app_info_equal (def, appinfo5));
558 g_assert_cmpint (g_list_length (list), ==, 2);
559 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo4));
560 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo5));
561 g_object_unref (def);
562 g_list_free_full (list, g_object_unref);
564 /* 5. set myapp5 as last used again */
565 g_app_info_set_as_last_used_for_type (appinfo5, contenttype, &error);
566 g_assert_no_error (error);
568 def = g_app_info_get_default_for_type (contenttype, FALSE);
569 list = g_app_info_get_recommended_for_type (contenttype);
570 g_assert (g_app_info_equal (def, appinfo5));
571 g_assert_cmpint (g_list_length (list), ==, 2);
572 g_assert (g_app_info_equal ((GAppInfo*)list->data, appinfo5));
573 g_assert (g_app_info_equal ((GAppInfo*)list->next->data, appinfo4));
574 g_object_unref (def);
575 g_list_free_full (list, g_object_unref);
577 g_object_unref (appinfo4);
578 g_object_unref (appinfo5);
582 test_scheme_handler (void)
584 GAppInfo *info, *info5;
586 info5 = (GAppInfo*)g_desktop_app_info_new ("myapp5.desktop");
587 info = g_app_info_get_default_for_uri_scheme ("ftp");
588 g_assert (g_app_info_equal (info, info5));
590 g_object_unref (info);
591 g_object_unref (info5);
594 /* test that g_app_info_* ignores desktop files with nonexisting executables
597 test_mime_ignore_nonexisting (void)
601 appinfo = (GAppInfo*)g_desktop_app_info_new ("nosuchapp.desktop");
602 g_assert (appinfo == NULL);
610 all = g_app_info_get_all ();
612 for (l = all; l; l = l->next)
613 g_assert (G_IS_APP_INFO (l->data));
615 g_list_free_full (all, g_object_unref);
619 main (int argc, char *argv[])
621 g_test_init (&argc, &argv, NULL);
625 g_test_add_func ("/appinfo/mime/api", test_mime_api);
626 g_test_add_func ("/appinfo/mime/default", test_mime_default);
627 g_test_add_func ("/appinfo/mime/file", test_mime_file);
628 g_test_add_func ("/appinfo/mime/scheme-handler", test_scheme_handler);
629 g_test_add_func ("/appinfo/mime/default-last-used", test_mime_default_last_used);
630 g_test_add_func ("/appinfo/mime/ignore-nonexisting", test_mime_ignore_nonexisting);
631 g_test_add_func ("/appinfo/all", test_all);
633 return g_test_run ();