summaryrefslogtreecommitdiff
path: root/libsoup
diff options
context:
space:
mode:
authorDan Winship <danw@gnome.org>2010-06-07 16:45:22 -0400
committerDan Winship <danw@gnome.org>2010-12-09 12:04:51 +0100
commit65d5f29c527ab6da5991696026d6bdbef903d169 (patch)
tree0d7eeb16b8f63688b757ecb2323d653e8a40c053 /libsoup
parentf5a0053364adfa24014f0c595c3a2890d10e437c (diff)
downloadlibsoup-65d5f29c527ab6da5991696026d6bdbef903d169.tar.gz
SoupSession: allow features to implement "subfeatures"
Let soup_session_add_feature_by_type() (and remove()) add and remove "features" from existing features. Eg, to add/remove auth types or Content-Encodings.
Diffstat (limited to 'libsoup')
-rw-r--r--libsoup/soup-session-feature.c39
-rw-r--r--libsoup/soup-session-feature.h54
-rw-r--r--libsoup/soup-session.c66
3 files changed, 120 insertions, 39 deletions
diff --git a/libsoup/soup-session-feature.c b/libsoup/soup-session-feature.c
index f5d12393..1db9c204 100644
--- a/libsoup/soup-session-feature.c
+++ b/libsoup/soup-session-feature.c
@@ -164,3 +164,42 @@ soup_session_feature_detach (SoupSessionFeature *feature,
{
SOUP_SESSION_FEATURE_GET_CLASS (feature)->detach (feature, session);
}
+
+gboolean
+soup_session_feature_add_feature (SoupSessionFeature *feature,
+ GType type)
+{
+ SoupSessionFeatureInterface *feature_iface =
+ SOUP_SESSION_FEATURE_GET_CLASS (feature);
+
+ if (feature_iface->add_feature)
+ return feature_iface->add_feature (feature, type);
+ else
+ return FALSE;
+}
+
+gboolean
+soup_session_feature_remove_feature (SoupSessionFeature *feature,
+ GType type)
+{
+ SoupSessionFeatureInterface *feature_iface =
+ SOUP_SESSION_FEATURE_GET_CLASS (feature);
+
+ if (feature_iface->remove_feature)
+ return feature_iface->remove_feature (feature, type);
+ else
+ return FALSE;
+}
+
+gboolean
+soup_session_feature_has_feature (SoupSessionFeature *feature,
+ GType type)
+{
+ SoupSessionFeatureInterface *feature_iface =
+ SOUP_SESSION_FEATURE_GET_CLASS (feature);
+
+ if (feature_iface->has_feature)
+ return feature_iface->has_feature (feature, type);
+ else
+ return FALSE;
+}
diff --git a/libsoup/soup-session-feature.h b/libsoup/soup-session-feature.h
index 1db776ce..aa64aa0f 100644
--- a/libsoup/soup-session-feature.h
+++ b/libsoup/soup-session-feature.h
@@ -21,30 +21,44 @@ typedef struct {
GTypeInterface parent;
/* methods */
- void (*attach) (SoupSessionFeature *feature,
- SoupSession *session);
- void (*detach) (SoupSessionFeature *feature,
- SoupSession *session);
-
- void (*request_queued) (SoupSessionFeature *feature,
- SoupSession *session,
- SoupMessage *msg);
- void (*request_started) (SoupSessionFeature *feature,
- SoupSession *session,
- SoupMessage *msg,
- SoupSocket *socket);
- void (*request_unqueued) (SoupSessionFeature *feature,
- SoupSession *session,
- SoupMessage *msg);
+ void (*attach) (SoupSessionFeature *feature,
+ SoupSession *session);
+ void (*detach) (SoupSessionFeature *feature,
+ SoupSession *session);
+
+ void (*request_queued) (SoupSessionFeature *feature,
+ SoupSession *session,
+ SoupMessage *msg);
+ void (*request_started) (SoupSessionFeature *feature,
+ SoupSession *session,
+ SoupMessage *msg,
+ SoupSocket *socket);
+ void (*request_unqueued) (SoupSessionFeature *feature,
+ SoupSession *session,
+ SoupMessage *msg);
+
+ gboolean (*add_feature) (SoupSessionFeature *feature,
+ GType type);
+ gboolean (*remove_feature) (SoupSessionFeature *feature,
+ GType type);
+ gboolean (*has_feature) (SoupSessionFeature *feature,
+ GType type);
} SoupSessionFeatureInterface;
-GType soup_session_feature_get_type (void);
+GType soup_session_feature_get_type (void);
+
+void soup_session_feature_attach (SoupSessionFeature *feature,
+ SoupSession *session);
+void soup_session_feature_detach (SoupSessionFeature *feature,
+ SoupSession *session);
-void soup_session_feature_attach (SoupSessionFeature *feature,
- SoupSession *session);
-void soup_session_feature_detach (SoupSessionFeature *feature,
- SoupSession *session);
+gboolean soup_session_feature_add_feature (SoupSessionFeature *feature,
+ GType type);
+gboolean soup_session_feature_remove_feature (SoupSessionFeature *feature,
+ GType type);
+gboolean soup_session_feature_has_feature (SoupSessionFeature *feature,
+ GType type);
G_END_DECLS
diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c
index 1dbde5a8..ffefca8a 100644
--- a/libsoup/soup-session.c
+++ b/libsoup/soup-session.c
@@ -186,8 +186,10 @@ soup_session_init (SoupSession *session)
NULL);
g_signal_connect (auth_manager, "authenticate",
G_CALLBACK (auth_manager_authenticate), session);
- soup_auth_manager_add_type (auth_manager, SOUP_TYPE_AUTH_BASIC);
- soup_auth_manager_add_type (auth_manager, SOUP_TYPE_AUTH_DIGEST);
+ soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager),
+ SOUP_TYPE_AUTH_BASIC);
+ soup_session_feature_add_feature (SOUP_SESSION_FEATURE (auth_manager),
+ SOUP_TYPE_AUTH_DIGEST);
soup_session_add_feature (session, SOUP_SESSION_FEATURE (auth_manager));
g_object_unref (auth_manager);
@@ -1802,12 +1804,19 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature)
/**
* soup_session_add_feature_by_type:
* @session: a #SoupSession
- * @feature_type: the #GType of a class that implements #SoupSessionFeature
+ * @feature_type: a #GType
*
- * Creates a new feature of type @feature_type and adds it to
- * @session. You can use this instead of soup_session_add_feature() in
- * the case wher you don't need to customize the new feature in any
- * way. You can also add a feature to the session at construct time by
+ * If @feature_type is the type of a class that implements
+ * #SoupSessionFeature, this creates a new feature of that type and
+ * adds it to @session as with soup_session_add_feature(). You can use
+ * this when you don't need to customize the new feature in any way.
+ *
+ * If @feature_type is not a #SoupSessionFeature type, this gives
+ * each existing feature on @session the chance to accept @feature_type
+ * as a "subfeature". This can be used to add new #SoupAuth types,
+ * for instance.
+ *
+ * You can also add a feature to the session at construct time by
* using the %SOUP_SESSION_ADD_FEATURE_BY_TYPE property.
*
* Since: 2.24
@@ -1815,14 +1824,24 @@ soup_session_add_feature (SoupSession *session, SoupSessionFeature *feature)
void
soup_session_add_feature_by_type (SoupSession *session, GType feature_type)
{
- SoupSessionFeature *feature;
-
g_return_if_fail (SOUP_IS_SESSION (session));
- g_return_if_fail (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE));
- feature = g_object_new (feature_type, NULL);
- soup_session_add_feature (session, feature);
- g_object_unref (feature);
+ if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) {
+ SoupSessionFeature *feature;
+
+ feature = g_object_new (feature_type, NULL);
+ soup_session_add_feature (session, feature);
+ g_object_unref (feature);
+ } else {
+ SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session);
+ GSList *f;
+
+ for (f = priv->features; f; f = f->next) {
+ if (soup_session_feature_add_feature (f->data, feature_type))
+ return;
+ }
+ g_warning ("No feature manager for feature of type '%s'", g_type_name (feature_type));
+ }
}
/**
@@ -1853,7 +1872,7 @@ soup_session_remove_feature (SoupSession *session, SoupSessionFeature *feature)
/**
* soup_session_remove_feature_by_type:
* @session: a #SoupSession
- * @feature_type: the #GType of a class that implements #SoupSessionFeature
+ * @feature_type: a #GType
*
* Removes all features of type @feature_type (or any subclass of
* @feature_type) from @session. You can also remove standard features
@@ -1871,12 +1890,21 @@ soup_session_remove_feature_by_type (SoupSession *session, GType feature_type)
g_return_if_fail (SOUP_IS_SESSION (session));
priv = SOUP_SESSION_GET_PRIVATE (session);
-restart:
- for (f = priv->features; f; f = f->next) {
- if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) {
- soup_session_remove_feature (session, f->data);
- goto restart;
+
+ if (g_type_is_a (feature_type, SOUP_TYPE_SESSION_FEATURE)) {
+ restart:
+ for (f = priv->features; f; f = f->next) {
+ if (G_TYPE_CHECK_INSTANCE_TYPE (f->data, feature_type)) {
+ soup_session_remove_feature (session, f->data);
+ goto restart;
+ }
+ }
+ } else {
+ for (f = priv->features; f; f = f->next) {
+ if (soup_session_feature_remove_feature (f->data, feature_type))
+ return;
}
+ g_warning ("No feature manager for feature of type '%s'", g_type_name (feature_type));
}
}