soup-auth-manager: add soup_auth_manager_use_auth()
[platform/upstream/libsoup.git] / libsoup / soup-session-feature.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-session-feature.c: Miscellaneous session feature-provider interface
4  *
5  * Copyright (C) 2008 Red Hat, Inc.
6  */
7
8 #ifdef HAVE_CONFIG_H
9 #include <config.h>
10 #endif
11
12 #include "soup-session-feature.h"
13 #include "soup.h"
14 #include "soup-message-private.h"
15
16 /**
17  * SECTION:soup-session-feature
18  * @short_description: Interface for miscellaneous session features
19  *
20  * #SoupSessionFeature is the interface used by classes that extend
21  * the functionality of a #SoupSession. Some features like HTTP
22  * authentication handling are implemented internally via
23  * #SoupSessionFeature<!-- -->s. Other features can be added to the session
24  * by the application. (Eg, #SoupLogger, #SoupCookieJar.)
25  *
26  * See soup_session_add_feature(), etc, to add a feature to a session.
27  **/
28
29 /**
30  * SoupSessionFeature:
31  *
32  * An object that implement some sort of optional feature for
33  * #SoupSession.
34  *
35  * Since: 2.24
36  **/
37
38 /**
39  * SoupSessionFeatureInterface:
40  * @parent: The parent interface.
41  * @attach: Perform setup when a feature is added to a session
42  * @detach: Perform cleanup when a feature is removed from a session
43  * @request_queued: Proxies the session's #SoupSession::request_queued signal
44  * @request_started: Proxies the session's #SoupSession::request_started signal
45  * @request_unqueued: Proxies the session's #SoupSession::request_unqueued signal
46  * @add_feature: adds a sub-feature to the main feature
47  * @remove_feature: removes a sub-feature from the main feature
48  * @has_feature: tests if the feature includes a sub-feature
49  *
50  * The interface implemented by #SoupSessionFeature<!-- -->s.
51  *
52  * Since: 2.24
53  **/
54
55 static void soup_session_feature_default_init (SoupSessionFeatureInterface *iface);
56
57 G_DEFINE_INTERFACE (SoupSessionFeature, soup_session_feature, G_TYPE_OBJECT)
58
59 static void
60 weak_notify_unref (gpointer feature, GObject *ex_object)
61 {
62         g_object_unref (feature);
63 }
64
65 static void
66 request_queued (SoupSession *session, SoupMessage *msg, gpointer feature)
67 {
68         if (soup_message_disables_feature (msg, feature))
69                 return;
70
71         SOUP_SESSION_FEATURE_GET_CLASS (feature)->
72                 request_queued (feature, session, msg);
73 }
74
75 static void
76 request_started (SoupSession *session, SoupMessage *msg,
77                  SoupSocket *socket, gpointer feature)
78 {
79         if (soup_message_disables_feature (msg, feature))
80                 return;
81
82         SOUP_SESSION_FEATURE_GET_CLASS (feature)->
83                 request_started (feature, session, msg, socket);
84 }
85
86 static void
87 request_unqueued (SoupSession *session, SoupMessage *msg, gpointer feature)
88 {
89         if (soup_message_disables_feature (msg, feature))
90                 return;
91
92         SOUP_SESSION_FEATURE_GET_CLASS (feature)->
93                 request_unqueued (feature, session, msg);
94 }
95
96 static void
97 soup_session_feature_real_attach (SoupSessionFeature *feature, SoupSession *session)
98 {
99         g_object_weak_ref (G_OBJECT (session),
100                            weak_notify_unref, g_object_ref (feature));
101
102         if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_queued) {
103                 g_signal_connect (session, "request_queued",
104                                   G_CALLBACK (request_queued), feature);
105         }
106
107         if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_started) {
108                 g_signal_connect (session, "request_started",
109                                   G_CALLBACK (request_started), feature);
110         }
111
112         if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_unqueued) {
113                 g_signal_connect (session, "request_unqueued",
114                                   G_CALLBACK (request_unqueued), feature);
115         }
116 }
117
118 void
119 soup_session_feature_attach (SoupSessionFeature *feature,
120                              SoupSession        *session)
121 {
122         SOUP_SESSION_FEATURE_GET_CLASS (feature)->attach (feature, session);
123 }
124
125 static void
126 soup_session_feature_real_detach (SoupSessionFeature *feature, SoupSession *session)
127 {
128         g_object_weak_unref (G_OBJECT (session), weak_notify_unref, feature);
129
130         g_signal_handlers_disconnect_by_func (session, request_queued, feature);
131         g_signal_handlers_disconnect_by_func (session, request_started, feature);
132         g_signal_handlers_disconnect_by_func (session, request_unqueued, feature);
133
134         g_object_unref (feature);
135 }
136
137 void
138 soup_session_feature_detach (SoupSessionFeature *feature,
139                              SoupSession        *session)
140 {
141         SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session);
142 }
143
144 static void
145 soup_session_feature_default_init (SoupSessionFeatureInterface *iface)
146 {
147         iface->attach = soup_session_feature_real_attach;
148         iface->detach = soup_session_feature_real_detach;
149 }
150
151 /**
152  * soup_session_feature_add_feature:
153  * @feature: the "base" feature
154  * @type: the #GType of a "sub-feature"
155  *
156  * Adds a "sub-feature" of type @type to the base feature @feature.
157  * This is used for features that can be extended with multiple
158  * different types. Eg, the authentication manager can be extended
159  * with subtypes of #SoupAuth.
160  *
161  * Return value: %TRUE if @feature accepted @type as a subfeature.
162  *
163  * Since: 2.34
164  */
165 gboolean
166 soup_session_feature_add_feature (SoupSessionFeature *feature,
167                                   GType               type)
168 {
169         SoupSessionFeatureInterface *feature_iface =
170               SOUP_SESSION_FEATURE_GET_CLASS (feature);
171
172         if (feature_iface->add_feature)
173                 return feature_iface->add_feature (feature, type);
174         else
175                 return FALSE;
176 }
177
178 /**
179  * soup_session_feature_remove_feature:
180  * @feature: the "base" feature
181  * @type: the #GType of a "sub-feature"
182  *
183  * Removes the "sub-feature" of type @type from the base feature
184  * @feature. See soup_session_feature_add_feature().
185  *
186  * Return value: %TRUE if @type was removed from @feature
187  *
188  * Since: 2.34
189  */
190 gboolean
191 soup_session_feature_remove_feature (SoupSessionFeature *feature,
192                                      GType               type)
193 {
194         SoupSessionFeatureInterface *feature_iface =
195               SOUP_SESSION_FEATURE_GET_CLASS (feature);
196
197         if (feature_iface->remove_feature)
198                 return feature_iface->remove_feature (feature, type);
199         else
200                 return FALSE;
201 }
202
203 /**
204  * soup_session_feature_has_feature:
205  * @feature: the "base" feature
206  * @type: the #GType of a "sub-feature"
207  *
208  * Tests if @feature has a "sub-feature" of type @type. See
209  * soup_session_feature_add_feature().
210  *
211  * Return value: %TRUE if @feature has a subfeature of type @type
212  *
213  * Since: 2.34
214  */
215 gboolean
216 soup_session_feature_has_feature (SoupSessionFeature *feature,
217                                   GType               type)
218 {
219         SoupSessionFeatureInterface *feature_iface =
220               SOUP_SESSION_FEATURE_GET_CLASS (feature);
221
222         if (feature_iface->has_feature)
223                 return feature_iface->has_feature (feature, type);
224         else
225                 return FALSE;
226 }