Git init
[profile/ivi/libsoup2.4.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-message-private.h"
14
15 /**
16  * SECTION:soup-session-feature
17  * @short_description: Interface for miscellaneous session features
18  *
19  * #SoupSessionFeature is the interface used by classes that extend
20  * the functionality of a #SoupSession. Some features like HTTP
21  * authentication handling are implemented internally via
22  * #SoupSessionFeature<!-- -->s. Other features can be added to the session
23  * by the application. (Eg, #SoupLogger, #SoupCookieJar.)
24  *
25  * See soup_session_add_feature(), etc, to add a feature to a session.
26  **/
27
28 /**
29  * SoupSessionFeature:
30  *
31  * An object that implement some sort of optional feature for
32  * #SoupSession.
33  *
34  * Since: 2.24
35  **/
36
37 /**
38  * SoupSessionFeatureInterface:
39  * @parent: The parent interface.
40  * @attach: Perform setup when a feature is added to a session
41  * @detach: Perform cleanup when a feature is removed from a session
42  * @request_queued: Proxies the session's #SoupSession::request_queued signal
43  * @request_started: Proxies the session's #SoupSession::request_started signal
44  * @request_unqueued: Proxies the session's #SoupSession::request_unqueued signal
45  *
46  * The interface implemented by #SoupSessionFeature<!-- -->s.
47  *
48  * Since: 2.24
49  **/
50
51 static void soup_session_feature_interface_init (SoupSessionFeatureInterface *interface);
52
53 static void attach (SoupSessionFeature *feature, SoupSession *session);
54 static void detach (SoupSessionFeature *feature, SoupSession *session);
55
56 GType
57 soup_session_feature_get_type (void)
58 {
59   static volatile gsize g_define_type_id__volatile = 0;
60   if (g_once_init_enter (&g_define_type_id__volatile))
61     {
62       GType g_define_type_id =
63         g_type_register_static_simple (G_TYPE_INTERFACE,
64                                        g_intern_static_string ("SoupSessionFeature"),
65                                        sizeof (SoupSessionFeatureInterface),
66                                        (GClassInitFunc)soup_session_feature_interface_init,
67                                        0,
68                                        (GInstanceInitFunc)NULL,
69                                        (GTypeFlags) 0);
70       g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
71       g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
72     }
73   return g_define_type_id__volatile;
74 }
75
76 static void
77 soup_session_feature_interface_init (SoupSessionFeatureInterface *interface)
78 {
79         interface->attach = attach;
80         interface->detach = detach;
81 }
82
83 static void
84 weak_notify_unref (gpointer feature, GObject *ex_object)
85 {
86         g_object_unref (feature);
87 }
88
89 static void
90 request_queued (SoupSession *session, SoupMessage *msg, gpointer feature)
91 {
92         if (soup_message_disables_feature (msg, feature))
93                 return;
94
95         SOUP_SESSION_FEATURE_GET_CLASS (feature)->
96                 request_queued (feature, session, msg);
97 }
98
99 static void
100 request_started (SoupSession *session, SoupMessage *msg,
101                  SoupSocket *socket, gpointer feature)
102 {
103         if (soup_message_disables_feature (msg, feature))
104                 return;
105
106         SOUP_SESSION_FEATURE_GET_CLASS (feature)->
107                 request_started (feature, session, msg, socket);
108 }
109
110 static void
111 request_unqueued (SoupSession *session, SoupMessage *msg, gpointer feature)
112 {
113         if (soup_message_disables_feature (msg, feature))
114                 return;
115
116         SOUP_SESSION_FEATURE_GET_CLASS (feature)->
117                 request_unqueued (feature, session, msg);
118 }
119
120 static void
121 attach (SoupSessionFeature *feature, SoupSession *session)
122 {
123         g_object_weak_ref (G_OBJECT (session),
124                            weak_notify_unref, g_object_ref (feature));
125
126         if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_queued) {
127                 g_signal_connect (session, "request_queued",
128                                   G_CALLBACK (request_queued), feature);
129         }
130
131         if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_started) {
132                 g_signal_connect (session, "request_started",
133                                   G_CALLBACK (request_started), feature);
134         }
135
136         if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_unqueued) {
137                 g_signal_connect (session, "request_unqueued",
138                                   G_CALLBACK (request_unqueued), feature);
139         }
140 }
141
142 void
143 soup_session_feature_attach (SoupSessionFeature *feature,
144                              SoupSession        *session)
145 {
146         SOUP_SESSION_FEATURE_GET_CLASS (feature)->attach (feature, session);
147 }
148
149 static void
150 detach (SoupSessionFeature *feature, SoupSession *session)
151 {
152         g_object_weak_unref (G_OBJECT (session), weak_notify_unref, feature);
153
154         g_signal_handlers_disconnect_by_func (session, request_queued, feature);
155         g_signal_handlers_disconnect_by_func (session, request_started, feature);
156         g_signal_handlers_disconnect_by_func (session, request_unqueued, feature);
157
158         g_object_unref (feature);
159 }
160
161 void
162 soup_session_feature_detach (SoupSessionFeature *feature,
163                              SoupSession        *session)
164 {
165         SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session);
166 }
167
168 /**
169  * soup_session_feature_add_feature:
170  * @feature: the "base" feature
171  * @type: the #GType of a "sub-feature"
172  *
173  * Adds a "sub-feature" of type @type to the base feature @feature.
174  * This is used for features that can be extended with multiple
175  * different types. Eg, the authentication manager can be extended
176  * with subtypes of #SoupAuth.
177  *
178  * Return value: %TRUE if @feature accepted @type as a subfeature.
179  *
180  * Since: 2.34
181  */
182 gboolean
183 soup_session_feature_add_feature (SoupSessionFeature *feature,
184                                   GType               type)
185 {
186         SoupSessionFeatureInterface *feature_iface =
187               SOUP_SESSION_FEATURE_GET_CLASS (feature);
188
189         if (feature_iface->add_feature)
190                 return feature_iface->add_feature (feature, type);
191         else
192                 return FALSE;
193 }
194
195 /**
196  * soup_session_feature_remove_feature:
197  * @feature: the "base" feature
198  * @type: the #GType of a "sub-feature"
199  *
200  * Removes the "sub-feature" of type @type from the base feature
201  * @feature. See soup_session_feature_add_feature().
202  *
203  * Return value: %TRUE if @type was removed from @feature
204  *
205  * Since: 2.34
206  */
207 gboolean
208 soup_session_feature_remove_feature (SoupSessionFeature *feature,
209                                      GType               type)
210 {
211         SoupSessionFeatureInterface *feature_iface =
212               SOUP_SESSION_FEATURE_GET_CLASS (feature);
213
214         if (feature_iface->remove_feature)
215                 return feature_iface->remove_feature (feature, type);
216         else
217                 return FALSE;
218 }
219
220 /**
221  * soup_session_feature_has_feature:
222  * @feature: the "base" feature
223  * @type: the #GType of a "sub-feature"
224  *
225  * Tests if @feature has a "sub-feature" of type @type. See
226  * soup_session_feature_add_feature().
227  *
228  * Return value: %TRUE if @feature has a subfeature of type @type
229  *
230  * Since: 2.34
231  */
232 gboolean
233 soup_session_feature_has_feature (SoupSessionFeature *feature,
234                                   GType               type)
235 {
236         SoupSessionFeatureInterface *feature_iface =
237               SOUP_SESSION_FEATURE_GET_CLASS (feature);
238
239         if (feature_iface->has_feature)
240                 return feature_iface->has_feature (feature, type);
241         else
242                 return FALSE;
243 }