[glib: 22/24] GAppInfo: Make g_app_info_launch_default_for_uri_async fully async




commit 8a880e1379785de06da34adee7ca1355ead3bdb1
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Thu Jun 2 00:24:25 2022 +0200

    GAppInfo: Make g_app_info_launch_default_for_uri_async fully async
    
    Despite the name, we still used blocking calls to get the default app
    for URI, now that we have an async implementation of the API to get the
    default implementation for URI scheme, we can remove the blocking calls.

 gio/gappinfo.c               |  65 +++++++++++++++++++++-------
 gio/tests/desktop-app-info.c | 101 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 150 insertions(+), 16 deletions(-)
---
diff --git a/gio/gappinfo.c b/gio/gappinfo.c
index 286b0bdbab..f1e866ddaa 100644
--- a/gio/gappinfo.c
+++ b/gio/gappinfo.c
@@ -1148,6 +1148,46 @@ launch_default_for_uri_default_handler_cb (GObject      *object,
     launch_default_for_uri_portal_open_uri (g_steal_pointer (&task), g_steal_pointer (&error));
 }
 
+static void
+launch_default_app_for_default_handler (GTask *task)
+{
+  GFile *file;
+  GCancellable *cancellable;
+  LaunchDefaultForUriData *data;
+
+  data = g_task_get_task_data (task);
+  cancellable = g_task_get_cancellable (task);
+  file = g_file_new_for_uri (data->uri);
+
+  g_file_query_default_handler_async (file,
+                                      G_PRIORITY_DEFAULT,
+                                      cancellable,
+                                      launch_default_for_uri_default_handler_cb,
+                                      g_steal_pointer (&task));
+  g_object_unref (file);
+}
+
+static void
+launch_default_app_for_uri_cb (GObject      *object,
+                               GAsyncResult *result,
+                               gpointer      user_data)
+{
+  GTask *task = G_TASK (user_data);
+  GAppInfo *app_info;
+
+  app_info = g_app_info_get_default_for_uri_scheme_finish (result, NULL);
+
+  if (!app_info)
+    {
+      launch_default_app_for_default_handler (g_steal_pointer (&task));
+    }
+  else
+    {
+      launch_default_for_uri_launch_uris (g_steal_pointer (&task),
+                                          g_steal_pointer (&app_info));
+    }
+}
+
 /**
  * g_app_info_launch_default_for_uri_async:
  * @uri: the uri to show
@@ -1178,7 +1218,6 @@ g_app_info_launch_default_for_uri_async (const char          *uri,
 {
   GTask *task;
   char *uri_scheme;
-  GAppInfo *app_info = NULL;
   LaunchDefaultForUriData *data;
 
   g_return_if_fail (uri != NULL);
@@ -1197,24 +1236,18 @@ g_app_info_launch_default_for_uri_async (const char          *uri,
    */
   uri_scheme = g_uri_parse_scheme (uri);
   if (uri_scheme && uri_scheme[0] != '\0')
-    /* FIXME: The following still uses blocking calls. */
-    app_info = g_app_info_get_default_for_uri_scheme (uri_scheme);
-  g_free (uri_scheme);
-
-  if (!app_info)
     {
-      GFile *file;
-
-      file = g_file_new_for_uri (uri);
-      g_file_query_default_handler_async (file,
-                                          G_PRIORITY_DEFAULT,
-                                          cancellable,
-                                          launch_default_for_uri_default_handler_cb,
-                                          g_steal_pointer (&task));
-      g_object_unref (file);
+      g_app_info_get_default_for_uri_scheme_async (uri_scheme,
+                                                   cancellable,
+                                                   launch_default_app_for_uri_cb,
+                                                   g_steal_pointer (&task));
     }
   else
