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 ();