1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-session-feature.c: Miscellaneous session feature-provider interface
5 * Copyright (C) 2008 Red Hat, Inc.
12 #include "soup-session-feature.h"
13 #include "soup-message-private.h"
16 * SECTION:soup-session-feature
17 * @short_description: Interface for miscellaneous session features
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.)
25 * See soup_session_add_feature(), etc, to add a feature to a session.
31 * An object that implement some sort of optional feature for
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 * @add_feature: adds a sub-feature to the main feature
46 * @remove_feature: removes a sub-feature from the main feature
47 * @has_feature: tests if the feature includes a sub-feature
49 * The interface implemented by #SoupSessionFeature<!-- -->s.
54 static void soup_session_feature_interface_init (SoupSessionFeatureInterface *interface);
56 static void attach (SoupSessionFeature *feature, SoupSession *session);
57 static void detach (SoupSessionFeature *feature, SoupSession *session);
60 soup_session_feature_get_type (void)
62 static volatile gsize g_define_type_id__volatile = 0;
63 if (g_once_init_enter (&g_define_type_id__volatile))
65 GType g_define_type_id =
66 g_type_register_static_simple (G_TYPE_INTERFACE,
67 g_intern_static_string ("SoupSessionFeature"),
68 sizeof (SoupSessionFeatureInterface),
69 (GClassInitFunc)soup_session_feature_interface_init,
71 (GInstanceInitFunc)NULL,
73 g_type_interface_add_prerequisite (g_define_type_id, G_TYPE_OBJECT);
74 g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
76 return g_define_type_id__volatile;
80 soup_session_feature_interface_init (SoupSessionFeatureInterface *interface)
82 interface->attach = attach;
83 interface->detach = detach;
87 weak_notify_unref (gpointer feature, GObject *ex_object)
89 g_object_unref (feature);
93 request_queued (SoupSession *session, SoupMessage *msg, gpointer feature)
95 if (soup_message_disables_feature (msg, feature))
98 SOUP_SESSION_FEATURE_GET_CLASS (feature)->
99 request_queued (feature, session, msg);
103 request_started (SoupSession *session, SoupMessage *msg,
104 SoupSocket *socket, gpointer feature)
106 if (soup_message_disables_feature (msg, feature))
109 SOUP_SESSION_FEATURE_GET_CLASS (feature)->
110 request_started (feature, session, msg, socket);
114 request_unqueued (SoupSession *session, SoupMessage *msg, gpointer feature)
116 if (soup_message_disables_feature (msg, feature))
119 SOUP_SESSION_FEATURE_GET_CLASS (feature)->
120 request_unqueued (feature, session, msg);
124 attach (SoupSessionFeature *feature, SoupSession *session)
126 g_object_weak_ref (G_OBJECT (session),
127 weak_notify_unref, g_object_ref (feature));
129 if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_queued) {
130 g_signal_connect (session, "request_queued",
131 G_CALLBACK (request_queued), feature);
134 if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_started) {
135 g_signal_connect (session, "request_started",
136 G_CALLBACK (request_started), feature);
139 if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_unqueued) {
140 g_signal_connect (session, "request_unqueued",
141 G_CALLBACK (request_unqueued), feature);
146 soup_session_feature_attach (SoupSessionFeature *feature,
147 SoupSession *session)
149 SOUP_SESSION_FEATURE_GET_CLASS (feature)->attach (feature, session);
153 detach (SoupSessionFeature *feature, SoupSession *session)
155 g_object_weak_unref (G_OBJECT (session), weak_notify_unref, feature);
157 g_signal_handlers_disconnect_by_func (session, request_queued, feature);
158 g_signal_handlers_disconnect_by_func (session, request_started, feature);
159 g_signal_handlers_disconnect_by_func (session, request_unqueued, feature);
161 g_object_unref (feature);
165 soup_session_feature_detach (SoupSessionFeature *feature,
166 SoupSession *session)
168 SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session);
172 * soup_session_feature_add_feature:
173 * @feature: the "base" feature
174 * @type: the #GType of a "sub-feature"
176 * Adds a "sub-feature" of type @type to the base feature @feature.
177 * This is used for features that can be extended with multiple
178 * different types. Eg, the authentication manager can be extended
179 * with subtypes of #SoupAuth.
181 * Return value: %TRUE if @feature accepted @type as a subfeature.
186 soup_session_feature_add_feature (SoupSessionFeature *feature,
189 SoupSessionFeatureInterface *feature_iface =
190 SOUP_SESSION_FEATURE_GET_CLASS (feature);
192 if (feature_iface->add_feature)
193 return feature_iface->add_feature (feature, type);
199 * soup_session_feature_remove_feature:
200 * @feature: the "base" feature
201 * @type: the #GType of a "sub-feature"
203 * Removes the "sub-feature" of type @type from the base feature
204 * @feature. See soup_session_feature_add_feature().
206 * Return value: %TRUE if @type was removed from @feature
211 soup_session_feature_remove_feature (SoupSessionFeature *feature,
214 SoupSessionFeatureInterface *feature_iface =
215 SOUP_SESSION_FEATURE_GET_CLASS (feature);
217 if (feature_iface->remove_feature)
218 return feature_iface->remove_feature (feature, type);
224 * soup_session_feature_has_feature:
225 * @feature: the "base" feature
226 * @type: the #GType of a "sub-feature"
228 * Tests if @feature has a "sub-feature" of type @type. See
229 * soup_session_feature_add_feature().
231 * Return value: %TRUE if @feature has a subfeature of type @type
236 soup_session_feature_has_feature (SoupSessionFeature *feature,
239 SoupSessionFeatureInterface *feature_iface =
240 SOUP_SESSION_FEATURE_GET_CLASS (feature);
242 if (feature_iface->has_feature)
243 return feature_iface->has_feature (feature, type);