mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-25 23:16:14 +01:00
Add async variant of g_app_info_launch_default_for_uri
This is useful in the portalized case, when the portal may present an app chooser dialog to the user. https://bugzilla.gnome.org/show_bug.cgi?id=768752
This commit is contained in:
parent
f885c4dd0d
commit
c1e8f705dd
@ -1427,6 +1427,8 @@ g_app_info_get_default_for_uri_scheme
|
|||||||
g_app_info_get_fallback_for_type
|
g_app_info_get_fallback_for_type
|
||||||
g_app_info_get_recommended_for_type
|
g_app_info_get_recommended_for_type
|
||||||
g_app_info_launch_default_for_uri
|
g_app_info_launch_default_for_uri
|
||||||
|
g_app_info_launch_default_for_uri_async
|
||||||
|
g_app_info_launch_default_for_uri_finish
|
||||||
g_app_launch_context_setenv
|
g_app_launch_context_setenv
|
||||||
g_app_launch_context_unsetenv
|
g_app_launch_context_unsetenv
|
||||||
g_app_launch_context_get_environment
|
g_app_launch_context_get_environment
|
||||||
|
256
gio/gappinfo.c
256
gio/gappinfo.c
@ -36,7 +36,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SECTION:gappinfo
|
* SECTION:gappinfo
|
||||||
* @short_description: Application information and launch contexts
|
* @short_description: Application information and launch contexts
|
||||||
@ -678,20 +677,95 @@ g_app_info_should_show (GAppInfo *appinfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef G_OS_UNIX
|
#ifdef G_OS_UNIX
|
||||||
static gboolean
|
static void
|
||||||
launch_default_with_portal (const char *uri,
|
response_received (GDBusConnection *connection,
|
||||||
GAppLaunchContext *context,
|
const char *sender_name,
|
||||||
GError **error)
|
const char *object_path,
|
||||||
|
const char *interface_name,
|
||||||
|
const char *signal_name,
|
||||||
|
GVariant *parameters,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GTask *task = user_data;
|
||||||
|
guint32 response;
|
||||||
|
guint signal_id;
|
||||||
|
|
||||||
|
signal_id = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (task), "signal-id"));
|
||||||
|
g_dbus_connection_signal_unsubscribe (connection, signal_id);
|
||||||
|
|
||||||
|
g_variant_get (parameters, "(u@a{sv})", &response, NULL);
|
||||||
|
|
||||||
|
if (response == 0)
|
||||||
|
g_task_return_boolean (task, TRUE);
|
||||||
|
else if (response == 1)
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Launch cancelled");
|
||||||
|
else
|
||||||
|
g_task_return_new_error (task, G_IO_ERROR, G_IO_ERROR_FAILED, "Launch failed");
|
||||||
|
|
||||||
|
g_object_unref (task);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
open_uri_done (GObject *source,
|
||||||
|
GAsyncResult *result,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GDBusConnection *connection = G_DBUS_CONNECTION (source);
|
||||||
|
GTask *task = user_data;
|
||||||
|
GVariant *res;
|
||||||
|
GError *error = NULL;
|
||||||
|
const char *path;
|
||||||
|
guint signal_id;
|
||||||
|
|
||||||
|
res = g_dbus_connection_call_finish (connection, result, &error);
|
||||||
|
|
||||||
|
if (res == NULL)
|
||||||
|
{
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
g_object_unref (task);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_variant_get (res, "(&o)", &path);
|
||||||
|
|
||||||
|
signal_id =
|
||||||
|
g_dbus_connection_signal_subscribe (connection,
|
||||||
|
"org.freedesktop.portal.Desktop",
|
||||||
|
"org.freedesktop.portal.Request",
|
||||||
|
"Response",
|
||||||
|
path,
|
||||||
|
NULL,
|
||||||
|
G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE,
|
||||||
|
response_received,
|
||||||
|
task, NULL);
|
||||||
|
|
||||||
|
g_object_set_data (G_OBJECT (task), "signal-id", GINT_TO_POINTER (signal_id));
|
||||||
|
|
||||||
|
g_variant_unref (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
launch_default_with_portal_async (const char *uri,
|
||||||
|
GAppLaunchContext *context,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GDBusConnection *session_bus;
|
GDBusConnection *session_bus;
|
||||||
GVariantBuilder opt_builder;
|
GVariantBuilder opt_builder;
|
||||||
const char *parent_window = NULL;
|
const char *parent_window = NULL;
|
||||||
GFile *file;
|
GFile *file;
|
||||||
char *real_uri;
|
char *real_uri;
|
||||||
|
GTask *task;
|
||||||
|
GAsyncReadyCallback dbus_callback;
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
|
session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
|
||||||
if (session_bus == NULL)
|
if (session_bus == NULL)
|
||||||
return FALSE;
|
{
|
||||||
|
g_task_report_error (context, callback, user_data, NULL, error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (context && context->priv->envp)
|
if (context && context->priv->envp)
|
||||||
parent_window = g_environ_getenv (context->priv->envp, "PARENT_WINDOW_ID");
|
parent_window = g_environ_getenv (context->priv->envp, "PARENT_WINDOW_ID");
|
||||||
@ -702,16 +776,13 @@ launch_default_with_portal (const char *uri,
|
|||||||
|
|
||||||
if (g_file_is_native (file))
|
if (g_file_is_native (file))
|
||||||
{
|
{
|
||||||
GError *local_error = NULL;
|
real_uri = g_document_portal_add_document (file, &error);
|
||||||
|
|
||||||
real_uri = g_document_portal_add_document (file, &local_error);
|
|
||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
|
|
||||||
if (real_uri == NULL)
|
if (real_uri == NULL)
|
||||||
{
|
{
|
||||||
g_warning ("Can't register with document portal: %s", local_error->message);
|
g_task_report_error (context, callback, user_data, NULL, error);
|
||||||
g_propagate_error (error, local_error);
|
return;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -720,6 +791,17 @@ launch_default_with_portal (const char *uri,
|
|||||||
real_uri = g_strdup (uri);
|
real_uri = g_strdup (uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (callback)
|
||||||
|
{
|
||||||
|
task = g_task_new (context, cancellable, callback, user_data);
|
||||||
|
dbus_callback = open_uri_done;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
task = NULL;
|
||||||
|
dbus_callback = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
g_dbus_connection_call (session_bus,
|
g_dbus_connection_call (session_bus,
|
||||||
"org.freedesktop.portal.Desktop",
|
"org.freedesktop.portal.Desktop",
|
||||||
"/org/freedesktop/portal/desktop",
|
"/org/freedesktop/portal/desktop",
|
||||||
@ -732,46 +814,35 @@ launch_default_with_portal (const char *uri,
|
|||||||
NULL,
|
NULL,
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
G_MAXINT,
|
G_MAXINT,
|
||||||
NULL,
|
cancellable,
|
||||||
NULL,
|
dbus_callback,
|
||||||
NULL);
|
task);
|
||||||
|
|
||||||
g_dbus_connection_flush (session_bus, NULL, NULL, NULL);
|
g_dbus_connection_flush (session_bus, cancellable, NULL, NULL);
|
||||||
g_object_unref (session_bus);
|
g_object_unref (session_bus);
|
||||||
g_free (real_uri);
|
g_free (real_uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
launch_default_with_portal (const char *uri,
|
||||||
|
GAppLaunchContext *context,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
launch_default_with_portal_async (uri, context, NULL, NULL, NULL);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
static gboolean
|
||||||
* g_app_info_launch_default_for_uri:
|
launch_default_for_uri (const char *uri,
|
||||||
* @uri: the uri to show
|
GAppLaunchContext *context,
|
||||||
* @launch_context: (allow-none): an optional #GAppLaunchContext.
|
GError **error)
|
||||||
* @error: a #GError.
|
|
||||||
*
|
|
||||||
* Utility function that launches the default application
|
|
||||||
* registered to handle the specified uri. Synchronous I/O
|
|
||||||
* is done on the uri to detect the type of the file if
|
|
||||||
* required.
|
|
||||||
*
|
|
||||||
* Returns: %TRUE on success, %FALSE on error.
|
|
||||||
**/
|
|
||||||
gboolean
|
|
||||||
g_app_info_launch_default_for_uri (const char *uri,
|
|
||||||
GAppLaunchContext *launch_context,
|
|
||||||
GError **error)
|
|
||||||
{
|
{
|
||||||
char *uri_scheme;
|
char *uri_scheme;
|
||||||
GAppInfo *app_info = NULL;
|
GAppInfo *app_info = NULL;
|
||||||
GList l;
|
GList l;
|
||||||
gboolean res;
|
gboolean res;
|
||||||
|
|
||||||
#ifdef G_OS_UNIX
|
|
||||||
if (glib_should_use_portal ())
|
|
||||||
return launch_default_with_portal (uri, launch_context, error);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* g_file_query_default_handler() calls
|
/* g_file_query_default_handler() calls
|
||||||
* g_app_info_get_default_for_uri_scheme() too, but we have to do it
|
* g_app_info_get_default_for_uri_scheme() too, but we have to do it
|
||||||
* here anyway in case GFile can't parse @uri correctly.
|
* here anyway in case GFile can't parse @uri correctly.
|
||||||
@ -788,26 +859,111 @@ g_app_info_launch_default_for_uri (const char *uri,
|
|||||||
file = g_file_new_for_uri (uri);
|
file = g_file_new_for_uri (uri);
|
||||||
app_info = g_file_query_default_handler (file, NULL, error);
|
app_info = g_file_query_default_handler (file, NULL, error);
|
||||||
g_object_unref (file);
|
g_object_unref (file);
|
||||||
if (app_info == NULL)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* We still use the original @uri rather than calling
|
|
||||||
* g_file_get_uri(), because GFile might have modified the URI
|
|
||||||
* in ways we don't want (eg, removing the fragment identifier
|
|
||||||
* from a file: URI).
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (app_info == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
l.data = (char *)uri;
|
l.data = (char *)uri;
|
||||||
l.next = l.prev = NULL;
|
l.next = l.prev = NULL;
|
||||||
res = g_app_info_launch_uris (app_info, &l,
|
res = g_app_info_launch_uris (app_info, &l, context, error);
|
||||||
launch_context, error);
|
|
||||||
|
|
||||||
g_object_unref (app_info);
|
g_object_unref (app_info);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_app_info_launch_default_for_uri:
|
||||||
|
* @uri: the uri to show
|
||||||
|
* @launch_context: (allow-none): an optional #GAppLaunchContext
|
||||||
|
* @error: (nullable): return location for an error, or %NULL
|
||||||
|
*
|
||||||
|
* Utility function that launches the default application
|
||||||
|
* registered to handle the specified uri. Synchronous I/O
|
||||||
|
* is done on the uri to detect the type of the file if
|
||||||
|
* required.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE on success, %FALSE on error.
|
||||||
|
**/
|
||||||
|
gboolean
|
||||||
|
g_app_info_launch_default_for_uri (const char *uri,
|
||||||
|
GAppLaunchContext *launch_context,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
if (glib_should_use_portal ())
|
||||||
|
return launch_default_with_portal (uri, launch_context, error);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
return launch_default_for_uri (uri, launch_context, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_app_info_launch_default_for_uri_async:
|
||||||
|
* @uri: the uri to show
|
||||||
|
* @context: (allow-none): an optional #GAppLaunchContext
|
||||||
|
* cancellable: (allow-none): a #GCancellable
|
||||||
|
* @callback: (allow-none): a #GASyncReadyCallback to call when the request is done
|
||||||
|
* @user_data: (allow-none): data to pass to @callback
|
||||||
|
*
|
||||||
|
* Async version of g_app_info_launch_default_for_uri().
|
||||||
|
*
|
||||||
|
* This version is useful if you are interested in receiving
|
||||||
|
* error information in the case where the application is
|
||||||
|
* sandboxed and the portal may present an application chooser
|
||||||
|
* dialog to the user.
|
||||||
|
*
|
||||||
|
* Since: 2.50
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_app_info_launch_default_for_uri_async (const char *uri,
|
||||||
|
GAppLaunchContext *context,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
gboolean res;
|
||||||
|
GError *error = NULL;
|
||||||
|
GTask *task;
|
||||||
|
|
||||||
|
#ifdef G_OS_UNIX
|
||||||
|
if (glib_should_use_portal ())
|
||||||
|
{
|
||||||
|
launch_default_with_portal_async (uri, context, cancellable, callback, user_data);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
res = launch_default_for_uri (uri, context, &error);
|
||||||
|
|
||||||
|
task = g_task_new (context, cancellable, callback, user_data);
|
||||||
|
if (!res)
|
||||||
|
g_task_return_error (task, error);
|
||||||
|
else
|
||||||
|
g_task_return_boolean (task, TRUE);
|
||||||
|
|
||||||
|
g_object_unref (task);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_app_info_launch_default_for_uri_finish:
|
||||||
|
* @result: a #GAsyncResult
|
||||||
|
* @error: (nullable): return location for an error, or %NULL
|
||||||
|
*
|
||||||
|
* Finishes an asynchronous launch-default-for-uri operation.
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if the launch was successful, %FALSE if @error is set
|
||||||
|
*
|
||||||
|
* Since: 2.50
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
g_app_info_launch_default_for_uri_finish (GAsyncResult *result,
|
||||||
|
GError **error)
|
||||||
|
{
|
||||||
|
return g_task_propagate_boolean (G_TASK (result), error);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_app_info_can_delete:
|
* g_app_info_can_delete:
|
||||||
* @appinfo: a #GAppInfo
|
* @appinfo: a #GAppInfo
|
||||||
|
@ -230,6 +230,17 @@ gboolean g_app_info_launch_default_for_uri (const char *uri,
|
|||||||
GAppLaunchContext *launch_context,
|
GAppLaunchContext *launch_context,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
GLIB_AVAILABLE_IN_2_50
|
||||||
|
void g_app_info_launch_default_for_uri_async (const char *uri,
|
||||||
|
GAppLaunchContext *launch_context,
|
||||||
|
GCancellable *cancellable,
|
||||||
|
GAsyncReadyCallback callback,
|
||||||
|
gpointer user_data);
|
||||||
|
GLIB_AVAILABLE_IN_2_50
|
||||||
|
gboolean g_app_info_launch_default_for_uri_finish (GAsyncResult *result,
|
||||||
|
GError **error);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GAppLaunchContext:
|
* GAppLaunchContext:
|
||||||
*
|
*
|
||||||
|
Loading…
Reference in New Issue
Block a user