• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
27 struct _GProxyResolverPortal {
28   GObject parent_instance;
29 
30   GXdpProxyResolver *resolver;
31   gboolean network_available;
32 };
33 
34 static void g_proxy_resolver_portal_iface_init (GProxyResolverInterface *iface);
35 
36 G_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 
45 static gboolean
ensure_resolver_proxy(GProxyResolverPortal * resolver)46 ensure_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 
66 static void
g_proxy_resolver_portal_init(GProxyResolverPortal * resolver)67 g_proxy_resolver_portal_init (GProxyResolverPortal *resolver)
68 {
69 }
70 
71 static gboolean
g_proxy_resolver_portal_is_supported(GProxyResolver * object)72 g_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 (name_owner);
84 
85   return has_portal;
86 }
87 
88 static const char *no_proxy[2] = { "direct://", NULL };
89 
90 static gchar **
g_proxy_resolver_portal_lookup(GProxyResolver * proxy_resolver,const gchar * uri,GCancellable * cancellable,GError ** error)91 g_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 (proxy);
112       proxy = g_strdupv ((gchar **)no_proxy);
113     }
114 
115   return proxy;
116 }
117 
118 static void
lookup_done(GObject * source,GAsyncResult * result,gpointer data)119 lookup_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, proxies, NULL);
134 
135   g_object_unref (task);
136 }
137 
138 static void
g_proxy_resolver_portal_lookup_async(GProxyResolver * proxy_resolver,const gchar * uri,GCancellable * cancellable,GAsyncReadyCallback callback,gpointer user_data)139 g_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 (proxy_resolver, cancellable, callback, 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 (task);
158 }
159 
160 static gchar **
g_proxy_resolver_portal_lookup_finish(GProxyResolver * proxy_resolver,GAsyncResult * result,GError ** error)161 g_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 (proxies);
176       proxies = g_strdupv ((gchar **)no_proxy);
177     }
178 
179   return proxies;
180 }
181 
182 static void
g_proxy_resolver_portal_finalize(GObject * object)183 g_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 
192 static void
g_proxy_resolver_portal_class_init(GProxyResolverPortalClass * resolver_class)193 g_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 
201 static void
g_proxy_resolver_portal_iface_init(GProxyResolverInterface * iface)202 g_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