mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 07:26:15 +01:00
Merge branch 'amolenaar/macos-launch-uris-async' into 'main'
macos: Implement GAppInfo launch_uris_async interface Closes #3403 See merge request GNOME/glib!4129
This commit is contained in:
commit
c5e17bc37f
@ -28,6 +28,7 @@
|
||||
#include "gfile.h"
|
||||
#include "gfileicon.h"
|
||||
#include "gioerror.h"
|
||||
#include "gtask.h"
|
||||
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
@ -271,38 +272,26 @@ create_url_list_from_glist (GList *uris,
|
||||
return (CFArrayRef)array;
|
||||
}
|
||||
|
||||
static LSLaunchURLSpec *
|
||||
create_urlspec_for_appinfo (GOsxAppInfo *info,
|
||||
static void
|
||||
fill_urlspec_for_appinfo (LSLaunchURLSpec *urlspec,
|
||||
GOsxAppInfo *info,
|
||||
GList *uris,
|
||||
gboolean are_files)
|
||||
{
|
||||
LSLaunchURLSpec *urlspec = NULL;
|
||||
const gchar *app_cstr;
|
||||
|
||||
g_return_val_if_fail (G_IS_OSX_APP_INFO (info), NULL);
|
||||
|
||||
urlspec = g_new0 (LSLaunchURLSpec, 1);
|
||||
app_cstr = g_osx_app_info_get_filename (info);
|
||||
g_assert (app_cstr != NULL);
|
||||
|
||||
/* Strip file:// from app url but ensure filesystem url */
|
||||
urlspec->appURL = create_url_from_cstr (app_cstr + strlen ("file://"), TRUE);
|
||||
urlspec->launchFlags = kLSLaunchDefaults;
|
||||
urlspec->appURL = (CFURLRef) [NSURL fileURLWithPath:[info->bundle bundlePath]];
|
||||
urlspec->itemURLs = create_url_list_from_glist (uris, are_files);
|
||||
|
||||
return urlspec;
|
||||
urlspec->launchFlags = kLSLaunchDefaults;
|
||||
}
|
||||
|
||||
static void
|
||||
free_urlspec (LSLaunchURLSpec *urlspec)
|
||||
clear_urlspec (LSLaunchURLSpec *urlspec)
|
||||
{
|
||||
if (urlspec->itemURLs)
|
||||
{
|
||||
CFArrayRemoveAllValues ((CFMutableArrayRef)urlspec->itemURLs);
|
||||
CFArrayRemoveAllValues ((CFMutableArrayRef) urlspec->itemURLs);
|
||||
CFRelease (urlspec->itemURLs);
|
||||
}
|
||||
CFRelease (urlspec->appURL);
|
||||
g_free (urlspec);
|
||||
}
|
||||
|
||||
static NSBundle *
|
||||
@ -463,15 +452,16 @@ g_osx_app_info_launch_internal (GAppInfo *appinfo,
|
||||
GError **error)
|
||||
{
|
||||
GOsxAppInfo *info = G_OSX_APP_INFO (appinfo);
|
||||
LSLaunchURLSpec *urlspec;
|
||||
LSLaunchURLSpec urlspec = { 0 };
|
||||
gint ret, success = TRUE;
|
||||
|
||||
g_return_val_if_fail (G_IS_OSX_APP_INFO (appinfo), FALSE);
|
||||
g_return_val_if_fail (uris == NULL, FALSE);
|
||||
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
||||
|
||||
urlspec = create_urlspec_for_appinfo (info, uris, are_files);
|
||||
fill_urlspec_for_appinfo (&urlspec, info, uris, are_files);
|
||||
|
||||
if ((ret = LSOpenFromURLSpec (urlspec, NULL)))
|
||||
if ((ret = LSOpenFromURLSpec (&urlspec, NULL)))
|
||||
{
|
||||
/* TODO: Better error codes */
|
||||
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
||||
@ -479,7 +469,7 @@ g_osx_app_info_launch_internal (GAppInfo *appinfo,
|
||||
success = FALSE;
|
||||
}
|
||||
|
||||
free_urlspec (urlspec);
|
||||
clear_urlspec (&urlspec);
|
||||
return success;
|
||||
}
|
||||
|
||||
@ -513,6 +503,72 @@ g_osx_app_info_launch_uris (GAppInfo *appinfo,
|
||||
return g_osx_app_info_launch_internal (appinfo, uris, FALSE, error);
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GList *uris; /* (element-type utf8) (owned) (nullable) */
|
||||
GAppLaunchContext *context; /* (owned) (nullable) */
|
||||
} LaunchUrisData;
|
||||
|
||||
static void
|
||||
launch_uris_data_free (LaunchUrisData *data)
|
||||
{
|
||||
g_clear_object (&data->context);
|
||||
g_list_free_full (data->uris, g_free);
|
||||
g_free (data);
|
||||
}
|
||||
|
||||
static void
|
||||
launch_uris_async_thread (GTask *task,
|
||||
gpointer source_object,
|
||||
gpointer task_data,
|
||||
GCancellable *cancellable)
|
||||
{
|
||||
GAppInfo *appinfo = G_APP_INFO (source_object);
|
||||
LaunchUrisData *data = task_data;
|
||||
GError *local_error = NULL;
|
||||
gboolean succeeded;
|
||||
|
||||
succeeded = g_osx_app_info_launch_internal (appinfo, data->uris, FALSE, &local_error);
|
||||
|
||||
if (local_error != NULL)
|
||||
g_task_return_error (task, g_steal_pointer (&local_error));
|
||||
else
|
||||
g_task_return_boolean (task, succeeded);
|
||||
}
|
||||
|
||||
static void
|
||||
g_osx_app_info_launch_uris_async (GAppInfo *appinfo,
|
||||
GList *uris,
|
||||
GAppLaunchContext *context,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
GTask *task;
|
||||
LaunchUrisData *data;
|
||||
|
||||
task = g_task_new (appinfo, cancellable, callback, user_data);
|
||||
g_task_set_source_tag (task, g_osx_app_info_launch_uris_async);
|
||||
|
||||
data = g_new0 (LaunchUrisData, 1);
|
||||
data->uris = g_list_copy_deep (uris, (GCopyFunc) g_strdup, NULL);
|
||||
g_set_object (&data->context, context);
|
||||
g_task_set_task_data (task, g_steal_pointer (&data), (GDestroyNotify) launch_uris_data_free);
|
||||
|
||||
g_task_run_in_thread (task, launch_uris_async_thread);
|
||||
g_object_unref (task);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_osx_app_info_launch_uris_finish (GAppInfo *appinfo,
|
||||
GAsyncResult *result,
|
||||
GError **error)
|
||||
{
|
||||
g_return_val_if_fail (g_task_is_valid (result, appinfo), FALSE);
|
||||
|
||||
return g_task_propagate_boolean (G_TASK (result), error);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
g_osx_app_info_should_show (GAppInfo *appinfo)
|
||||
{
|
||||
@ -570,7 +626,8 @@ g_osx_app_info_iface_init (GAppInfoIface *iface)
|
||||
|
||||
iface->launch = g_osx_app_info_launch;
|
||||
iface->launch_uris = g_osx_app_info_launch_uris;
|
||||
|
||||
iface->launch_uris_async = g_osx_app_info_launch_uris_async;
|
||||
iface->launch_uris_finish = g_osx_app_info_launch_uris_finish;
|
||||
iface->supports_uris = g_osx_app_info_supports_uris;
|
||||
iface->supports_files = g_osx_app_info_supports_files;
|
||||
iface->should_show = g_osx_app_info_should_show;
|
||||
@ -743,7 +800,7 @@ g_app_info_get_default_for_uri_scheme_impl (const char *uri_scheme)
|
||||
|
||||
if (!bundle_id)
|
||||
{
|
||||
g_warning ("No default handler found for url scheme '%s'.", uri_scheme);
|
||||
g_info ("No default handler found for url scheme '%s'.", uri_scheme);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -153,6 +153,12 @@ gio_tests = {
|
||||
'win32-appinfo' : {},
|
||||
}
|
||||
|
||||
if glib_have_cocoa
|
||||
gio_tests += {
|
||||
'osx-appinfo' : {}
|
||||
}
|
||||
endif
|
||||
|
||||
if have_cxx
|
||||
gio_tests += {
|
||||
'cxx' : {
|
||||
|
87
gio/tests/osx-appinfo.c
Normal file
87
gio/tests/osx-appinfo.c
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright (C) 2024 GNOME Foundation
|
||||
* Copyright (C) 2024 Arjan Molenaar
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General
|
||||
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gio/gio.h>
|
||||
#include <gio/gosxappinfo.h>
|
||||
|
||||
|
||||
static void
|
||||
async_result_cb (GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
gpointer user_data)
|
||||
{
|
||||
GAsyncResult **result_out = user_data;
|
||||
|
||||
g_assert (*result_out == NULL);
|
||||
*result_out = g_object_ref (result);
|
||||
g_main_context_wakeup (g_main_context_get_thread_default ());
|
||||
}
|
||||
|
||||
static void
|
||||
test_launch_async (void)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
GAppLaunchContext *context;
|
||||
GAsyncResult *result = NULL;
|
||||
GError *error = NULL;
|
||||
|
||||
app_info = g_app_info_get_default_for_uri_scheme ("file");
|
||||
g_assert_nonnull (app_info);
|
||||
g_assert_true (G_IS_OSX_APP_INFO (app_info));
|
||||
|
||||
context = g_app_launch_context_new ();
|
||||
|
||||
g_app_info_launch_uris_async (G_APP_INFO (app_info), NULL, context, NULL, async_result_cb, &result);
|
||||
|
||||
while (result == NULL)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
// Locally, the result is TRUE, but in CI it's FALSE, due to the absense of a GUI(?)
|
||||
if (g_app_info_launch_uris_finish (G_APP_INFO (app_info), result, &error))
|
||||
g_assert_no_error (error);
|
||||
else
|
||||
g_assert_error (error, G_IO_ERROR, G_IO_ERROR_FAILED);
|
||||
|
||||
g_clear_error (&error);
|
||||
g_clear_object (&result);
|
||||
g_clear_object (&context);
|
||||
g_clear_object (&app_info);
|
||||
}
|
||||
|
||||
static void
|
||||
test_invalid_uri_scheme (void)
|
||||
{
|
||||
GAppInfo *app_info;
|
||||
|
||||
app_info = g_app_info_get_default_for_uri_scheme ("thisisnotanurlscheme");
|
||||
g_assert_null (app_info);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
{
|
||||
g_test_init (&argc, &argv, NULL, NULL);
|
||||
|
||||
g_test_add_func ("/osx-app-info/launch-async", test_launch_async);
|
||||
g_test_add_func ("/osx-app-info/invalid-uri-scheme", test_invalid_uri_scheme);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user