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
46 * The interface implemented by #SoupSessionFeature<!-- -->s.
51 static void soup_session_feature_interface_init (SoupSessionFeatureInterface *interface);
53 static void attach (SoupSessionFeature *feature, SoupSession *session);
54 static void detach (SoupSessionFeature *feature, SoupSession *session);
57 soup_session_feature_get_type (void)
59 static volatile gsize g_define_type_id__volatile = 0;
60 if (g_once_init_enter (&g_define_type_id__volatile))
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,
68 (GInstanceInitFunc)NULL,
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);
73 return g_define_type_id__volatile;
77 soup_session_feature_interface_init (SoupSessionFeatureInterface *interface)
79 interface->attach = attach;
80 interface->detach = detach;
84 weak_notify_unref (gpointer feature, GObject *ex_object)
86 g_object_unref (feature);
90 request_queued (SoupSession *session, SoupMessage *msg, gpointer feature)
92 if (soup_message_disables_feature (msg, feature))
95 SOUP_SESSION_FEATURE_GET_CLASS (feature)->
96 request_queued (feature, session, msg);
100 request_started (SoupSession *session, SoupMessage *msg,
101 SoupSocket *socket, gpointer feature)
103 if (soup_message_disables_feature (msg, feature))
106 SOUP_SESSION_FEATURE_GET_CLASS (feature)->
107 request_started (feature, session, msg, socket);
111 request_unqueued (SoupSession *session, SoupMessage *msg, gpointer feature)
113 if (soup_message_disables_feature (msg, feature))
116 SOUP_SESSION_FEATURE_GET_CLASS (feature)->
117 request_unqueued (feature, session, msg);
121 attach (SoupSessionFeature *feature, SoupSession *session)
123 g_object_weak_ref (G_OBJECT (session),
124 weak_notify_unref, g_object_ref (feature));
126 if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_queued) {
127 g_signal_connect (session, "request_queued",
128 G_CALLBACK (request_queued), feature);
131 if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_started) {
132 g_signal_connect (session, "request_started",
133 G_CALLBACK (request_started), feature);
136 if (SOUP_SESSION_FEATURE_GET_CLASS (feature)->request_unqueued) {
137 g_signal_connect (session, "request_unqueued",
138 G_CALLBACK (request_unqueued), feature);
143 soup_session_feature_attach (SoupSessionFeature *feature,
144 SoupSession *session)
146 SOUP_SESSION_FEATURE_GET_CLASS (feature)->attach (feature, session);
150 detach (SoupSessionFeature *feature, SoupSession *session)
152 g_object_weak_unref (G_OBJECT (session), weak_notify_unref, feature);
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);
158 g_object_unref (feature);
162 soup_session_feature_detach (SoupSessionFeature *feature,
163 SoupSession *session)
165 SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session);
169 * soup_session_feature_add_feature:
170 * @feature: the "base" feature
171 * @type: the #GType of a "sub-feature"
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.
178 * Return value: %TRUE if @feature accepted @type as a subfeature.
183 soup_session_feature_add_feature (SoupSessionFeature *feature,
186 SoupSessionFeatureInterface *feature_iface =
187 SOUP_SESSION_FEATURE_GET_CLASS (feature);
189 if (feature_iface->add_feature)
190 return feature_iface->add_feature (feature, type);
196 * soup_session_feature_remove_feature:
197 * @feature: the "base" feature
198 * @type: the #GType of a "sub-feature"
200 * Removes the "sub-feature" of type @type from the base feature
201 * @feature. See soup_session_feature_add_feature().
203 * Return value: %TRUE if @type was removed from @feature
208 soup_session_feature_remove_feature (SoupSessionFeature *feature,
211 SoupSessionFeatureInterface *feature_iface =
212 SOUP_SESSION_FEATURE_GET_CLASS (feature);
214 if (feature_iface->remove_feature)
215 return feature_iface->remove_feature (feature, type);
221 * soup_session_feature_has_feature:
222 * @feature: the "base" feature
223 * @type: the #GType of a "sub-feature"
225 * Tests if @feature has a "sub-feature" of type @type. See
226 * soup_session_feature_add_feature().
228 * Return value: %TRUE if @feature has a subfeature of type @type
233 soup_session_feature_has_feature (SoupSessionFeature *feature,
236 SoupSessionFeatureInterface *feature_iface =
237 SOUP_SESSION_FEATURE_GET_CLASS (feature);
239 if (feature_iface->has_feature)
240 return feature_iface->has_feature (feature, type);