[glib/wip/oholy/gappinfo-async: 2/5] gfile: Add g_file_query_default_handler_async()



commit f83e9d4bade2c7ee7d994163bd961018bb9c1984
Author: Ondrej Holy <oholy redhat com>
Date:   Tue Jan 22 15:37:44 2019 +0100

    gfile: Add g_file_query_default_handler_async()
    
    This is needed as a first step to fix the
    g_app_info_launch_default_for_uri_async() function to be really
    asynchronous.
    
    It still uses the g_app_info_get_default_for_uri_scheme() and
    g_app_info_get_default_for_type() functions, which may use synchronous
    calls to local MIME DB.
    
    https://gitlab.gnome.org/GNOME/glib/issues/1347
    https://gitlab.gnome.org/GNOME/glib/issues/1249

 docs/reference/gio/gio-sections.txt |   2 +
 gio/gfile.c                         | 123 ++++++++++++++++++++++++++++++++++++
 gio/gfile.h                         |  11 ++++
 3 files changed, 136 insertions(+)
---
diff --git a/docs/reference/gio/gio-sections.txt b/docs/reference/gio/gio-sections.txt
index 1fe37e488..ea53d2624 100644
--- a/docs/reference/gio/gio-sections.txt
+++ b/docs/reference/gio/gio-sections.txt
@@ -125,6 +125,8 @@ g_file_query_filesystem_info
 g_file_query_filesystem_info_async
 g_file_query_filesystem_info_finish
 g_file_query_default_handler
+g_file_query_default_handler_async
+g_file_query_default_handler_finish
 g_file_measure_disk_usage
 g_file_measure_disk_usage_async
 g_file_measure_disk_usage_finish
diff --git a/gio/gfile.c b/gio/gfile.c
index e6b468b55..c7926478c 100644
--- a/gio/gfile.c
+++ b/gio/gfile.c
@@ -6885,6 +6885,129 @@ g_file_query_default_handler (GFile         *file,
   return NULL;
 }
 
+static void
+query_default_handler_query_info_cb (GObject      *object,
+                                     GAsyncResult *result,
+                                     gpointer      user_data)
+{
+  GFile *file = G_FILE (object);
+  GTask *task = G_TASK (user_data);
+  GError *error = NULL;
+  GFileInfo *info;
+  const char *content_type;
+  GAppInfo *appinfo = NULL;
+
+  info = g_file_query_info_finish (file, result, &error);
+  if (info == NULL)
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      g_object_unref (task);
+      return;
+    }
+
+  content_type = g_file_info_get_content_type (info);
+  if (content_type)
+    {
+      char *path;
+
+      /* Don't use is_native(), as we want to support fuse paths if available */
+      path = g_file_get_path (file);
+
+      /* FIXME: The following still uses blocking calls. */
+      appinfo = g_app_info_get_default_for_type (content_type,
+                                                 path == NULL);
+      g_free (path);
+    }
+
+  g_object_unref (info);
+
+  if (appinfo != NULL)
+    g_task_return_pointer (task, g_steal_pointer (&appinfo), g_object_unref);
+  else
+    g_task_return_new_error (task,
+                             G_IO_ERROR,
+                             G_IO_ERROR_NOT_SUPPORTED,
+                             _("No application is registered as handling this file"));
+  g_object_unref (task);
+}
+
+/**
+ * g_file_query_default_handler_async:
+ * @file: a #GFile to open
+ * @cancellable: optional #GCancellable object, %NULL to ignore
+ * @callback: (nullable): a #GAsyncReadyCallback to call when the request is done
+ * @user_data: (nullable): data to pass to @callback
+ *
+ * Async version of g_file_query_default_handler().
+ *
+ * Since: 2.60
+ */
+void
+g_file_query_default_handler_async (GFile              *file,
+                                    int                 io_priority,
+                                    GCancellable       *cancellable,
+                                    GAsyncReadyCallback callback,
+                                    gpointer            user_data)
+{
+  GTask *task;
+  char *uri_scheme;
+
+  task = g_task_new (file, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_file_query_default_handler_async);
+
+  uri_scheme = g_file_get_uri_scheme (file);
+  if (uri_scheme && uri_scheme[0] != '\0')
+    {
+      GAppInfo *appinfo;
+
+      /* FIXME: The following still uses blocking calls. */
+      appinfo = g_app_info_get_default_for_uri_scheme (uri_scheme);
+      g_free (uri_scheme);
+
+      if (appinfo != NULL)
+        {
+          g_task_return_pointer (task, g_steal_pointer (&appinfo), g_object_unref);
+          g_object_unref (task);
+          return;
+        }
+    }
+  else
+    g_free (uri_scheme);
+
+  g_file_query_info_async (file,
+                           G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+                           0,
+                           io_priority,
+                           cancellable,
+                           query_default_handler_query_info_cb,
+                           g_steal_pointer (&task));
+}
+
+/**
+ * g_file_query_default_handler_finish:
+ * @file: a #GFile to open
+ * @result: a #GAsyncResult
+ * @error: (nullable): a #GError
+ *
+ * Finishes g_file_query_default_handler_async() operation.
+ *
+ * Returns: (transfer full): a #GAppInfo if the handle was found,
+ *     %NULL if there were errors.
+ *     When you are done with it, release it with g_object_unref()
+ *
+ * Since: 2.60
+ */
+GAppInfo *
+g_file_query_default_handler_finish (GFile        *file,
+                                     GAsyncResult *result,
+                                     GError      **error)
+{
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+  g_return_val_if_fail (g_task_is_valid (result, file), NULL);
+
+  return g_task_propagate_pointer (G_TASK (result), error);
+}
+
 #define GET_CONTENT_BLOCK_SIZE 8192
 
 /**
diff --git a/gio/gfile.h b/gio/gfile.h
index 4aff644c3..6e25b0de0 100644
--- a/gio/gfile.h
+++ b/gio/gfile.h
@@ -1183,6 +1183,17 @@ GLIB_AVAILABLE_IN_ALL
 GAppInfo *g_file_query_default_handler       (GFile                  *file,
                                              GCancellable           *cancellable,
                                              GError                **error);
+GLIB_AVAILABLE_IN_2_60
+void      g_file_query_default_handler_async (GFile                  *file,
+                                              int                     io_priority,
+                                              GCancellable           *cancellable,
+                                              GAsyncReadyCallback     callback,
+                                              gpointer                user_data);
+GLIB_AVAILABLE_IN_2_60
+GAppInfo *g_file_query_default_handler_finish (GFile                 *file,
+                                               GAsyncResult          *result,
+                                               GError               **error);
+
 GLIB_AVAILABLE_IN_ALL
 gboolean g_file_load_contents                (GFile                  *file,
                                              GCancellable           *cancellable,


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