1/* GIO - GLib Input, Output and Streaming Library
2 *
3 * Copyright 2016 Red Hat, Inc.
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, see
17 * <http://www.gnu.org/licenses/>.
18 */
19
20#include "config.h"
21
22#include "xdp-dbus.h"
23#include "giomodule-priv.h"
24#include "gportalsupport.h"
25#include "gproxyresolverportal.h"
26
27struct _GProxyResolverPortal {
28 GObject parent_instance;
29
30 GXdpProxyResolver *resolver;
31 gboolean network_available;
32};
33
34static void g_proxy_resolver_portal_iface_init (GProxyResolverInterface *iface);
35
36G_DEFINE_TYPE_WITH_CODE (GProxyResolverPortal, g_proxy_resolver_portal, G_TYPE_OBJECT,
37 G_IMPLEMENT_INTERFACE (G_TYPE_PROXY_RESOLVER,
38 g_proxy_resolver_portal_iface_init)
39 _g_io_modules_ensure_extension_points_registered ();
40 g_io_extension_point_implement (G_PROXY_RESOLVER_EXTENSION_POINT_NAME,
41 g_define_type_id,
42 "portal",
43 90))
44
45static gboolean
46ensure_resolver_proxy (GProxyResolverPortal *resolver)
47{
48 if (resolver->resolver)
49 return TRUE;
50
51 if (!glib_should_use_portal ())
52 return FALSE;
53
54 resolver->resolver = gxdp_proxy_resolver_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
55 G_DBUS_PROXY_FLAGS_NONE,
56 "org.freedesktop.portal.Desktop",
57 "/org/freedesktop/portal/desktop",
58 NULL,
59 NULL);
60
61 resolver->network_available = glib_network_available_in_sandbox ();
62
63 return resolver->resolver != NULL;
64}
65
66static void
67g_proxy_resolver_portal_init (GProxyResolverPortal *resolver)
68{
69}
70
71static gboolean
72g_proxy_resolver_portal_is_supported (GProxyResolver *object)
73{
74 GProxyResolverPortal *resolver = G_PROXY_RESOLVER_PORTAL (object);
75 char *name_owner;
76 gboolean has_portal;
77
78 if (!ensure_resolver_proxy (resolver))
79 return FALSE;
80
81 name_owner = g_dbus_proxy_get_name_owner (G_DBUS_PROXY (resolver->resolver));
82 has_portal = name_owner != NULL;
83 g_free (mem: name_owner);
84
85 return has_portal;
86}
87
88static const char *no_proxy[2] = { "direct://", NULL };
89
90static gchar **
91g_proxy_resolver_portal_lookup (GProxyResolver *proxy_resolver,
92 const gchar *uri,
93 GCancellable *cancellable,
94 GError **error)
95{
96 GProxyResolverPortal *resolver = G_PROXY_RESOLVER_PORTAL (proxy_resolver);
97 char **proxy = NULL;
98
99 ensure_resolver_proxy (resolver);
100 g_assert (resolver->resolver);
101
102 if (!gxdp_proxy_resolver_call_lookup_sync (resolver->resolver,
103 uri,
104 &proxy,
105 cancellable,
106 error))
107 return NULL;
108
109 if (!resolver->network_available)
110 {
111 g_strfreev (str_array: proxy);
112 proxy = g_strdupv (str_array: (gchar **)no_proxy);
113 }
114
115 return proxy;
116}
117
118static void
119lookup_done (GObject *source,
120 GAsyncResult *result,
121 gpointer data)
122{
123 GTask *task = data;
124 GError *error = NULL;
125 gchar **proxies = NULL;
126
127 if (!gxdp_proxy_resolver_call_lookup_finish (GXDP_PROXY_RESOLVER (source),
128 &proxies,
129 result,
130 &error))
131 g_task_return_error (task, error);
132 else
133 g_task_return_pointer (task, result: proxies, NULL);
134
135 g_object_unref (object: task);
136}
137
138static void
139g_proxy_resolver_portal_lookup_async (GProxyResolver *proxy_resolver,
140 const gchar *uri,
141 GCancellable *cancellable,
142 GAsyncReadyCallback callback,
143 gpointer user_data)
144{
145 GProxyResolverPortal *resolver = G_PROXY_RESOLVER_PORTAL (proxy_resolver);
146 GTask *task;
147
148 ensure_resolver_proxy (resolver);
149 g_assert (resolver->resolver);
150
151 task = g_task_new (source_object: proxy_resolver, cancellable, callback, callback_data: user_data);
152 gxdp_proxy_resolver_call_lookup (resolver->resolver,
153 uri,
154 cancellable,
155 lookup_done,
156 g_object_ref (task));
157 g_object_unref (object: task);
158}
159
160static gchar **
161g_proxy_resolver_portal_lookup_finish (GProxyResolver *proxy_resolver,
162 GAsyncResult *result,
163 GError **error)
164{
165 GProxyResolverPortal *resolver = G_PROXY_RESOLVER_PORTAL (proxy_resolver);
166 GTask *task = G_TASK (result);
167 char **proxies;
168
169 proxies = g_task_propagate_pointer (task, error);
170 if (proxies == NULL)
171 return NULL;
172
173 if (!resolver->network_available)
174 {
175 g_strfreev (str_array: proxies);
176 proxies = g_strdupv (str_array: (gchar **)no_proxy);
177 }
178
179 return proxies;
180}
181
182static void
183g_proxy_resolver_portal_finalize (GObject *object)
184{
185 GProxyResolverPortal *resolver = G_PROXY_RESOLVER_PORTAL (object);
186
187 g_clear_object (&resolver->resolver);
188
189 G_OBJECT_CLASS (g_proxy_resolver_portal_parent_class)->finalize (object);
190}
191
192static void
193g_proxy_resolver_portal_class_init (GProxyResolverPortalClass *resolver_class)
194{
195 GObjectClass *object_class;
196
197 object_class = G_OBJECT_CLASS (resolver_class);
198 object_class->finalize = g_proxy_resolver_portal_finalize;
199}
200
201static void
202g_proxy_resolver_portal_iface_init (GProxyResolverInterface *iface)
203{
204 iface->is_supported = g_proxy_resolver_portal_is_supported;
205 iface->lookup = g_proxy_resolver_portal_lookup;
206 iface->lookup_async = g_proxy_resolver_portal_lookup_async;
207 iface->lookup_finish = g_proxy_resolver_portal_lookup_finish;
208}
209

source code of gtk/subprojects/glib/gio/gproxyresolverportal.c