-    launch_default_for_uri_launch_uris (g_steal_pointer (&task), g_steal_pointer (&app_info));
+    {
+      launch_default_app_for_default_handler (g_steal_pointer (&task));
+    }
+
+  g_free (uri_scheme);
 }
 
 /**
diff --git a/gio/tests/desktop-app-info.c b/gio/tests/desktop-app-info.c
index 05b45c6462..2bcdba7cf0 100644
--- a/gio/tests/desktop-app-info.c
+++ b/gio/tests/desktop-app-info.c
@@ -1053,6 +1053,106 @@ test_default_uri_handler (void)
   g_free (file_path);
 }
 
+static void
+on_launch_default_for_uri_success_cb (GObject      *object,
+                                      GAsyncResult *result,
+                                      gpointer      user_data)
+{
+  GError *error = NULL;
+  gboolean *called = user_data;
+
+  g_assert_true (g_app_info_launch_default_for_uri_finish (result, &error));
+  g_assert_no_error (error);
+
+  *called = TRUE;
+}
+
+static void
+on_launch_default_for_uri_not_found_cb (GObject      *object,
+                                        GAsyncResult *result,
+                                        gpointer      user_data)
+{
+  GError *error = NULL;
+  GMainLoop *loop = user_data;
+
+  g_assert_false (g_app_info_launch_default_for_uri_finish (result, &error));
+  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED);
+  g_clear_error (&error);
+
+  g_main_loop_quit (loop);
+}
+
+static void
+on_launch_default_for_uri_cancelled_cb (GObject      *object,
+                                        GAsyncResult *result,
+                                        gpointer      user_data)
+{
+  GError *error = NULL;
+  GMainLoop *loop = user_data;
+
+  g_assert_false (g_app_info_launch_default_for_uri_finish (result, &error));
+  g_assert_error (error, G_IO_ERROR, G_IO_ERROR_CANCELLED);
+  g_clear_error (&error);
+
+  g_main_loop_quit (loop);
+}
+
+static void
+test_default_uri_handler_async (void)
+{
+  GCancellable *cancellable;
+  gchar *file_path = NULL;
+  GAppInfo *info;
+  GMainLoop *loop;
+  gboolean called = FALSE;
+
+  loop = g_main_loop_new (NULL, FALSE);
+  info = create_app_info_toucher ("Touch Handled", "handled-async",
+                                  "x-scheme-handler/glib-async-touch",
+                                  &file_path);
+  g_assert_true (G_IS_APP_INFO (info));
+  g_assert_nonnull (file_path);
+
+  g_app_info_launch_default_for_uri_async ("glib-async-touch://touch-me", NULL,
+                                           NULL,
+                                           on_launch_default_for_uri_success_cb,
+                                           &called);
+
+  while (!g_file_test (file_path, G_FILE_TEST_IS_REGULAR))
+    g_main_context_iteration (NULL, FALSE);
+
+  g_assert_true (called);
+  g_assert_true (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
+
+  g_unlink (file_path);
+  g_assert_false (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
+
+  g_app_info_launch_default_for_uri_async ("glib-async-INVALID-touch://touch-me",
+                                           NULL, NULL,
+                                           on_launch_default_for_uri_not_found_cb,
+                                           loop);
+  g_main_loop_run (loop);
+
+  cancellable = g_cancellable_new ();
+  g_app_info_launch_default_for_uri_async ("glib-async-touch://touch-me", NULL,
+                                           cancellable,
+                                           on_launch_default_for_uri_cancelled_cb,
+                                           loop);
+  g_cancellable_cancel (cancellable);
+  g_main_loop_run (loop);
+
+  /* Once started our touch app may take some time before having written the
+   * file, so let's wait a bit here before ensuring that the file has been
+   * created as expected.
+   */
+  g_usleep (G_USEC_PER_SEC / 10);
+  g_assert_false (g_file_test (file_path, G_FILE_TEST_IS_REGULAR));
+
+  g_object_unref (info);
+  g_main_loop_unref (loop);
+  g_free (file_path);
+}
+
 /* Test if Desktop-File Id is correctly formed */
 static void
 test_id (void)
@@ -1088,6 +1188,7 @@ main (int   argc,
   g_test_add_func ("/desktop-app-info/show-in", test_show_in);
   g_test_add_func ("/desktop-app-info/launch-as-manager", test_launch_as_manager);
   g_test_add_func ("/desktop-app-info/launch-default-uri-handler", test_default_uri_handler);
+  g_test_add_func ("/desktop-app-info/launch-default-uri-handler-async", test_default_uri_handler_async);
   g_test_add_func ("/desktop-app-info/id", test_id);
 
   return g_test_run ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]