fixed typo enable_sqllite -> enable_sqlite
[platform/upstream/libsoup.git] / libsoup / soup-proxy-resolver-default.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-proxy-resolver-default.c: proxy resolution based on GIO's GProxyResolver
4  *
5  * Copyright (C) 2011 Collabora Ltd.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #undef SOUP_VERSION_MIN_REQUIRED
13 #define SOUP_VERSION_MIN_REQUIRED SOUP_VERSION_2_42
14
15 #include "soup-proxy-resolver-default.h"
16 #include "soup.h"
17
18 /**
19  * SECTION:soup-proxy-resolver-default
20  * @short_description: System proxy configuration integration
21  *
22  * #SoupProxyResolverDefault is a <type>SoupProxyURIResolver</type>
23  * implementation that uses the default gio #GProxyResolver to resolve
24  * proxies.
25  *
26  * In libsoup 2.44 and later, you can set the session's
27  * #SoupSession:proxy-resolver property to the resolver returned by
28  * g_proxy_resolver_get_default() to get the same effect. Note that
29  * for "plain" #SoupSessions (ie, not #SoupSessionAsync or
30  * #SoupSessionSync), this is done for you automatically.
31  *
32  * Since: 2.34
33  *
34  * Deprecated: Use #SoupSession:proxy-resolver
35  */
36
37 static void soup_proxy_resolver_default_interface_init (SoupProxyURIResolverInterface *proxy_resolver_interface);
38
39 G_DEFINE_TYPE_EXTENDED (SoupProxyResolverDefault, soup_proxy_resolver_default, G_TYPE_OBJECT, 0,
40                         G_IMPLEMENT_INTERFACE (SOUP_TYPE_SESSION_FEATURE, NULL)
41                         G_IMPLEMENT_INTERFACE (SOUP_TYPE_PROXY_URI_RESOLVER, soup_proxy_resolver_default_interface_init))
42
43 enum {
44         PROP_0,
45         PROP_GPROXY_RESOLVER
46 };
47
48 typedef struct {
49         GProxyResolver *gproxy_resolver;
50 } SoupProxyResolverDefaultPrivate;
51 #define SOUP_PROXY_RESOLVER_DEFAULT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), SOUP_TYPE_PROXY_RESOLVER_DEFAULT, SoupProxyResolverDefaultPrivate))
52
53 static void
54 soup_proxy_resolver_default_init (SoupProxyResolverDefault *resolver)
55 {
56 }
57
58 static void
59 soup_proxy_resolver_default_set_property (GObject *object, guint prop_id,
60                                           const GValue *value, GParamSpec *pspec)
61 {
62         SoupProxyResolverDefaultPrivate *priv = SOUP_PROXY_RESOLVER_DEFAULT_GET_PRIVATE (object);
63
64         switch (prop_id) {
65         case PROP_GPROXY_RESOLVER:
66                 if (priv->gproxy_resolver)
67                         g_object_unref (priv->gproxy_resolver);
68                 priv->gproxy_resolver = g_value_dup_object (value);
69                 break;
70         default:
71                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
72                 break;
73         }
74 }
75
76 static void
77 soup_proxy_resolver_default_constructed (GObject *object)
78 {
79         SoupProxyResolverDefaultPrivate *priv = SOUP_PROXY_RESOLVER_DEFAULT_GET_PRIVATE (object);
80
81         if (!priv->gproxy_resolver) {
82                 priv->gproxy_resolver = g_proxy_resolver_get_default ();
83                 g_object_ref (priv->gproxy_resolver);
84         }
85
86         G_OBJECT_CLASS (soup_proxy_resolver_default_parent_class)->constructed (object);
87 }
88
89 static void
90 soup_proxy_resolver_default_finalize (GObject *object)
91 {
92         SoupProxyResolverDefaultPrivate *priv = SOUP_PROXY_RESOLVER_DEFAULT_GET_PRIVATE (object);
93
94         g_clear_object (&priv->gproxy_resolver);
95
96         G_OBJECT_CLASS (soup_proxy_resolver_default_parent_class)->finalize (object);
97 }
98
99 static void
100 soup_proxy_resolver_default_class_init (SoupProxyResolverDefaultClass *klass)
101 {
102         GObjectClass *object_class = G_OBJECT_CLASS (klass);
103
104         g_type_class_add_private (klass, sizeof (SoupProxyResolverDefaultPrivate));
105
106         object_class->set_property = soup_proxy_resolver_default_set_property;
107         object_class->constructed = soup_proxy_resolver_default_constructed;
108         object_class->finalize = soup_proxy_resolver_default_finalize;
109
110         g_object_class_install_property (
111                 object_class, PROP_GPROXY_RESOLVER,
112                 g_param_spec_object ("gproxy-resolver",
113                                      "GProxyResolver",
114                                      "The underlying GProxyResolver",
115                                      G_TYPE_PROXY_RESOLVER,
116                                      G_PARAM_WRITABLE));
117 }
118
119 typedef struct {
120         SoupProxyURIResolver *resolver;
121         GCancellable *cancellable;
122         SoupProxyURIResolverCallback callback;
123         gpointer user_data;
124 } SoupAsyncData;
125
126 static void
127 resolved_proxy (GObject *object, GAsyncResult *result, gpointer data)
128 {
129         GProxyResolver *proxy_resolver = G_PROXY_RESOLVER (object);
130         SoupAsyncData *async_data = data;
131         GError *error = NULL;
132         char **proxy_uris = NULL;
133         SoupURI *proxy_uri = NULL;
134         guint status = SOUP_STATUS_OK;
135
136         proxy_uris = g_proxy_resolver_lookup_finish (proxy_resolver,
137                                                      result,
138                                                      &error);
139
140         if (error || proxy_uris == NULL || proxy_uris[0] == NULL) {
141                 status = SOUP_STATUS_CANT_RESOLVE_PROXY;
142                 goto finish;
143         }
144
145         /* We need to handle direct:// specially, otherwise
146          * SoupSession will try to resolve it as the proxy address.
147          */
148         if (!g_strcmp0 (proxy_uris[0], "direct://"))
149                 goto finish;
150
151         proxy_uri = soup_uri_new (proxy_uris[0]);
152         if (proxy_uri == NULL)
153                 status = SOUP_STATUS_CANT_RESOLVE_PROXY;
154
155 finish:
156         async_data->callback (async_data->resolver,
157                               status,
158                               proxy_uri,
159                               async_data->user_data);
160
161         if (async_data->cancellable)
162                 g_object_unref (async_data->cancellable);
163
164         g_strfreev (proxy_uris);
165
166         if (proxy_uri)
167                 soup_uri_free (proxy_uri);
168
169         g_object_unref (async_data->resolver);
170         g_slice_free (SoupAsyncData, async_data);
171 }
172
173 static void
174 get_proxy_uri_async (SoupProxyURIResolver  *resolver,
175                      SoupURI               *uri,
176                      GMainContext          *async_context,
177                      GCancellable          *cancellable,
178                      SoupProxyURIResolverCallback callback,
179                      gpointer               user_data)
180 {
181         SoupProxyResolverDefaultPrivate *priv = SOUP_PROXY_RESOLVER_DEFAULT_GET_PRIVATE (resolver);
182         SoupAsyncData *async_data;
183         char *uri_string;
184
185         async_data = g_slice_new0 (SoupAsyncData);
186         async_data->resolver = (SoupProxyURIResolver*) g_object_ref (resolver);
187         async_data->cancellable = cancellable;
188         async_data->callback = callback;
189         async_data->user_data = user_data;
190
191         uri_string = soup_uri_to_string (uri, FALSE);
192
193         if (async_context)
194                 g_main_context_push_thread_default (async_context);
195
196         g_proxy_resolver_lookup_async (priv->gproxy_resolver,
197                                        uri_string,
198                                        cancellable ? g_object_ref (cancellable) : NULL,
199                                        resolved_proxy,
200                                        async_data);
201
202         if (async_context)
203                 g_main_context_pop_thread_default (async_context);
204
205         g_free (uri_string);
206 }
207
208 static guint
209 get_proxy_uri_sync (SoupProxyURIResolver  *resolver,
210                     SoupURI               *uri,
211                     GCancellable          *cancellable,
212                     SoupURI              **proxy_uri)
213 {
214         SoupProxyResolverDefaultPrivate *priv = SOUP_PROXY_RESOLVER_DEFAULT_GET_PRIVATE (resolver);
215         GError *error = NULL;
216         char** proxy_uris = NULL;
217         char *uri_string;
218         guint status = SOUP_STATUS_OK;
219
220         uri_string = soup_uri_to_string (uri, FALSE);
221
222         proxy_uris = g_proxy_resolver_lookup (priv->gproxy_resolver,
223                                               uri_string,
224                                               cancellable,
225                                               &error);
226
227         g_free (uri_string);
228
229         if (error || proxy_uris == NULL || proxy_uris[0] == NULL) {
230                 status = SOUP_STATUS_CANT_RESOLVE_PROXY;
231                 goto cleanup;
232         }
233
234         /* We need to handle direct:// specially, otherwise
235          * SoupSession will try to resolve it as the proxy address.
236          */
237         if (!g_strcmp0 (proxy_uris[0], "direct://"))
238                 goto cleanup;
239
240         *proxy_uri = soup_uri_new (proxy_uris[0]);
241
242         if (!*proxy_uri)
243                 status = SOUP_STATUS_CANT_RESOLVE_PROXY;
244
245 cleanup:
246         g_strfreev (proxy_uris);
247         if (error)
248                 g_clear_error (&error);
249         return status;
250 }
251
252 static void
253 soup_proxy_resolver_default_interface_init (SoupProxyURIResolverInterface *iface)
254 {
255         iface->get_proxy_uri_async = get_proxy_uri_async;
256         iface->get_proxy_uri_sync = get_proxy_uri_sync;
257 }